mirror of
https://github.com/ComposioHQ/composio.git
synced 2026-09-22 11:46:35 +08:00
py@0.15.0
787 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
08f7072110 |
fix(ci): make CLI releases reliably ship binary assets (#3515)
## Summary Permanently stops the recurring *"release published with zero assets → install/upgrade 404s"* outage (https://github.com/ComposioHQ/composio/issues/3408, https://github.com/ComposioHQ/composio/issues/3269; regressions of https://github.com/ComposioHQ/composio/issues/2625 and https://github.com/ComposioHQ/composio/issues/1820 — 3 of the last 5 stable releases shipped empty). **Root cause:** a concurrent-writer race. On a CLI version bump, `changesets/action` creates an empty `@composio/cli@x.y.z` GitHub Release in seconds, then the slower `build-cli-binaries.yml` fails its `gh release create` because the release already exists — so binaries never attach. > 🥞 **Stacked on #3415** (`pi/exclude-cli-ts-release-42161920`), which removes the *second writer* (changesets no longer creates CLI releases). Review/merge #3415 first; this PR targets that branch. This PR hardens the now-sole writer so a *partial* build can't publish either, and fixes the monitoring that hid the failure. ## What changed (`build-cli-binaries.yml` + canary) - **Draft → verify → publish.** The release is built as a **draft**, then a gate asserts all 6 canonical assets are present **and** `state == "uploaded"` (loud `::error::` + fail otherwise), and only the final step flips it to published. Drafts fire no `release: published` event and are excluded from `/releases/latest`, so no install.sh / Homebrew / redirect consumer can observe an incomplete release. - **`fail-fast: false`** on the build matrix → a single platform failure can never publish a partial set (`needs.build.result` is `success` only if all legs pass). - **Per-tag job-level `concurrency`** so re-runs / quick pushes can't interleave uploads on the same tag, without serializing unrelated betas. - **Beta-safe:** `--prerelease` is set on the draft so betas stay prereleases through the publish flip. - **`promote-stable` guard** uses `gh release view --json isDraft` (the REST tags endpoint 404s on drafts) to resume an existing draft but refuse an already-published tag. - **Least privilege:** workflow defaults to `contents: read`; only the release job opts up to `contents: write`. - **Canary fix** (`cli.install-health-check.yml`): install the newest stable **pinned** tag (`npm view @composio/cli version`) instead of the asset-aware no-arg flow, which self-heals to the last good release and kept the canary green through every outage. ## Idempotency note Re-running a run that failed **before publish** is safe (reuse draft + `--clobber`). An already-**published** tag is refused, not mutated — by design. ## Testing - Extended `test/release-workflow.test.ts` (run via `pnpm test:release-workflow`) to lock in: draft→verify→publish ordering, `fail-fast: false`, per-tag concurrency, preserved `--prerelease`, and the pinned-tag canary. ✅ passes. - `shellcheck` clean on the new `run:` scripts; YAML validated. `actionlint` runs in CI. - Runtime verification of the full green path happens on the next release CI run. ## Out of scope (deferred to their own PRs) Per reviewer consensus, these are real but *not this bug*: a per-release npm↔GitHub asset auditor (needs a grace window), the Homebrew trigger constraint (folds into #3355), `composio upgrade` missing-asset back-off (https://github.com/ComposioHQ/composio/issues/3269), and a rollback runbook. --------- Co-authored-by: Rahul Tarak <cryogenicplanet@gmail.com> |
||
|
|
632757ec60 |
chore(ts/packages/core): add repository, bugs, and homepage metadata (#3573)
## Summary Adds missing npm support metadata to `ts/packages/core/package.json` for the `@composio/core` package: - **`repository`**: adds full object with `type`, `url`, and `directory` (monorepo package path) - **`bugs.url`**: points to `https://github.com/ComposioHQ/composio/issues` - **`homepage`**: points to the package README in the repository ## Verification ```sh npm view @composio/core@0.10.0 repository bugs homepage # Currently returns empty for all three fields ``` No runtime code, dependencies, tests, or build configuration are changed. --------- Co-authored-by: XananasX7 <xananasandy@gmail.com> Co-authored-by: Alberto Schiabel <jkomyno@users.noreply.github.com> Co-authored-by: jkomyno <alberto@composio.dev> |
||
|
|
a94715f577 |
feat(sdk): forward user_id on triggers.create for trigger 2FA (#3576)
## What `triggers.create(userId/user_id, ...)` already accepts a user id and uses it to resolve the connected account, but **dropped it** when building the `trigger_instances.upsert` body. With [2FA for triggers](https://linear.app/composio/issue/PLEN-2580) on the backend, 2FA-enabled projects need `user_id` on the upsert to verify the pinned connected account belongs to the caller's user. This forwards `user_id` to upsert in **both SDKs**: - **TS** (`ts/packages/core/src/models/Triggers.ts`): adds `user_id` to the upsert params via a `& { user_id?: string }` bridge. - **Python** (`python/composio/core/models/triggers.py`): forwards `user_id` via the client's supported `extra_body` escape hatch. Both bridges exist only until `@composio/client` / `composio-client` regenerate from the updated OpenAPI spec with a native `user_id` field — drop them then. ## Safety Backends without trigger 2FA ignore the extra field, so this is safe to land ahead of / alongside the backend rollout (hermes PR #10635). ## Tests - TS: upsert-body assertion added. - Python: `tests/test_triggers.py::test_create_with_user_id` asserts `extra_body == {"user_id": ...}`. 49 tests pass. Closes part of PLEN-2580 (SDK follow-up to the agreed approach). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: jkomyno <alberto@composio.dev> |
||
|
|
ce4b213361 |
fix(providers): normalize string tool-call arguments across all providers (TS + Python) (#3514)
## Summary Models — and some MCP transports — occasionally emit tool-call arguments as a **JSON string instead of an object/dict**. The most visible trigger is `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI SDK, where streaming fails with: > `messages.3.content.1.tool_use.input: Input should be a valid dictionary` Until now only a handful of providers guarded against this, each with its own slightly different inline check, leaving most providers vulnerable and behaviour inconsistent across the SDK. This PR centralizes the coercion into **one helper per language** and routes **every** provider through it, in both the TypeScript and Python SDKs. Closes https://github.com/ComposioHQ/composio/issues/2406 ## What changed **TypeScript** — new `normalizeToolArguments` in `@composio/core` (exported), used by every provider: `vercel`, `cloudflare`, `openai-agents`, `openai` (ChatCompletions + Responses), `anthropic`, `google`, `langchain`, `llamaindex`, `claude-agent-sdk`, `mastra`. **Python** — new `normalize_tool_arguments` in `composio.utils.shared`, used by every provider: `openai`, `openai-responses`, `anthropic`, `google`, `langchain`, `langgraph`, `crewai`, `autogen`, `llamaindex`, `gemini`, `google-adk`, `openai-agents`, `claude-agent-sdk`. Shared semantics (identical in both languages): | Input | Result | | --- | --- | | object / dict | returned unchanged | | JSON string | parsed to object | | empty / whitespace string | `{}` | | `null` / `undefined` / `None` | `{}` | | array, primitive, unparseable string, JSON that isn't an object | **typed error** (`ComposioInvalidToolArgumentsError` / `InvalidParams`) with the original parse error as cause | The typed error replaces the previous grab-bag of behaviours: a raw `SyntaxError`/`JSONDecodeError`, or — worse — silently forwarding a malformed string downstream. ## Why this supersedes the open PRs This consolidates and extends three open PRs that each addressed a slice of the problem inconsistently. Their authors are credited as co-authors on the relevant commits: - **#3489** (LlamaIndex + Claude Agent SDK, TS) — @srijanarya - **#3438** (Anthropic, Google, LangChain, TS) — @aptsalt - **#3437** (Google ADK empty schemas + name fix, Python) — @pragnyanramtha — its empty-`input_parameters` / missing-description handling and the `gemini` → `google_adk` provider-name fix are folded in here. Compared to the three combined, this PR additionally: covers **every** provider in **both** SDKs (not a subset of one), defines a single source of truth instead of per-provider snippets, normalizes empty/`null` payloads to `{}`, and raises an actionable typed error instead of leaking `SyntaxError` or forwarding a bad string. ## Tests - Exhaustive unit tests for both helpers (object passthrough, JSON-string parse, empty/null → `{}`, malformed/non-object → typed error). - Per-provider regression tests across the touched TypeScript providers (string path, malformed-string path, empty-payload path). - Full `@composio/core` + touched-provider TS suites pass; `typecheck` and `lint` clean. Python `ruff` clean and new test green. ## Changeset Patch bump for all affected TypeScript packages (`@composio/core` + the providers). Python follows its own versioning, so no changeset there. --------- Co-authored-by: srijanarya <74669415+srijanarya@users.noreply.github.com> Co-authored-by: Deepak Singh Kandari <deepaksinghkandari07@gmail.com> Co-authored-by: Pragnyan Ramtha <pragnyanramtha@gmail.com> |
||
|
|
6606c0da92 |
fix(ts): upgrade vitest for GHSA-5xrq-8626-4rwp (#3569)
This PR: - closes #3502 - extracts the useful dependency and Cloudflare config slice from https://github.com/ComposioHQ/composio/pull/3503 onto a clean `next` branch - upgrades `vitest` and `@vitest/ui` through the workspace catalog to resolve the critical advisory - switches the Mastra provider test dependency back to the catalog - migrates the Cloudflare Worker Vitest configs to the `cloudflareTest()` plugin API - preserves existing `COMPOSIO_BASE_URL` bindings that were dropped in #3503 - keeps Vitest 4 compatibility fixes scoped to constructor mocks, spy cleanup, and temp-root project detection - leaves Node, `mise`, release docs, and Effect catalog versions unchanged; the commit includes @Dotify71 as `Co-authored-by` Co-authored-by: Dushyant Acharya <dushyantacharya873@gmail.com> |
||
|
|
74ce25812e |
fix(ci): repair CLI binary and docs sync workflows (#3568)
This PR: - patches the Peekaboo sidecar build to rewrite the resolved `swift-system` `AT_RESOLVE_BENEATH` Darwin guard before compiling on GitHub macOS runners - adds regression coverage for the `swift-system` checkout patch and includes script tests in `@composio/cli-local-tools` Vitest - switches the SDK docs sync workflow to `anthropics/claude-code-action/base-action` so push-triggered automation does not fail on unsupported event parsing - moves Claude tool restrictions to `claude_args` and quotes `$GITHUB_OUTPUT` writes so the workflow passes `actionlint` - verifies the changed package and workflow with targeted tests, build, formatting, YAML parsing, and `actionlint` |
||
|
|
56534e2158 |
chore(cli): release 0.2.31 (#3538)
## What Manual version bump for **`@composio/cli` → 0.2.31**, replacing the broken changeset-bot flow. - Bumps `ts/packages/cli/package.json` `0.2.30 → 0.2.31` - Adds the `0.2.31` entry to `ts/packages/cli/CHANGELOG.md` - Consumes (deletes) the 5 CLI changesets it covers: - `composio upgrade <version>` (#3428) - `x-cli-session-id` header (#3430) - refreshed approval fallback page (#3431) - LLM-friendly output (#3450) - fish completion paths (#3162) + 1-hour permission expiry (#3449) - Leaves the `@composio/core` changesets untouched for the bot. ## Why manual The changeset release bot (`ts.release.yml` → `changesets/action`) has been failing on **`HttpError: Bad credentials`** on every run since 2026-06-04 — its `CI_BOT_TOKEN` secret is expired/invalid — so it can no longer regenerate the "Release: update version" PR (#3429, stale since 2026-05-20). `build-cli-binaries.yml` is healthy and independent of that token: on merge to `next` it compares `ts/packages/cli/package.json` against the previous commit, detects the version change, and builds + publishes the stable **`@composio/cli@0.2.31`** GitHub release (cross-platform binaries). The CLI is `"private": true`, so it ships only as the GitHub binary release, not npm — this path fully covers it. ## Validated The pinned-actions binary pipeline was already validated green end-to-end (all 4 platform binaries built + full install-test matrix passed) on a `build-beta` run. Local binary (built from this same source) passed version/whoami/help, LLM-friendly stdout, `upgrade <version>`, and the full Slack + `experimental_subAgent` integration test. ## Follow-up (separate) `CI_BOT_TOKEN` needs refreshing to restore the changeset bot (recommend a GitHub App installation token over a personal PAT to avoid future expiry). Tracked outside this PR. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
44e5458c35 |
feat(core): remove legacy TypeScript custom tools (#3509)
This PR is **part 2 of 3** splitting https://github.com/ComposioHQ/composio/pull/3505 to make the removal of the old 2025 custom tools easier to review. It carries the **TypeScript** slice. - builds on top of https://github.com/ComposioHQ/composio/pull/3508 (stacked — review/merge the Python slice first; this PR's base is `remove-py-custom-tools`) - removes the legacy `composio.tools.createCustomTool(...)` in-memory registry: the plural `CustomTools` model, registry wiring, legacy-only tests/examples/`ts/docs` pages, and stale error/type exports - preserves the 2026 tool-router APIs: `experimental_createTool`, `experimental_createToolkit`, `ToolRouter`, `ToolRouterSession`, and inline custom-tool execution - regenerates the TypeScript SDK reference so raw tool listing no longer describes the removed local registry and points to session-scoped custom tools - adds a `@composio/core` minor changeset ## Notes - The committed SDK reference is **verified self-consistent**: `pnpm --filter @composio/core generate:docs` reproduces it with zero diff. - This slice is a byte-identical subset of #3505 — the three split branches recombine to that PR's exact tree. See #3505 for the original verification logs (`typecheck`, `test`, `lint`, `cf-workers` e2e); CI re-runs per PR. |
||
|
|
b69cef123f |
fix(mastra): tolerate dangling $ref in tool schemas [PLEN-2451] (#3400)
## Summary Closes [PLEN-2451](https://linear.app/composio/issue/PLEN-2451/mastraprovider-dollardefsdollarref-schema-is-dangling-at-the-api). Fixes https://github.com/ComposioHQ/composio/issues/3307. The Composio API ships some tools (e.g. `GMAIL_FETCH_EMAILS`) with `outputParameters` like: ```jsonc { "type": "object", "properties": { "data": { "$ref": "#/$defs/FetchEmailsResponse" }, // ← points into $defs "error": { "type": "string" }, "successful": { "type": "boolean" } }, "required": ["data", "successful"] // ← no `$defs` block anywhere } ``` Since [PLEN-2244](https://linear.app/composio/issue/PLEN-2244) introduced strict `dereferenceJsonSchema`, this caused `composio.tools.get(...)` to throw `JsonSchemaRefResolutionError: Cannot resolve $ref #/$defs/FetchEmailsResponse` upfront via `MastraProvider.wrapTool`, making every Gmail / Slack / Google Calendar tool unusable through the Mastra integration. ### Approach Two-tier fix that keeps the architectural boundary from PLEN-2244 (only the provider that owns the validation contract pre-processes the schema): 1. **`@composio/core`** — add an additive opt-in to `dereferenceJsonSchema`: ```ts dereferenceJsonSchema(schema, { onUnresolved: 'sentinel', // default 'throw' unchanged onReplace: (ref, reason) => { /* observe */ }, }) ``` In `'sentinel'` mode the unresolvable branch is replaced with the same `{ type: 'object', additionalProperties: true }` cycle-break sentinel the resolver already uses for `$ref` cycles. Safety caps (`MAX_REF_CHAIN_DEPTH`, `MAX_NODE_DEPTH`) keep throwing in both modes. Default behavior is byte-for-byte unchanged — first-party / custom-tool authors who typo a `$ref` still see a hard error. 2. **`@composio/mastra`** — opt `wrapTool` into sentinel mode for both `inputParameters` and `outputParameters` and emit one `logger.warn` per `(toolSlug, ref)` pair via a provider-scoped dedup `Set`. The warning names the tool / toolkit / pointer and links to https://github.com/ComposioHQ/composio/issues/3307. ### Why not centralize the dereferencing in `Tools.ts`? - Mastra is the only provider that wraps `outputParameters`. Vercel / OpenAI / Anthropic / Google bind tool input schemas to function-calling APIs that ignore output shapes. - Centralized dereferencing would silently mutate `tools.get()`'s public output shape for callers iterating raw schemas. - PLEN-2244 set the precedent — the provider that owns the validation contract pre-processes its own schemas. This PR mirrors that boundary. ### API-side follow-up The proper long-term fix is for the Composio API to emit a top-level `$defs` block alongside any `$ref` it produces. That belongs in a separate backend ticket — the SDK fix is intentionally independent so we don't block on a backend rollout. The SDK now degrades gracefully regardless of which API version it talks to. ## Test plan Red-green TDD — every new test was confirmed red against the pre-fix `dereferenceJsonSchema` / `MastraProvider`, then green after the fix. - [x] **Core** — 9 new cases in `ts/packages/core/test/utils/jsonSchema.test.ts` under `describe("with onUnresolved: 'sentinel' lenient mode")` covering: missing-target, missing-key, malformed-pointer (non-`#/` ref), mixed schema (resolvable + dangling siblings), `onReplace` reasons, safety-cap-still-throws (chain & node depth), explicit `'throw'` matches default, `onReplace` not called in strict mode. - [x] **Mastra** — new file `ts/packages/providers/mastra/test/mastra-dangling-defs.test.ts` (6 cases, un-mocked `@mastra/schema-compat`): replicates the exact `GMAIL_FETCH_EMAILS.outputParameters` shape; verifies no throw, no surviving `$ref` in the produced schema, exactly one warn per `(slug, ref)` pair across repeat wraps, a separate warn per slug, symmetric tolerance on `inputParameters`, and a regression guard for resolvable `$defs` (PLEN-2244 contract). - [x] **Regression** — all 908 core tests, all 39 existing `mastra.test.ts` cases, and all 3 `mastra-ref.test.ts` cases continue to pass. Full TS workspace test run: 14 packages green, 1322 tests total. - [x] `pnpm typecheck` passes in both `@composio/core` and `@composio/mastra`. - [x] `pnpm lint` on touched files produces no new warnings. - [ ] **Manual** (post-merge, against live API): `composio.tools.get(userId, { tools: ['GMAIL_FETCH_EMAILS'] })` returns a `MastraTool` whose `outputSchema` is defined; SDK logs exactly one warning per process per `(slug, ref)` pair. ## Files ``` ts/packages/core/src/index.ts # new type exports ts/packages/core/src/utils/jsonSchema.ts # opts + lenient branch ts/packages/core/test/utils/jsonSchema.test.ts # 9 new cases ts/packages/providers/mastra/src/index.ts # opt-in + dedup warn ts/packages/providers/mastra/test/mastra-dangling-defs.test.ts # 6 new cases .changeset/fix-mastra-dangling-defs-ref.md # core/mastra patch plans/fix-mastra-dangling-defs-ref.md # design + acceptance log ``` --------- Co-authored-by: jkomyno <12381818+jkomyno@users.noreply.github.com> |
||
|
|
22a9171981 |
fix(core): defer telemetry sends (#3447)
## Summary - Defer telemetry batch processing via microtask scheduling so reaching the batch size no longer starts telemetry network work inline with SDK calls. - Defer SDK init/error telemetry sends and make `flush()` wait for both deferred sends and pending batches. - Remove stale blocking TODOs and add regression coverage for deferred batch/error telemetry behavior. Fixes #3442 ## Tests - `pnpm --filter @composio/json-schema-to-zod build` - `pnpm --filter @composio/core typecheck` - `pnpm --dir ts/packages/core exec vitest run test/telemetry/TelemetryService.test.ts` - `pnpm --filter @composio/core test` - `pnpm exec eslint ts/packages/core/src/telemetry/BatchProcessor.ts ts/packages/core/src/telemetry/Telemetry.ts ts/packages/core/src/services/telemetry/TelemetryService.ts` ## CI - GitHub checks are pending on PR creation; initial `gh pr checks 3447` showed required jobs queued/in progress. |
||
|
|
832c65ee1d |
fix: correct typos 'sucessfull' and 'satus' in callbackUrl JSDoc (#3478)
## Summary Fixes #3475 Two typos in the JSDoc comment for `CreateConnectedAccountLinkOptionsSchema.callbackUrl` in `ts/packages/core/src/types/connectedAccounts.types.ts`: - `sucessfull` → `successful` - `satus=failed` → `status=failed` |
||
|
|
cf13e17817 |
Fix fish completion install paths (#3162)
## Summary - Route fish shell completions to `~/.config/fish/completions/composio.fish` instead of writing them into the rc file. - Keep fish PATH setup in `~/.config/fish/config.fish` while writing completion blocks to the dedicated completions file. - Sanitize fish completion lines to strip description text that can break parsing, including multiline descriptions. - Add tests covering fish install behavior and fish completion sanitization. Closes #3147 ## Testing - `pnpm test --filter ts/packages/cli/test/src/commands/install.cmd.test.ts` - `pnpm test --filter ts/packages/cli/test/src/effects/shell-completions.test.ts` - Not run: full repository test suite |
||
|
|
1692bbee7a |
fix(cli): make output more LLM friendly (#3450)
## Summary - Route Effect pretty logger output to stderr and share a TTY-based interactive detector for human-only CLI UI. - Gate upgrade notices and default browser login waiting on interactive stdio; non-interactive `composio login` now emits session JSON and exits. - Stream `composio run` helper/subagent logs to stderr (or only to the run log with `--logs-off`) without polluting stdout. - Add a CLI patch changeset. ## Tests - `pnpm -C ts/packages/cli exec vitest run test/src/services/update-check.test.ts test/src/commands/login.cmd.test.ts test/src/commands/run.cmd.test.ts` - `pnpm --filter @composio/cli typecheck` - `pnpm typecheck` - `pnpm exec eslint ts/packages/cli/src/utils/stdio.ts ts/packages/cli/src/services/terminal-ui.ts ts/packages/cli/src/services/update-check.ts ts/packages/cli/src/cli-main.ts ts/packages/cli/src/commands/login.cmd.ts ts/packages/cli/src/commands/run.cmd.ts ts/packages/cli/src/services/run-helpers-runtime.ts --no-warn-ignored` - `pnpm exec prettier --check ts/packages/cli/src/utils/stdio.ts ts/packages/cli/src/services/terminal-ui.ts ts/packages/cli/src/services/update-check.ts ts/packages/cli/src/cli-main.ts ts/packages/cli/src/commands/login.cmd.ts ts/packages/cli/src/commands/run.cmd.ts ts/packages/cli/src/services/run-helpers-runtime.ts ts/packages/cli/test/src/services/update-check.test.ts ts/packages/cli/test/src/commands/login.cmd.test.ts` ## Notes - Initial targeted `pnpm --filter @composio/cli test -- ...` ran the full CLI suite and failed before building `@composio/cli-keyring`; after building/installing workspace deps, the targeted Vitest command above passed. |
||
|
|
afa118c8fb |
fix(cli): make permission allows expire after one hour (#3449)
## Summary - Rename the permission prompt action from “Allow for session” to “Allow for 1 hr” in browser and native UI flows. - Cache allow decisions with a 1-hour expiry in `tool-permissions-cache.json`, with an in-memory fast path and stale-entry pruning. - Preserve existing permission snapshot cache behavior while keeping cached allow decisions across CLI invocations until expiry. ## Tests - `pnpm install --frozen-lockfile --ignore-scripts` - `pnpm build:packages` - `cd ts/packages/cli && pnpm run typecheck` ## Notes - The decision enum remains `allow_session` for compatibility with existing backend/native callback payloads; only the UX/caching semantics now expose and enforce a 1-hour duration. |
||
|
|
eb51b923bb |
feat(cli): send x-cli-session-id header on every request (#3430)
## Summary - Pulls the per-cwd CLI session id (already generated by `getCurrentCwdSessionId()` and used as `cli_session_id` on analytics events) and attaches it as the `x-cli-session-id` header on every request from the composio client. - Backend reads the header off `requestInfo`, threads it through `enrichSessionInfo`, and writes `session_info.cli_session_id` on every tool execution log row. Companion hermes PR: ComposioHQ/hermes#9990 ## Why The CLI already tracks a stable per-cwd session id for analytics, but tool execution logs are blind to it — there's no way to filter the logs UI / retool back to a single CLI session. Wiring the header through lets us group all tool calls from one CLI workflow together. ## Test plan - [x] `pnpm --filter @composio/cli typecheck` clean - [ ] Run `composio tools execute <slug>` against a build with the hermes companion deployed, confirm ClickHouse tool log has `session_info.cli_session_id` - [ ] Confirm header is absent (and log field absent) when no cwd session is cached 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
1ba66ca045 |
fix(core): normalize empty output_parameters so MCP tools can execute [PLEN-2450] (#3397)
Closes [PLEN-2450](https://linear.app/composio/issue/PLEN-2450/toolsexecute-fails-for-all-mcp-toolkits-strict-zod-validation-rejects) · refs https://github.com/ComposioHQ/composio/issues/3354 ## Summary `composio.tools.execute('<MCP_TOOL>', ...)` currently throws a `ZodError` for **every** tool from an MCP-backed toolkit (`granola_mcp`, `apify_mcp`, `tavily_mcp`, …) on `@composio/core` 0.6.x–0.9.x. The reporter on #3354 confirmed all three versions hit the identical failure; users are working around it by dropping to `@composio/client` and losing modifiers, custom-tool routing, version checks, and provider wrapping. **Root cause** (`ts/packages/core/src/models/Tools.ts` + `src/types/tool.types.ts`): - `tools.execute` and `tools.get` both run the API response through `transformToolCases → ToolSchema.parse`. - `ParametersSchema` requires `{ type: 'object', properties: {...} }`. - The API returns `output_parameters: {}` for MCP tools that have no declared output schema, so the validator throws. **Fix:** a tiny module-private `normalizeRawToolParameters` helper applied to both `input_parameters` and `output_parameters` inside `transformToolCases`. `null` / `undefined` / `{}` all map to `undefined`; everything else passes through to strict Zod validation. This: - Preserves the existing `outputParameters: undefined` ⇒ "no declared schema" contract — `outputParameters` was already optional in the public `Tool` type, so no public API change. - Fixes both `tools.execute` and `tools.list` (single funnel covers both paths). - Doesn't relax `ParametersSchema` — tools that actually declare a schema remain strictly validated. - Forward-compatible for every present / future `*_mcp` toolkit with no toolkit allow-list. ## Testing Red → green confirmed locally. New `describe('MCP-shaped tool metadata (PLEN-2450)')` block in `tools.test.ts` covers: 1. `getRawComposioToolBySlug` does not throw `ZodError` for `output_parameters: {}`. 2. Empty `output_parameters` is normalized to `undefined` on the transformed `Tool`. 3. Both-empty edge case (`input_parameters: {}` + `output_parameters: {}`). 4. `tools.list` path also tolerates empty `output_parameters`. 5. End-to-end `tools.execute` succeeds against an MCP-shaped fixture. All five tests **fail** on `next` without the helper (reproducing the exact `ZodError` from the report) and **pass** with it. Full `@composio/core` suite: **904 / 904 green**. ```bash cd ts/packages/core pnpm vitest run tools.test -t "MCP-shaped tool metadata" # → PASS (5) FAIL (0) pnpm vitest run # → PASS (904) FAIL (0) ``` ## Test plan - [x] Red phase confirmed: 5 new tests fail with the exact `ZodError` from the report. - [x] Green phase confirmed: 5 new tests pass after the helper lands. - [x] Full `@composio/core` test suite stays green (904 tests). - [x] `pnpm typecheck` clean. - [ ] Optional live sanity: build a tarball and run the reporter's `repro.mjs` against a sandbox user (`pg-test-9f4d0df7-…`) — not blocking; the mocked end-to-end test pins the same path. ## Follow-ups (out of scope) - **Python SDK** — verify whether `composio` Python has the same over-strict Pydantic check and apply the equivalent normalization if so. > Note: not proposing an API-side change. `output_parameters: {}` is the correct JSON Schema for "no declared schema" (the empty schema validates anything); the bug was the SDK's Zod validator being over-strict, not the API. The fix belongs at the SDK layer, where it now lives. Co-authored-by: jkomyno <12381818+jkomyno@users.noreply.github.com> |
||
|
|
5555dee25c |
feat(cli): refresh approval fallback page (#3431)
## Summary - Refresh the browser fallback tool-approval page with the Composio CLI landing page visual language: light dithered background, mono terminal card, and brand-blue actions. - Serve the approval HTML directly from the temporary `127.0.0.1` callback server instead of writing/opening a `file://` page, so approval buttons call back to the active CLI process with relative local routes. - Keep the native macOS sidecar as the preferred prompt when available; the browser prompt remains the fallback when the sidecar is missing or fails before returning a decision. - Add a CLI patch changeset. ## Tests - `pnpm exec eslint ts/packages/cli/src/services/tool-permissions.ts` - `pnpm --filter @composio/cli typecheck:src` - `git diff --check` ## Notes - Initially `typecheck:src` failed before workspace package build artifacts existed in the fresh worktree; after building required workspace dependencies it passed. --------- Co-authored-by: Malay Vasa <malayvasa@gmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
93b67e8b2f |
fix(ts-sdk): handle file upload list unions (#3374)
## Summary
This updates the TypeScript SDK's automatic file upload/download
modifier to handle tool schemas that accept either a single file or a
list of files.
Tools can expose file inputs as a composed schema such as:
```json
{
"anyOf": [
{ "type": "object", "file_uploadable": true },
{ "type": "array", "items": { "type": "object", "file_uploadable": true } }
]
}
```
When auto-upload is enabled, the SDK presents those file-uploadable
objects to models as file path strings. If the model supplies a list of
local paths, the old upload resolver selected the first file-bearing
branch, usually the single-file branch, and left the list unchanged.
That means the backend could receive local paths instead of staged `{
name, mimetype, s3key }` descriptors.
## Changes
- Adds runtime-shape-aware composed-schema selection for file
upload/download modifiers.
- Chooses the array branch for list values while preserving single-file
behavior for string/File values.
- Preserves the existing fallback behavior: if no runtime shape matches,
use the first file-bearing variant.
- Keeps `anyOf`, `oneOf`, and `allOf` on the same composed-schema path
used by the SDK today.
- Adds regression coverage for single-file vs multi-file unions, array
item unions, and download parity.
- Adds a patch changeset for `@composio/core`.
## Why
Some file-capable tool schemas are backward compatible at the API level
by accepting both a single file and multiple files. The TypeScript SDK
should transform a list of local paths into a list of staged file
descriptors, just as it already does for direct array schemas.
## Verification
- `pnpm --filter @composio/core exec prettier --check
src/utils/modifiers/FileToolModifier.node.ts
test/tools/fileModifiers.test.ts`
Blocked locally:
- `pnpm --filter @composio/core test -- fileModifiers.test.ts` fails
before collecting tests because this workspace cannot resolve the
unbuilt `@composio/json-schema-to-zod` package entry.
- `pnpm --filter @composio/core typecheck:tsc` is also blocked by
existing local generated-client/workspace dependency errors unrelated to
this patch.
---------
Co-authored-by: Zen <zen@composio.dev>
|
||
|
|
2d52e7f7c0 |
feat(cli): support composio upgrade <version> for specific releases (#3428)
## Summary - `composio upgrade` now accepts an optional `<version>` argument so users can install any published CLI release — stable or beta — without having to wait for the channel pointer to move. - Accepts `0.13.1`, `v0.13.1`, `0.13.1-beta.42`, or the full `@composio/cli@0.13.1` tag (normalized internally). - When a version is provided, the "already on latest" guard is skipped so the command also supports downgrades and reinstalls. `--beta` continues to control the no-arg case. ## Examples ```bash composio upgrade # latest stable (unchanged) composio upgrade --beta # latest beta (unchanged) composio upgrade 0.13.1 # pin to a specific stable composio upgrade 0.13.1-beta.42 # install a specific beta composio upgrade @composio/cli@0.13.1 # full release tag also accepted ``` ## Implementation - `upgrade.cmd.ts`: added optional `version` Args, normalizes input to a `@composio/cli@<semver>` release tag, passes it through to the service. - `upgrade-binary.ts`: `upgrade`/`fetchLatestRelease` now accept a `tag` option that fetches the GitHub release directly via `/releases/tags/<tag>`, bypassing the channel resolver. When a tag is explicit, the update-availability check is skipped. - Falls back to the explicit tag for `installSkillSafe` when the upgrade completes without returning one. ## Test plan - [x] `pnpm typecheck` (CLI package) — clean - [x] `pnpm test` in `ts/packages/cli` — 703 passed, 1 skipped, no regressions in `upgrade-binary.test.ts` - [ ] Manual: `composio upgrade 0.13.0` from a newer beta to confirm downgrade path works against real GitHub releases - [ ] Manual: `composio upgrade --beta` still resolves the latest beta when no version is given 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
878ac4d34b |
Release: update version (#3425)
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to next, this PR will be updated. # Releases ## @composio/core@0.10.0 ### Minor Changes - |
||
|
|
ff4085a78d |
feat(connected-accounts-py): namespace SHARED-connection surface under experimental (#3412)
## Summary
Moves the SHARED connected-accounts surface in the Python SDK under the
`composio.experimental` namespace, mirroring the wire-level restructure
of the same fields. Same precedent as `composio.experimental.tool` /
`composio.experimental.Toolkit` — the namespace tells callers the shape
may still change.
- `link()` and `session.authorize()`: flat `account_type` /
`acl_config_for_shared` kwargs → single `experimental={}` dict
- `composio.connected_accounts.update_acl(...)` →
`composio.experimental.update_acl(...)`
- `composio.connected_accounts.list(...)` now exposes
`account_type='PRIVATE' | 'SHARED' | 'ALL'` (flat — the wire keeps this
as a query param)
- `composio-client` bumped `1.38.0` → `1.39.0` so the generated typed
client carries the `Experimental` TypedDicts
Pinning a SHARED connection in a session (`connected_accounts={...}`)
and direct execute by `connected_account_id` are unchanged — only the
connection-create / patch / authorize surfaces moved.
## Caller migration
```python
# before
composio.connected_accounts.link(
user_id, auth_config_id,
account_type="SHARED",
acl_config_for_shared={"allow_all_users": True},
)
composio.connected_accounts.update_acl("ca_abc", allow_all_users=True)
session.authorize(
"github",
account_type="SHARED",
acl_config_for_shared={"allow_all_users": True},
)
# after
composio.connected_accounts.link(
user_id, auth_config_id,
experimental={
"account_type": "SHARED",
"acl_config_for_shared": {"allow_all_users": True},
},
)
composio.experimental.update_acl("ca_abc", allow_all_users=True)
session.authorize(
"github",
experimental={
"account_type": "SHARED",
"acl_config_for_shared": {"allow_all_users": True},
},
)
# new — list SHARED connections
shared = composio.connected_accounts.list(
account_type="SHARED",
user_ids=["user_creator"],
)
```
## Tests
- `link()` forwards the experimental block / omits it when not provided
/ preserves explicit empty lists
- `link()` maps the `acl_config_for_shared is only valid on SHARED` 400
to `ComposioAclOnlyForSharedError`; non-ACL 400s re-raise
- `experimental.update_acl()` body construction, deny-list handling,
`ValidationError` when no fields provided, `ValidationError` when no
client is bound, same 400-mapper as `link()`
- `authorize()` forwards the experimental block
- `list(account_type="SHARED")` delegates the flat filter through to the
client
## Test plan
- [ ] `nox -s fmt` and `nox -s chk` clean for `composio/` (pre-existing
4 mypy errors in `providers/langgraph` and `providers/langchain` are
unrelated — same on `origin/next`)
- [ ] `pytest tests/test_connected_accounts.py
tests/test_tool_router.py` → 136 passed
- [ ] Docs page update (separate PR — code samples already on the
experimental shape there; `account_type=` list filter example to be
added once this lands)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||
|
|
cfa30ceef3 |
chore(connected-accounts): drop dead re-exports from Experimental.ts
Three types (LinkCreateParams, SessionLinkParams, ConnectedAccountListParamsRaw) were imported and re-exported but had zero external consumers. The named-type imports of LinkCreateParams / SessionLinkParams were only referenced in a descriptive comment; ConnectedAccountListParamsRaw wasn't used at all. Rewrote the comment so it documents the structural-typing rationale without referencing the now-unimported namespace names. Typecheck clean, 919/919 tests pass. |
||
|
|
123b8d6f34 |
fix(connected-accounts): address review feedback on #3424
Six code-review nits from the multi-agent review on PR #3424: P1.1 — `experimental_updateAcl(composio, id, opts)` doesn't match the `experimental_createTool` precedent it cited. That export is a *pure factory* (returns a value object, no client, no I/O), whereas `updateAcl` takes a client and performs a network call. Costs the current shape was paying: - Awkward call site (composio passed as first arg every time) - Bypassed `telemetry.instrument(this, 'ConnectedAccounts')` — the proxy only wraps class methods - Diverged from the Python sibling (#3412) which mounts at `composio.experimental.update_acl(id, opts)` Moved to `composio.experimental.updateAcl(id, opts)` as a method on a new `Experimental` class. Top-level `experimental_*` prefix is now reserved for stateless factories, matching the Python parity. P2.2 — `ToolRouterSession.authorize` was re-inlining the same camelCase→snake_case wire mapping that `ConnectedAccounts.link` already encoded. Extracted `serializeExperimentalForWire` / `serializeAclConfigForWire` into `models/Experimental.ts` and imported both call sites from there. Next field added to the experimental block now lands in one place. P2.3 — `AuthorizeOptionsSchema` was a structural duplicate of `ConnectedAccountExperimentalSchema`. Composed from the canonical schema instead. P2.4 — Substring match `acl_config_for_shared is only valid on SHARED` extracted to `ACL_ONLY_FOR_SHARED_ERROR_FRAGMENT` in `models/Experimental.ts` and reused from `ConnectedAccounts.link`, `ToolRouterSession.authorize`, and `Experimental.updateAcl`. Single source of truth so a server-side message tweak doesn't silently downgrade three call sites to generic BadRequestError. P2.5 — `ConnectedAccountsErrors.ts` `possibleFixes` strings on `ComposioSharedAccessDeniedError` and `ComposioSharedConnectionNotAccessibleError` were pointing at `composio.connectedAccounts.updateAcl()` (method now removed). Rewrote to `composio.experimental.updateAcl()` so the typed-error hint compiles. P2.6 — Telemetry bypass auto-fixed by P1.1. `Experimental` is now an instrumented class; methods on it get the same telemetry proxy as `ConnectedAccounts`. P2.7 — Inline `import('../types/connectedAccounts.types')` type at the old `serializeExperimentalForWire` declaration is gone with the function move. Sibling models use plain top-level imports. Tests: 919/919 pass, typecheck clean. **Push-back on remaining findings:** - P2.8 (`ComposioFailedToCreateConnectedAccountLink` missing `Error` suffix) — pre-existing naming, not introduced by this PR. Rename with back-compat alias is bigger scope; deferred. - P2.9 (TS Zod caps vs Python no caps) — the TS caps are a UX win (clear ValidationError vs server 400). Better direction is adding the caps to Python in a follow-up, not dropping them from TS. - All P3 nice-to-haves deferred. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
44972d90ad |
Merge remote-tracking branch 'origin/next' into feat/connected-accounts-experimental-py
# Conflicts: # python/composio/utils/schema_converter.py |
||
|
|
42ebff3f6b |
feat(connected-accounts): namespace SHARED-connection surface under experimental
Aligns the TypeScript SDK with the experimental wire shape used by
Shared Connections. The flat accountType / aclConfigForShared options
on connectedAccounts.link() and session.authorize() have moved under a
single experimental block, and connectedAccounts.updateAcl() has moved
off the class onto a top-level experimental_updateAcl(composio, id, opts)
export — same precedent as experimental_createTool /
experimental_createToolkit.
The experimental namespace is the signal that the shape may change in
future releases. Pinning a SHARED connection in a session config and
direct execute by connectedAccountId are unchanged — only the
connection-create / patch / authorize surfaces are namespaced.
Also surfaces the accountType filter on connectedAccounts.list() so
SHARED connections can be listed without dropping to the raw client.
The wire keeps this as a flat query param, so the SDK keeps it flat too.
@composio/client bumped from 0.1.0-alpha.71 -> 0.1.0-alpha.72 so the
generated typed client carries the Experimental namespaces for
link.create, toolRouter.session.link, and connectedAccounts.patch.
Caller migration:
// before
await composio.connectedAccounts.link('user_id', 'auth_config_id', {
accountType: 'SHARED',
aclConfigForShared: { allowAllUsers: true },
});
await composio.connectedAccounts.updateAcl('ca_abc', { allowAllUsers: true });
await session.authorize('github', {
accountType: 'SHARED',
aclConfigForShared: { allowAllUsers: true },
});
// after
await composio.connectedAccounts.link('user_id', 'auth_config_id', {
experimental: {
accountType: 'SHARED',
aclConfigForShared: { allowAllUsers: true },
},
});
await experimental_updateAcl(composio, 'ca_abc', { allowAllUsers: true });
await session.authorize('github', {
experimental: {
accountType: 'SHARED',
aclConfigForShared: { allowAllUsers: true },
},
});
// new — list SHARED connections
const shared = await composio.connectedAccounts.list({
accountType: 'SHARED',
userIds: ['user_creator'],
});
Tests cover: experimental block forwarding (link + authorize), no-op
when omitted, empty-array preservation, typed error mapping for the
PRIVATE-with-ACL case, experimental_updateAcl body construction +
deny-list handling + ValidationError when no fields are provided, and
list(accountType: 'SHARED') flat-filter delegation.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
69e6ef6495 |
chore(cli): drop darwin-x64 local tools, bundles, and enhanced controls (#3421)
## Summary - Remove darwin-x64 from local toolkit platform lists (beeper-imessage, peekaboo, chrome-devtools) and drop the corresponding bundled binary path entries. - Skip building native Swift sidecar binaries (peekaboo, imessage-cli, composio-native-ui) for darwin-x64; remove the bun-darwin-x64 matrix entry from `build-cli-binaries.yml` so we no longer produce a darwin-x64 CLI bundle. - Locally force-disable enhanced controls / elicitation on darwin-x64 in `tool-permissions.ts` even when the backend opts the org in (logs a debug message). ## Test plan - [x] `pnpm --filter @composio/cli typecheck` - [x] `pnpm --filter @composio/cli-local-tools typecheck` - [ ] CI green on the build workflow (no darwin-x64 job runs) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
d6bf4370d7 |
feat(cli): add enhanced permission cache gating (#3419)
## Summary - Add a CLI consumer permission cache backed by `~/.composio/tool-permissions-cache.json` with a 5 minute TTL. - Read enhanced-controls state from `/api/v3.1/org/consumer/config` and resolve stored connected-account permissions from `/api/v3.1/consumer/permissions/resolve`. - Thread consumer cache scope through Tool Router session creation so CLI link sessions use the enhanced public link URL when enhanced controls are enabled. - Add execute/run-compatible gating: CLI execute checks cached permission config before the Tool Router execute call and opens the bundled macOS native UI sidecar for ask modes. - Use the sidecar `--callback-file` JSON decision channel, pass the selected connection `word_id` to the UI account line, and treat no response within 30 seconds as denial. - Fall back to browser approval when the native sidecar is unavailable/non-macOS. ## Stack - Base PR: #3418 (`pi/swift-sidecar-ui-dfceb48e`) — native UI sidecar. - This PR: CLI permissions cache and native sidecar gating integration. ## Tests - `pnpm --filter @composio/cli typecheck` - `pnpm exec eslint ts/packages/cli/src/effects/create-tool-router-session.ts ts/packages/cli/src/services/tools-executor.ts ts/packages/cli/src/services/native-ui-sidecar.ts ts/packages/cli/src/services/tool-permissions.ts` - `pnpm --filter @composio/cli build` - `pnpm --filter @composio/cli-local-tools build:composio-native-ui -- --target darwin-arm64` - Earlier on this branch: `pnpm install --frozen-lockfile`, `pnpm build:packages` ## Notes / Risks - Native approval UI is macOS-only. Non-macOS or missing sidecar binaries fall back to the temporary browser approval page. - The CLI gates locally and does not pass `experimental.permissions` into Tool Router sessions yet, because direct CLI execute does not provide MCP elicitation transport. It does pass `experimental.link_url_overwrite` for enhanced link flows. - On a cold cache, the first consumer Tool Router session creation refreshes permission state synchronously; fresh cache entries are returned immediately while a background refresh updates disk for future calls. |
||
|
|
7477aa9566 |
feat(cli): scaffold native UI sidecar (#3418)
## Summary - Scaffold a macOS Swift `composio-native-ui` sidecar with a borderless floating native overlay and Metal-driven pulsing/liquid-glass visual treatment. - Add a hidden/dev `composio dev native-ui` command that spawns the bundled sidecar from CLI local-tool assets. - Wire the sidecar into local-tool binary build scripts and CLI binary release packaging checks for Darwin artifacts. ## Tests - `pnpm install --frozen-lockfile` - `pnpm typecheck` - `pnpm --filter @composio/cli build` - `pnpm --filter @composio/cli-local-tools build:composio-native-ui -- --target darwin-arm64` - Manual launch via `COMPOSIO_LOCAL_TOOLS_BIN_DIR=../cli-local-tools/local-tools-binaries bun dist/bin.mjs dev native-ui --timeout 35` ## Notes / Risks - This is a scaffold/prototype and is intentionally opened as a draft PR. - The visual effect uses a transparent AppKit panel, `NSVisualEffectView`, and a Metal overlay. True optical distortion of arbitrary content behind the window would require a different approach such as ScreenCaptureKit/backdrop sampling and associated permissions. - Generated sidecar executables remain ignored; release jobs rebuild them before packaging artifacts. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
126b79cdbf |
docs: update CLAUDE.md for composio SDK (#3396)
# Description Weekly automated CLAUDE.md refresh. Updates stale CLAUDE.md files to reflect recent codebase changes. Files updated: - `CLAUDE.md` — 403 -> 97 lines. Rewrote to current state: removed stale `examples/` top-level entry, added `cli-keyring` and `cli-local-tools` packages, noted default branch is `next`, kept the Bun version-mismatch gotcha and the e2e Docker note, pointed agents at `AGENTS.md`, `docs/CLAUDE.md`, and `ts/packages/cli/AGENTS.md`. - `ts/packages/cli/AGENTS.md` (which `ts/packages/cli/CLAUDE.md` symlinks to) — 379 -> 197 lines. Replaced the outdated command table (the `manage` namespace was removed in #2937 and many new top-level commands were added: `agent`, `auth-configs`, `connected-accounts`, `orgs`, `projects`, `toolkits`, `tools`, `triggers`, `logs`, `init`, `install`, `signup`, `proxy`, `listen`, `run`, `dev`, `artifacts`, `config`, `local-tools`). Added a note that `@composio/cli-keyring` powers OS credential storage. Dropped duplicate Effect / Clack "Reference Source" sections (already consolidated). Kept the load-bearing pieces: required typecheck, output-conventions (stdout vs stderr), Effect patterns, release workflow. - `docs/CLAUDE.md` — unchanged. Already current (last updated 2026-04-21) and within the 30-70 line target at 107 lines; the `.claude/` subtree matches what it documents. # How did I test this PR - Verified line counts: root 97 (target 60-150), `docs/CLAUDE.md` 107 (unchanged), `ts/packages/cli/AGENTS.md` 197. - Cross-checked the CLI command table against `ts/packages/cli/src/commands/` (`ls ts/packages/cli/src/commands/`) and against recent commits (`02e72116d`, `3415a4a15`, `d1ef6b25e`, `67867aea1`). - Cross-checked `ts/packages/` listing against the structure block in the root `CLAUDE.md` (cli, cli-keyring, cli-local-tools, core, json-schema-to-zod, providers, ts-builders). - Confirmed `ts/packages/cli/CLAUDE.md` is still the symlink to `AGENTS.md` after rewriting. Origin: cron-update-claude-docs / [zen-cron-248f7d9ad575](https://zen-api-production-4c98.up.railway.app/dashboard/#/chat/zen-cron-248f7d9ad575) Triggered by: karan@composio.dev | Source: cron Session: https://zen-api-production-4c98.up.railway.app/dashboard/#/chat/zen-cron-248f7d9ad575 |
||
|
|
02723698b0 |
Release: update version (#3402)
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to next, this PR will be updated. # Releases ## @composio/cli-local-tools@0.0.3 ### Patch Changes - Updated dependencies [ |
||
|
|
a202b9ea90 |
docs(connected-accounts): drop residual "at create time" wording in error class
Two more spots leaking the same immutability wording removed from the upstream API description: - ComposioAclOnlyForSharedError possibleFixes said "Set accountType: 'SHARED' at create time". Reworded to "Use accountType: 'SHARED'". - ComposioSharedConnectionNotAccessibleError JSDoc said "caught at session-create time". Replaced "caught" framing with "Raised at session-create time" — "session-create time" stays because it's user-facing (tells the SDK caller when the error is raised, i.e. during session.create() / session.patch()). Also tightened the surrounding wording — class doc cross-references the actual SDK method names (`toolRouter.session.create()` / `session.patch()`) instead of abstract phrasing. No behaviour changes — docstring cleanup only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
10b914fd43 |
docs(connected-accounts): drop residual internal references
Final sweep caught three more spots leaking internal detail: - `CreateConnectedAccountLinkOptionsSchema.aclConfigForShared` JSDoc said "the backend rejects ACL on a PRIVATE connection". Replaced with "raises ComposioAclOnlyForSharedError on a PRIVATE connection" — describes the SDK contract from the caller's perspective. - `UpdateConnectedAccountAclParamsSchema` JSDoc had a parallel "Backend rejects ACL writes on a PRIVATE connection" sentence. Reworded the same way. - Test comment in toolRouter.test.ts had a "Bugbot-flagged gap" annotation referencing internal review tooling. Replaced with a neutral description of what the tests verify. No behaviour changes — JSDoc / comment cleanup only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
382ffe5ee9 |
docs(connected-accounts): drop "set at creation time only" wording
Two more JSDoc spots — `ConnectedAccountTypes` and the `accountType` field on `CreateConnectedAccountLinkOptionsSchema` — claimed `accountType` was "set at creation time only — cannot be changed later". The wording has been removed from the corresponding API parameter description upstream, so the SDK shouldn't echo it independently. No behaviour changes — JSDoc-only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
eba561f771 |
docs(connected-accounts): sanitize public docstrings — remove internal references
Addresses 4 review comments from @abir-taheer on #3392: - transformers/connectedAccounts.ts:21 — remove Hermes PR references - types/connectedAccounts.types.ts:79 — users don't belong to projects - types/connectedAccounts.types.ts:55 — drop backend storage detail - models/ToolRouterSession.ts:330 — remove internal information Swept the full PR diff for similar leaks rather than just the four flagged lines, since the same patterns repeat across the new files: - Removed Hermes PR numbers (#9860 / #9882 / #9902) from inline comments and JSDoc in transformers, types, model, test describe block, and changeset. - Removed "JSONB column on `connected_accounts`" storage detail. - Reworded "any user_id in the project" / "users in the project" / "project member" / "project/org API key" — users don't belong to a project entity in Composio's data model, so the wording was misleading. Replaced with phrasing focused on the mechanism (pinning in a tool-router session, authorisation via creator or API key) and on the `userId` identifier. - Removed "Backend response: 400 with code `ConnectedAccount_...`" blocks from error class JSDoc — surfacing the internal error code name leaked implementation details. - Cleaned up the augmented `RawConnectedAccountResponseWithLabels` intersection — `account_type` and `acl_config_for_shared` are now on the regenerated `@composio/client@0.1.0-alpha.71` types, so the manual augmentation lines (which carried the Hermes refs) can be deleted entirely. Field access still works through the existing intersection used for `word_id` / `alias`. Also tightened a pre-existing leak I introduced earlier in the PR's own JSDoc on `update()` — dropped the "historical JSDoc mentioning alias/credentials" callout since that's internal noise. No behaviour changes — pure docstring / comment / changeset cleanup. Verified: pnpm typecheck clean, 915 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
14a5b52b60 |
fix(connected-accounts): validate ACL input in ToolRouterSession.authorize()
Bugbot caught a parity gap (cursor[bot] review on #3392): authorize() accepted aclConfigForShared and passed it straight to the wire, while ConnectedAccounts.link() validated through CreateConnectedAccountLinkOptionsSchema (which enforces the 1000-entry list cap and 1..256 char user_id length from ConnectedAccountAclConfigSchema). Callers using authorize() with oversized lists or invalid user IDs got opaque backend 400s instead of clear SDK-level ValidationError, breaking the changeset's claim that "The SDK enforces these caps via Zod at the input boundary." Added a local `AuthorizeOptionsSchema` (callbackUrl + alias + accountType + aclConfigForShared) and a safeParse + ValidationError throw at the top of authorize(), mirroring the pattern in link() / updateAcl(). The shape is identical to link's options sub-shape so the same caps apply. Tests (toolRouter.test.ts): - forwards accountType + nested acl_config_for_shared on the wire - throws ValidationError when allowedUserIds exceeds 1000 entries - throws ValidationError when a user_id exceeds 256 chars - throws ValidationError when a user_id is empty 915 tests pass (4 new + 911 prior). pnpm typecheck clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
49a23fed24 |
fix(cli): add account_type to SessionLinkResponse test mocks
@composio/client@0.1.0-alpha.71 (just bumped in
|
||
|
|
483af36070 |
feat(connected-accounts): bump @composio/client to alpha.71, drop casts, add tests + error mapping
Now that #77 in composio-base-ts merged and @composio/client@0.1.0-alpha.71 is published with account_type + acl_config_for_shared in the typed surface, all the forward-compat shims come out. Removed: - AclConfigWireShape, LinkCreateBodyWithAcl, ConnectedAccountPatchBodyWithAcl local types - 3x `as unknown as Parameters<typeof X>[N]` casts in ConnectedAccounts.ts + ToolRouterSession.ts Now uses the generated types directly: - ConnectedAccountPatchParams, ConnectedAccountPatchResponse from @composio/client/resources/connected-accounts - LinkCreateParams + LinkCreateParams.ACLConfigForShared from @composio/client/resources/link - SessionLinkParams + SessionLinkParams.ACLConfigForShared from @composio/client/resources/tool-router/session/session Review fixes from #3392 multi-agent review: - P1-1: moved orphaned JSDoc back onto ComposioLegacyConnectedAccountsEndpoint- RetiredError (was stranded above ComposioSharedAccessDeniedError) - P1-2: added empty-array footgun warning to updateAcl() JSDoc — passing `notAllowedUserIds: []` silently clears the deny list - P1-3: changeset reconciled with PR body (Python ships as separate PR) - P2-9: updateAcl() returns ConnectedAccountPatchResponse instead of void, matching sibling update()/refresh() ergonomics - P2-11: clarifying JSDoc on update() pointing at updateAcl() and noting the pre-existing "alias/credentials" doc is inaccurate (this PR doesn't fix it) - P3-12: callbackUrl/alias guards normalized to `!== undefined` (was a mix of `&&` and `!= null`) — empty strings now propagate correctly - P3-17: refine-guard comment on UpdateConnectedAccountAclParamsSchema noting ZodEffects doesn't expose .shape P2-6/P2-7: typed error mapping for ComposioAclOnlyForSharedError (400) wired at three call sites: - ConnectedAccounts.link() — wraps existing ComposioFailedToCreateConnectedAccountLink catch - ConnectedAccounts.updateAcl() — new catch with rethrow fallback - ToolRouterSession.authorize() — new catch with rethrow fallback Substring match on `'acl_config_for_shared is only valid on SHARED'` — verified against apps/apollo/src/lib/connected_accounts/createConnectedAccount.ts in hermes#9902. ComposioSharedAccessDeniedError and ComposioSharedConnectionNotAccessibleError remain exported but not yet thrown — they'll be wrapped when Tools.execute() and ToolRouterSession.create() error-mapping lands in a follow-up. Tests: 12 new behaviour tests in test/connectedAccounts/connectedAccounts.test.ts covering link() ACL forwarding (5), updateAcl() body construction + empty-object refine + AclOnlyForShared mapping (6), and link() error-mapping fallback (1). 911 tests pass (up from 899). Verified: pnpm typecheck clean, pnpm build clean (publint + attw clean). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
752efd8863 |
refactor(connected-accounts): nest ACL under aclConfigForShared, match merged 9902 contract
The original draft built against 9902's PR description shape — three flat
top-level ACL fields (`allow_all_users`, `allowed_user_ids`,
`not_allowed_user_ids`). The merged design (deployed to staging now)
collapsed them into a single JSONB column and exposes them on the wire
as a nested `acl_config_for_shared` object. This commit reshapes the SDK
to match.
Wire contract changes verified against staging-backend.composio.dev:
POST /connected_accounts/link body: account_type, acl_config_for_shared
POST /connected_accounts body.connection.{account_type, acl_config_for_shared}
PATCH /connected_accounts/{id} body: alias, connection, acl_config_for_shared
GET /connected_accounts item.{account_type, acl_config_for_shared?}
GET /connected_accounts/{id} response.{account_type, acl_config_for_shared?}
POST /tool_router/session/{id}/link body: account_type, acl_config_for_shared
SDK changes:
- types: `ConnectedAccountAclSchema` → `ConnectedAccountAclConfigSchema`
(input — all fields optional) + `ConnectedAccountAclConfigResponseSchema`
(output — all fields populated when block is visible). Added per-user_id
length cap (1..256) matching aclConfig.ts. `link()` options exposes
`aclConfigForShared?` instead of three flat fields. Retrieve response
exposes `aclConfigForShared?` (undefined when caller can't see ACL).
- model: `link()` and `updateAcl()` serialize the SDK's flat camelCase
ACL params into the nested snake_case `acl_config_for_shared` wire
block via a new `serializeAclConfigForWire` helper. Local body types
updated to match.
- transformer: maps `acl_config_for_shared` (nested) → `aclConfigForShared`
(nested camelCase). Forwards `undefined` when the block is absent.
- ToolRouterSession.authorize() options gain `accountType` +
`aclConfigForShared` — the `/tool_router/session/{id}/link` endpoint
accepts the same fields.
- changeset rewritten to document the nested shape.
Verified: pnpm typecheck clean, build clean, 899 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
f273e95f92 |
docs: update CLAUDE.md for composio SDK
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
84a3a074b3 |
feat(connected-accounts): surface accountType + per-user ACL on SHARED connections
Adds SDK wrappers for Hermes #9860, #9882, #9902 — three Apollo-side features that previously had no high-level surface. Existing call sites are unchanged; new fields/methods are opt-in. - `link()` accepts `accountType` ('PRIVATE' | 'SHARED') and ACL fields (`allowAllUsers`, `allowedUserIds`, `notAllowedUserIds`) to create a SHARED connection in one call. - `get()` / `list()` responses now expose `accountType`. ACL fields are forwarded when present (backend hides them for non-creator/non-API-key callers — left as undefined in the SDK shape). - New `updateAcl(nanoid, params)` method wires the existing `client.connectedAccounts.patch` (PATCH /connected_accounts/{id}) for ACL writes. PATCH semantics: omit a field to leave unchanged; pass empty array to clear an allow/deny list. At least one field required. - New error classes: `ComposioSharedAccessDeniedError` (403), `ComposioAclOnlyForSharedError` (400), `ComposioSharedConnectionNotAccessibleError` (400). The wire-level fields (account_type, allow_all_users, etc.) are not yet in @composio/client@0.1.0-alpha.70's typed surface — they'll land when Stainless regenerates against the post-merge backend spec. Two narrow local types (`LinkCreateBodyWithAcl`, `ConnectedAccountPatchBodyWithAcl`) + boundary casts paper over the gap until then; remove once the client is bumped. Verified: pnpm typecheck clean, build clean, 899 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c358ffaa3b |
fix(connected-accounts): SEC-339 gate initiate() warning on response Deprecation header
initiate() previously emitted a one-time deprecation warning whenever the
response carried a redirectable OAuth scheme (OAUTH1, OAUTH2, DCR_OAUTH),
regardless of whether the auth config was Composio-managed (subject to the
2026-07-03 cutover) or custom (unaffected). The wording was conditional —
'If this auth config is Composio-managed…' — so callers using their own
OAuth apps could ignore it, but the warning still printed and added noise
to logs.
Apollo already emits the SEC-339 'Deprecation' / 'Sunset' / 'Link
rel="deprecation"' headers (RFC 9745 / RFC 8594) only on the retiring
branch — managed + redirectable OAuth + LD didn't block. The SDKs now
read the 'Deprecation' header from the response and gate the warning on
its presence. Custom auth configs and non-OAuth schemes get a clean
response from the server and now stay silent in the SDK as well.
TS:
- Chain '.withResponse()' on the underlying client.connectedAccounts.create
call to expose the raw Response. Defensive fallback for tests that mock
create() as a plain Promise.
- Drop the LEGACY_RETIRING_OAUTH_SCHEMES set; the apollo header is now the
sole signal.
- New tests in describe('initiate deprecation header gate', ...) pin the
contract: warns when Deprecation is present, silent when absent, and
one-time-per-process even across multiple managed-OAuth calls. A
mockApiPromiseWithHeaders helper wraps mocked values as APIPromise-shape
thenables so the new tests can simulate apollo's header behavior.
Python:
- Switch to client.connected_accounts.with_raw_response.create so we can
read raw.headers.get('Deprecation'). Defensive fallback to the parsed-
only path for test mocks that don't stub with_raw_response.
- Drop _LEGACY_RETIRING_OAUTH_SCHEMES; same simplification as TS.
- New TestInitiateDeprecationHeaderGate class with the same three pinning
cases. A _set_initiate_response helper routes mock responses through
the with_raw_response surface that initiate() now consumes. Pre-existing
initiate tests migrated to the helper; one assertion that inspected
create.call_args.kwargs now reads with_raw_response.create.call_args.kwargs.
No public API change for either SDK — initiate() returns the same
ConnectionRequest shape and respects the same allowMultiple guard.
ComposioLegacyConnectedAccountsEndpointRetiredError continues to surface
from the 400 retired-path response.
Changeset bumps @composio/core as a patch.
|
||
|
|
e14e61c051 | Fix provider release versions to 0.9.0 | ||
|
|
49629a7b9d | Release: update version | ||
|
|
a4c9e0ada2 |
refactor(cli): define local tools as custom toolkits (#3356)
## Summary - Stacks this local-tools PR on top of #3360, which contains the core duplicate custom-toolkit child slug fix. - Refactors `@composio/cli-local-tools` to define bundled local toolkits with core `experimental_createTool` / `experimental_createToolkit` handles instead of hand-rolled schema objects. - Keeps Tool Router v3.1 inline custom toolkit definitions attached to session create/search/execute calls so bundled local tools remain searchable/executable. - Adds CLI/local-tools test coverage for forwarding local custom toolkit payloads and for core custom toolkit handles from the local registry. ## Stack - Base PR: #3360 (`fix(core): qualify custom toolkit child slug lookups`) - This PR should now show only CLI/local-tools changes relative to #3360. ## Tests - `pnpm --filter @composio/core typecheck` - `pnpm --filter @composio/cli-local-tools typecheck` - `pnpm --filter @composio/cli typecheck` - `pnpm --filter @composio/cli-local-tools test` - `pnpm --filter @composio/cli-local-tools build` - `pnpm --filter @composio/cli exec vitest run test/src/commands/tools/tools.search.cmd.test.ts test/src/commands/tools/tools.execute.cmd.test.ts` - `pnpm --filter @composio/core exec vitest run test/models/customTool.test.ts test/models/toolRouter.test.ts test/models/customToolRouting.test.ts` |
||
|
|
d31efcb160 |
fix(core): qualify custom toolkit child slug lookups (#3360)
## Summary
- Fixes SDK custom-tool mapping for custom toolkits that reuse the same
child tool slug, e.g. `APP_A.VERSION` and `APP_B.VERSION`.
- Adds toolkit-qualified lookup (`toolkit + original slug`) while
keeping bare original-slug lookup only when it is unambiguous.
- Throws a client-side ambiguity error for manual
`session.execute('VERSION')` when multiple custom toolkit tools share
`VERSION`, instead of falling through to backend execution.
- Keeps `session.customToolkits()` / `session.customTools()` mapped to
the backend-assigned final slugs for duplicate child names.
## Repro / validation
Validated locally with a temporary Tool Router script (not committed)
using two dummy custom toolkits that both define `VERSION`:
- Current `next` SDK fails before high-level use with `Custom tool slug
collision: original slug "VERSION" maps to multiple final slugs...`.
- Tool Router backend accepts the same payload and returns both
`LOCAL_DUMMY_APP_A_REPRO_VERSION` and `LOCAL_DUMMY_APP_B_REPRO_VERSION`.
- This branch builds the SDK map successfully and high-level SDK
execution routes each final slug to its own internal handler:
- `LOCAL_DUMMY_APP_A_REPRO_VERSION` -> `{ app: "A", version: "1.0.0" }`
- `LOCAL_DUMMY_APP_B_REPRO_VERSION` -> `{ app: "B", version: "2.0.0" }`
## Tests
- `pnpm --filter @composio/core typecheck`
- `pnpm --filter @composio/core exec vitest run
test/models/customTool.test.ts test/models/toolRouter.test.ts
test/models/customToolRouting.test.ts`
|
||
|
|
fdf4e85350 |
Refine ToolRouter preload and generated attach support (#3364)
## Summary - Add public direct-tools preset constants (`SessionPreset.DIRECT_TOOLS` in TS, `SESSION_PRESET_DIRECT_TOOLS` in Python) and internal `preload.tools = "all"` constants. - Reuse the create-time inline custom tool preload preparation path for `use(..., customTools/customToolkits)` attach flows, including existing-session `preload.tools = "all"` handling for attached customs. - Use generated Stainless attach types where available; keep a narrow Python additive type for the custom-definition `preload` hint until Stainless exposes that field. - Clean up user-facing preload docs/comments, direct custom tool description prefix, and direct/preload examples with normalized `LOCAL_*` assertions. - Add separate changesets for preload behavior and the direct-tools preset. ## Validation - `pnpm --dir ts/packages/core typecheck` - `pnpm --dir ts/packages/core test test/models/toolRouter.test.ts test/models/customTool.test.ts` - `(cd python && .nox/chk/bin/mypy --config-file config/mypy.ini composio/)` - `COMPOSIO_CACHE_DIR=/private/tmp/composio-cache python/.nox/chk/bin/python -m pytest python/tests/test_tool_router.py python/tests/test_custom_tools.py` - `python/.nox/chk/bin/python -m ruff check python/composio/core/models/tool_router.py python/composio/core/models/custom_tool_types.py python/composio/core/models/inline_custom_tools_payload.py python/composio/core/models/custom_tool.py python/composio/core/models/tool_router_constants.py python/tests/test_tool_router.py` - `python/.nox/chk/bin/python -m ruff check python/examples/tool_router/direct_tools_preset.py` - `python/.nox/chk/bin/python -m py_compile python/examples/tool_router/direct_tools_preset.py` - `git diff --check` |
||
|
|
b48711c587 | Clarify custom preload use behavior | ||
|
|
04545a72d3 |
fix(core): expose string | string[] in connectedAccounts public type (#3365)
## Summary Follow-up to #3358. The `.transform()` added on the `connectedAccounts` Zod schema made the inferred TypeScript type resolve to the **post-transform output** (`Record<string, string[]>`), so TS users still hit `error TS2322: Type 'string' is not assignable to type 'string[]'` even though the runtime accepted strings. The runtime fix landed; the public TS surface didn't follow. This PR moves the coercion out of the schema and into `ToolRouter.create`, mirroring the Python implementation. The public type is now `Record<string, string | string[]>` and runtime behavior is unchanged. ## Why CI didn't catch this in #3358 The PR's own test file (`toolRouter.test.ts`) already assigns a `string` to `ToolRouterCreateSessionConfig`, but `ts/packages/core/tsconfig.json` has `"include": ["src/**/*.ts"]` — `test/` is not typechecked. So `tsc --noEmit clean` was technically true while masking the issue. Verified empirically by dropping a typecheck file into `src/` on `next`: ``` src/__type_check.ts(8,7): error TS2322: Type 'string' is not assignable to type 'string[]'. ``` After this PR, the same file compiles cleanly. ## Changes - **`ts/packages/core/src/types/toolRouter.types.ts`**: drop `.transform()` from the `connectedAccounts` schema; `z.infer` now exposes `Record<string, string | string[]>`. - **`ts/packages/core/src/models/ToolRouter.ts`**: coerce `string → [string]` inside `create` before sending to the backend (which expects arrays). Preserves the original `connected_accounts: undefined` behavior when the field is omitted (the parent schema's `.partial()` strips the `default({})`). - **`ts/packages/core/src/types/toolRouter.types.ts`**: fix stale `@param {Record<string, string>}` JSDoc on the same field. - **`.changeset/v31-connected-accounts-array.md`**: drop the inaccurate *"Bumps `@composio/client` to `0.1.0-alpha.70`"* line — that bump landed in a separate commit on `next` (`7c1443838`), not in #3358's diff (`git diff 2bbd791de^1 2bbd791de` shows zero `pnpm-lock.yaml`/`package.json` changes). - **`.changeset/fix-connected-accounts-string-type.md`**: new `patch` changeset for `@composio/core`. ## Test plan - [x] `pnpm exec tsc --noEmit -p tsconfig.json` clean on `@composio/core` - [x] `pnpm exec vitest run` — 883/883 tests pass (incl. 110 in `toolRouter.test.ts`) - [x] `pnpm prettier --check` clean on touched files - [x] Spot-checked: assigning `{ connectedAccounts: { gmail: 'ca_xxx' } }` to `ToolRouterCreateSessionConfig` now typechecks; assigning the array form still typechecks. |
||
|
|
bccd32beae | Refine ToolRouter preload docs and constants | ||
|
|
c96f094b15 |
feat(core): add session.update() for partial config updates (#3362)
## Summary
- Adds `session.update()` method to both TypeScript and Python SDKs
- Calls the existing `PATCH /api/v3/tool_router/session/{id}` endpoint
- Accepts the same config shape as `create()` (toolkits, tools, tags,
auth_configs, connected_accounts, manage_connections, workbench,
multi_account, preload)
- Mutates the session object in-place (preload, configVersion, warnings)
## Usage
### TypeScript
```typescript
const session = await composio.create('user_123', {
toolkits: ['gmail'],
manageConnections: true,
});
await session.update({
toolkits: { enable: ['gmail', 'github'] },
workbench: { enable: false },
});
```
### Python
```python
session = composio.create(user_id='user_123', toolkits=['gmail'])
session.update(
toolkits={'enable': ['gmail', 'github']},
workbench={'enable': False},
)
```
## Test plan
- [x] TypeScript: `tsc --noEmit` passes
- [x] TypeScript: all 874 existing tests pass
- [x] Python: mypy passes
- [x] Python: ruff lint + format clean
- [x] Python: all 82 tool_router tests pass
- [ ] Manual test: create session, call `session.update()`, verify
config changes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|