2 Commits

Author SHA1 Message Date
Alberto Schiabel b1c6671b20 fix(py): send Content-Type on S3 PUTs and parse Content-Length (#4168)
This PR:
- fixes #4153
- supersedes https://github.com/ComposioHQ/composio/pull/4154 (fork PR
authored against a pre-#4146 tree; its tests patch `requests.put`, which
`upload()` no longer calls after #4146, so they fail on merge)
- adds `parse_content_length()` in `composio.utils.url_safety`, shared
by both URL fetch helpers (`_files.py::_fetch_file_from_url` and
`tool_router_session_files.py::_fetch_url_bytes`), so a
malformed/negative remote `Content-Length` degrades to unknown size
under the streamed byte count instead of raising a raw `ValueError`
- converges the file and bytes upload paths onto
`_upload_to_presigned_url()`: one PUT that sends the `Content-Type` the
presign request was signed with and raises `ErrorUploadingFile` carrying
the HTTP status (a 403 no longer collapses into a path-only error)
- single-sources the presign wire shape via
`_request_presigned_upload()`; `from_path()` forwards the exact mimetype
it minted, so signed and sent content types cannot drift
- mirrors the TypeScript SDK: `uploadFileToS3` funnels path/URL/File
inputs through one uploader that always sends `Content-Type` and throws
on non-2xx, and `readResponseBodyWithLimit` trusts `Content-Length` only
as a hint
- adds tests against the `safe_request` seam
(`test_file_upload_robustness.py`, plus one malformed-header case for
`RemoteFile.buffer()`)

## Context

Both defects in #4153 were symptoms of two parallel upload paths
drifting: the bytes path sent `Content-Type` and raised with the status,
the file path did neither. Patching the symptom in place (as #4154
proposed) would have left three presigned PUT sites and two error
contracts in the tree; this PR deletes the drift vector instead. Full
suite green (1320 passed), `make chk` and `make snt` clean; Python-only
change, so no changeset per `AGENTS.md`.

---------

Co-authored-by: Mustaqeem66 <265153888+Mustaqeem66@users.noreply.github.com>
2026-08-18 19:09:02 +02:00
Musthaq Ahamad ebc9778595 feat(sdk): default-off auto file upload/download; add dangerouslyAllowAutoUploadDownloadFiles (#3260)
## Summary

Automatic tool file upload/download for `file_uploadable` fields is
**off by default** in TypeScript and Python. Callers must explicitly opt
in, and uploads from local paths are constrained by a fail-closed
allowlist.

## Changes

- **Removed (breaking):** `autoUploadDownloadFiles` (TS) /
`auto_upload_download_files` (Python) — the legacy default-on flag is
gone, not just deprecated.
- **New opt-in:** `dangerouslyAllowAutoUploadDownloadFiles` (TS) /
`dangerously_allow_auto_upload_download_files` (Python). When `true`,
`tools.get(...)` collapses `file_uploadable` schemas to `{ type:
'string', format: 'path' }` and the SDK stages local paths/URLs at
execute time.
- **New:** `fileUploadDirs?: string[] | false` — fail-closed allowlist
for local upload paths. `undefined` → `[<home>/.composio/temp]`; `false`
→ reject all local paths (URLs / `File` objects unaffected); explicit
`string[]` replaces the default. Components are matched on a path
boundary after `realpath`.
- **New:** `fileDownloadDir?: string` — directory where
`file_downloadable` results are staged.
- **New:** `beforeFileUpload` hook receives `source: 'path' | 'url' |
'file'` (TS) / `'path' | 'url'` (Python) so it can branch on input type.
- **New (TS):** when auto-upload is **off** and an LLM-driven
`tools.execute` is called against a tool with `file_uploadable` inputs,
the SDK emits a one-shot warning per tool slug pointing at
`composio.files.upload()` for manual staging.

## Migration

To restore previous behavior:

```ts
new Composio({
  apiKey: process.env.COMPOSIO_API_KEY!,
  dangerouslyAllowAutoUploadDownloadFiles: true,
  // Optional: tighten the allowlist beyond the default ~/.composio/temp
  fileUploadDirs: ['/srv/uploads'],
});
```

```python
Composio(api_key="...", dangerously_allow_auto_upload_download_files=True)
```

If you previously passed the legacy flag, remove it. There is no
transitional warning — TS and Python both reject the unknown property at
the type/keyword-arg level.

## Versioning

| Package | Bump |
| ------- | ---- |
| `@composio/core` | minor |
| `composio` (Python) | minor |
| Other `@composio/*` packages | patch (via changesets
`updateInternalDependencies: "patch"`) |

See
`docs/content/changelog/04-24-26-legacy-auto-upload-config-removal.mdx`
for the full migration writeup.
2026-04-28 10:55:03 +05:30