fix(python-sdk): handle anyOf(string, array<file>) for file_uploadable#3353
Draft
abhishekpatil4 wants to merge 1 commit into
Draft
fix(python-sdk): handle anyOf(string, array<file>) for file_uploadable#3353abhishekpatil4 wants to merge 1 commit into
abhishekpatil4 wants to merge 1 commit into
Conversation
When a tool's `file_uploadable` parameter has an `anyOf` accepting both a
single path and an array of paths (e.g. the new `GMAIL_SEND_EMAIL`
`attachment` schema), the model often picks the array branch and sends
`["/p1", "/p2", "/p3"]`. The SDK previously always returned the first
matching anyOf variant from `_find_uploadable_schema_variant`, which is
the singular string variant, then called `FileUploadable.from_path` on
the list — crashing with:
argument should be a str or an os.PathLike object where __fspath__
returns a str, not 'list'
The variant picker is now value-aware: when called with a runtime
`value`, it prefers the variant whose JSON-Schema `type` matches the
value (`array` for lists, `string` for strings, `object` for dicts).
A new array-of-`file_uploadable` branch in `_substitute_file_uploads_recursively`
iterates the list and uploads each file, replacing the parameter with
`[{name, mimetype, s3key}, ...]`.
This unblocks Gmail multi-attachment, Slack multi-file upload, and any
other tool that exposes `anyOf(file, array<file>)`. Single-path callers
are unaffected because `_find_uploadable_schema_variant` falls back to
the first candidate when the value is `None` or doesn't match any
variant type.
Co-authored-by: Cursor <cursoragent@cursor.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Python SDK's
file_uploadableresolver was breaking on tools whose schema accepts both a single path and a list of paths (e.g. the newGMAIL_SEND_EMAIL.attachmentschema):When the model picked the array branch and sent
[\"/p1\", \"/p2\", \"/p3\"], the SDK always returned the first matchinganyOfvariant from_find_uploadable_schema_variant(the string one), then calledFileUploadable.from_path(file=<list>)and crashed with:This affects every tool exposing
anyOf(file, array<file>)— Gmail multi-attachment, SlackSLACK_UPLOAD_OR_CREATE_A_FILE_IN_SLACKwhen the model batches files into one call, etc.Fixes #
Changes
_find_uploadable_schema_variantis now value-aware. When a runtimevalueis passed in, it prefers theanyOf/oneOf/allOfvariant whose JSON-Schematypematches the value's Python type (arrayforlist,stringforstr,objectfordict). Falls back to first match if no value or no type match — preserves existing behavior for callers that passvalue=None.file_uploadablebranch in_substitute_file_uploads_recursively: when the picker returns an array variant whose items arefile_uploadable, iterate the list and upload each file viaFileUploadable.from_path, replacing the parameter with[{name, mimetype, s3key}, ...]. The existing security/allowlist/before-hook kwargs (sensitive_file_upload_protection,file_upload_path_deny_segments,file_upload_allowlist,before_file_upload) are threaded through to each upload.Type of change
How Has This Been Tested?
Repro before the fix:
Before:
GMAIL_SEND_EMAILonce withattachment=['/a.png','/b.jpg','/c.png']successful=falsewith\"argument should be a str or an os.PathLike object where __fspath__ returns a str, not 'list'\"After:
attachment=[{name, mimetype, s3key}, ...]to the backend executor.Manual verification done against
backend.composio.devwith the liveGMAIL_SEND_EMAILschema. Existing single-path call sites (attachment='/a.png') are unaffected because the picker still returns the string variant for non-list values.I'd like to add unit tests in
python/tests/test_auto_upload_download_files.pycovering both branches (single path vs list) before this leaves draft — happy to do that here or as a follow-up depending on what reviewers prefer.Checklist
Additional context
Originally surfaced while debugging a multi-attachment Gmail send. The toolkit-side
attachmentschema was already updated toanyOf(string<file>, array<file>); this PR fixes the matching SDK-side resolver so the new schema is actually usable end-to-end.Made with Cursor