Commit Graph

117 Commits

Author SHA1 Message Date
Kshitij Jhunjhunwala 14011b9057 fix(e2e): scope node_modules dockerignore to the CLI image only
A root .dockerignore excluding **/node_modules broke Dockerfile.node's
runtime fixtures: suites without a setup phase (claude-agent-sdk) resolve
deps through node_modules copied in via COPY ts/e2e-tests/. BuildKit's
per-Dockerfile ignore keeps the exclusion for Dockerfile.cli, which
installs inside the image and must not see host pnpm symlinks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-28 13:21:49 -07:00
Kshitij Jhunjhunwala fc1460995b feat(cli): make headless composio login agent-friendly (PRDE-1138)
Teach non-interactive login to reuse an existing READY agent identity without creating one implicitly. Preserve explicit --no-browser and --no-wait contracts, and branch on TerminalUI.canPrompt so piping stdout alone remains interactive.

Add unattended guidance, installer analytics attribution, and focused unit and Docker E2E coverage. Exclude host node_modules from Docker build contexts.
2026-07-28 20:13:57 +05:30
Alberto Schiabel 503b50ab02 chore(deps): refresh SDK, Python, and CI dependencies (#3955)
This PR:

- splits https://github.com/ComposioHQ/composio/pull/3953 in two: this
PR carries every dependency and GitHub Actions bump **except** the docs
site, which follows in a stacked PR
- consolidates and supersedes Dependabot PRs #3915, #3916, and #3934
through #3942
- adopts TypeScript 7.0.2 for primary compilation while retaining the
`@typescript/typescript6` API lane that TypeScript-ESLint still
requires, following the upstream side-by-side guidance
- refreshes Python core and provider dependencies, lockfiles, and the
Ruff 0.16 lint configuration
- updates every GitHub Action with a verified newer official release,
including majors, while retaining immutable commit SHA pins and
migrating setup-uv cache pruning
- deletes four per-package `eslint.config.mjs` shims: under ESLint 10
the default per-file config lookup re-anchors the root config's globs
into each package, so `pnpm lint` stayed green while the CLI's
try/catch, `process.env` and node-builtin bans went unenforced
- bounds and documents the new `brace-expansion` and `@hono/node-server`
security overrides, raising the `@hono/node-server` floor to 2.0.10 to
clear GHSA-9mqv-5hh9-4cgg
- preserves intentional compatibility fixtures and lanes for AI SDK 6,
Zod 3, TypeScript 5.8, Mastra AI SDK 5, and Python provider constraints

## Context

The docs site is a separate Bun workspace with its own `bun.lock` and is
not a pnpm workspace member, so the two halves share no lockfile and no
build. Splitting them keeps the Fumadocs 11 migration (a breaking API
change with real refactoring) reviewable on its own, independently of
the mechanical version bumps here.

The `brace-expansion` override deliberately spans majors:
GHSA-mh99-v99m-4gvg (HIGH) is published as a single `<=5.0.7` range with
no 1.x or 2.x backport, so narrowing it to the 5.x line puts
`brace-expansion` 2.1.2 back under `core>minimatch>brace-expansion` and
`pnpm audit --prod --audit-level=high` exits 1. Verified both ways; the
trade-off it buys is recorded inline in `pnpm-workspace.yaml`.

Verified on this branch standalone: `pnpm install --frozen-lockfile`,
`pnpm lint`, `pnpm typecheck`, `pnpm build:packages`, `pnpm test` (963
tests, 26/26 tasks), and `pnpm audit --prod --audit-level=high`.
2026-07-27 17:57:29 +05:30
Alberto Schiabel 473e9d20ad fix(cli): make version update checks reliable (#3952)
This PR:

- builds on top of https://github.com/ComposioHQ/composio/pull/3944
- reports `checkStatus: "unknown"` instead of fabricating an up-to-date
result when GitHub refreshes fail
- preserves the last successful release cache and throttles failed
attempts separately
- uses `Command.provideEffectDiscard` to start background checks after
parsing and skips explicit `composio version --check` invocations
- validates installed release versions before semver comparison
- adds deterministic unit concurrency coverage and compiled-binary CLI
E2E coverage

## Verification

- `pnpm --filter @composio/cli test` (`963` passed, `1` skipped)
- `pnpm typecheck` (`14/14` tasks)
- `pnpm build:packages` (`19/19` tasks)
- `pnpm --filter @e2e-tests/cli-version test:e2e:cli` (`9` passed)
- `pnpm build:binary` followed by `pnpm install:binary`
- installed Mach-O binary smoke checks for plain version, live and
cached `version --check`, unknown status, and both leading `--log-level`
forms
- scoped ESLint on all changed TypeScript files
- `git diff --check`

Repository-wide `pnpm lint` remains red on 52 existing errors across
unrelated docs and scripts; the changed TypeScript files pass scoped
ESLint.
2026-07-27 12:49:17 +05:30
Kshitij Jhunjhunwala 20273ea66e fix(cli): honor if-present for unsupported hosts 2026-07-14 19:35:10 -07:00
Kshitij Jhunjhunwala 2b375b4855 fix(cli): handle plugin setup errors gracefully 2026-07-14 19:20:57 -07:00
Kshitij Jhunjhunwala 460f804dd1 fix(cli): continue setup with supported hosts 2026-07-14 19:06:52 -07:00
Kshitij Jhunjhunwala d004b2a309 fix(cli): handle incompatible Codex plugin commands 2026-07-14 18:59:01 -07:00
Kshitij Jhunjhunwala 82341643a4 feat(cli): add plugin uninstall flow 2026-07-14 15:54:54 -07:00
Kshitij Jhunjhunwala fb5e97749d feat(cli): install detected agent plugins 2026-07-14 15:54:36 -07:00
jkomyno 506c402e36 test(cli): prove plugin setup idempotence 2026-07-15 01:54:35 +04:00
jkomyno 42db6d13e1 fix(cli): simplify and harden plugin setup
Co-authored-by: Kshitij Jhunjhunwala <kj@composio.dev>
2026-07-14 15:51:53 +04:00
Kshitij Jhunjhunwala b4dbab5060 fix(cli): verify plugin setup state 2026-07-13 19:20:10 -07:00
Kshitij Jhunjhunwala d583e7ef6f fix(cli): harden plugin setup installation 2026-07-13 15:19:38 -07:00
Alberto Schiabel fbcf08136d revert(core): defer v1 session alias removal (#3826)
This PR:
- reverts https://github.com/ComposioHQ/composio/pull/3780
- restores the TypeScript `composio.create()` and `composio.use()`
session aliases, with their runtime and type-test coverage
- restores the prior deprecation state for
`BaseProvider.wrapMcpServerResponse`
- removes the pre-v1 breaking-change changeset so the release PR no
longer advertises this removal

The v1 API-freeze change should be recreated later as a draft PR and
kept out of the merge queue until v1 is ready.
2026-07-14 01:01:18 +04:00
Alberto Schiabel 0de52639c4 feat(core)!: remove bare session aliases; freeze MCP SPI (#3780)
## What and why

This makes the intended v1 API cleanup real rather than postponing it to
v2:

- Remove the TypeScript root aliases `composio.create(...)` and
`composio.use(...)`. Session creation and reuse now live only at
`composio.sessions.create(...)` and `composio.sessions.use(...)`. This
is a deliberate breaking change, reflected by a major changeset.
- Retain `BaseProvider.wrapMcpServerResponse` as the stable v1 provider
SPI. Its earlier deprecation pointed to a method that was never
introduced.

The scope is intentionally narrow: it does **not** remove unrelated
deprecated APIs, and Python keeps its supported `Composio.create/use`
API. The TypeScript docs, examples, providers, runtime fixtures,
generated SDK reference, and API-reference indexes now use the
namespaced TypeScript API. Historical changelog examples are left as
history.

## Verification

- `pnpm typecheck`
- `pnpm --filter @composio/core test -- --run test/core/session.test.ts`
(42 files, 1,018 tests)
- `pnpm exec eslint ts/packages/core/src/composio.ts`
- `pnpm --filter @composio/core generate:docs`
- `cd docs && bun run generate:api-index`
- `cd docs && bun run types:check`
- `git diff --check` and targeted scans for removed TypeScript aliases

I also attempted the affected Node and Cloudflare runtime E2E suites.
They cannot initialize in this checkout without `COMPOSIO_API_KEY` (and,
for Cloudflare, `COMPOSIO_BASE_URL` and `OPENAI_API_KEY`); they did not
report a product assertion failure.
2026-07-13 13:22:55 +04:00
dependabot[bot] 4baacbeb77 chore(deps): bump the npm-production group across 1 directory with 7 updates (#3799)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: jkomyno <alberto@composio.dev>
2026-07-10 19:06:45 +04:00
Alberto Schiabel 58bc93b2d9 chore(deps): consolidate dependency updates (#3760)
This PR:
- consolidates https://github.com/ComposioHQ/composio/pull/3733,
https://github.com/ComposioHQ/composio/pull/3735 through
https://github.com/ComposioHQ/composio/pull/3744, and
https://github.com/ComposioHQ/composio/pull/3752
- refreshes the pnpm workspace dependencies under the existing
`minimumReleaseAge` supply-chain gate
- keeps latest compatible pins for ESLint 9, AI SDK 6, and Cloudflare
workers types 4 where latest majors conflict with the current workspace
- keeps zod-v3 runtime fixtures on `zod@3.25.76` while bumping the
workspace catalog to zod 4
- bumps Python `composio-client` to `1.42.0` and refreshes `uv.lock`
- updates the SHA-pinned Claude and Codex workflow actions from the
Dependabot action group
- adds a patch changeset for the versioned package manifests touched by
dependency updates
- verifies the rollup with frozen pnpm/uv locks, peer checks, audit
threshold checks, typecheck, lint, builds, TypeScript tests, and Python
`nox -s chk`

## Context

`pnpm audit --prod --audit-level=moderate` passes. The remaining
production audit item is a low `@ai-sdk/provider-utils` advisory through
Mastra transitive dependencies; forcing it higher would require leaving
the compatible stable Mastra dependency path.
2026-07-06 14:33:55 +04:00
Alberto Schiabel 03cb181fdb chore(deps): roll up dependency bumps (#3711)
This PR:
- rolls up https://github.com/ComposioHQ/composio/pull/3695,
https://github.com/ComposioHQ/composio/pull/3696,
https://github.com/ComposioHQ/composio/pull/3697, and
https://github.com/ComposioHQ/composio/pull/3698 into one
dependency-bump branch
- updates Python dependency metadata for `langchain-openai`,
`pyautogen`, and `crewai`
- updates npm production dependency metadata for `zod-to-json-schema`,
`openai`, and `@modelcontextprotocol/sdk`
- refreshes `uv.lock` and `pnpm-lock.yaml` with the repo-pinned package
managers
- leaves Changesets unchanged because the touched TS package manifests
are private/ignored and no published TS SDK package metadata changes
- verified with `pnpm install --frozen-lockfile`, `pnpm lint`, `pnpm
typecheck`, focused TS builds/tests, clean-worktree `pnpm
test:examples`, Python import tests, and Python nox checks
- note: local `pnpm build:packages` hit a pre-existing broad-build race
around `@composio/slim` rebuilding `@composio/core`; focused dependent
builds pass

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-29 19:20:15 +04:00
Alberto Schiabel 956f9be9b4 chore(agents): normalize repo guidance skills (#3666)
This PR:
- replaces the duplicated repo-local skill set with the requested
canonical `.agents/skills` taxonomy and short router `SKILL.md` files
backed by first-level references
- makes `.claude/skills` a compatibility symlink to `.agents/skills` and
removes hand-maintained Claude skill/rule copies
- moves docs agent guidance and decisions into neutral
`docs/agent-guidance/` and `docs/decisions/`, with `docs/CLAUDE.md`
reduced to a shim
- retires CLI Cursor rules after migrating CLI design, Effect source,
and client-cache sync guidance into `AGENTS.md` and `cli-command`
- adds nested `AGENTS.md` files for TS, core, providers, e2e, Python,
Python providers, and docs
- adds `pnpm validate:agent-skills` to validate skill frontmatter,
taxonomy, references, symlink invariants, stale paths, and command names
- implements missing Python `tst` and `snt` nox sessions that existing
Makefile targets already exposed
- no changeset: repository guidance/tooling only, no published SDK
package behavior

## Verification
- `pnpm validate:agent-skills` -> `Validated 14 canonical agent skills
and guidance invariants.`
- `for skill in .agents/skills/*; do python
/Users/jkomyno/.codex/skills/.system/skill-creator/scripts/quick_validate.py
"$skill" || exit 1; done` -> 14x `Skill is valid!`
- `pnpm --dir ts/packages/cli validate:skills` -> `Validated
composio-cli skill builds for stable and beta.`
- `cd python && uv run nox --list` -> includes `tst` and `snt`
- `cd python && uv run nox -s snt` -> 18 passed
- `cd python && uv run nox -s tst -- tests/test_imports.py` -> 8 passed
- `git diff --check` / `git diff --cached --check` -> clean
- stale reference search for retired docs/Claude/Cursor paths -> no
matches

## Forward Tests
- TypeScript core bug: loaded `bug-fixing`, `typescript-sdk`,
`typescript-testing`; found correct root/ts/core `AGENTS.md` route.
- Python provider: loaded `python-providers`, `python-testing`; found
missing nox sessions, fixed here.
- CLI command: loaded `cli-command`; found recording/changeset wording
gaps, fixed here.
- Cross-SDK drift: loaded `cross-sdk-parity`; again found Python nox
drift, fixed here.
- Docs + decision: loaded `docs-decisions`; found decision
template/index and Twoslash path gaps, fixed here.

## Notes
The first normal `git commit` attempt hit a lint-staged/Git stash
limitation while replacing `.claude/skills/` with a symlink (`path ...
beyond a symbolic link`). The final commit used `--no-verify` after the
validators and formatting checks above passed.
2026-06-27 00:35:57 +04:00
Alberto Schiabel cddd66c3ce chore(ts): bump Hono, Mastra, and Chrome deps (#3691)
This PR:
- bumps `hono`, `@mastra/core`, and `chrome-devtools-mcp` to their
current latest published versions
- routes the remaining Cloudflare Tool Router Hono consumer through the
workspace catalog
- updates the `@composio/mastra` `@mastra/core` peer range and adds a
patch changeset
- fixes `check-peer-deps` to resolve `semver` through the normal package
dependency
2026-06-26 20:45:25 +04:00
Alberto Schiabel 9ffc696a99 feat(vercel): support AI SDK v7 (#3683)
This PR:

- widens the `ai` peer dependency of `@composio/vercel` to `^6.0.0 ||
^7.0.0`, adding AI SDK v7 support and dropping the previously-untested
v5 arm
- adds Docker-based Node e2e compatibility suites for AI SDK v6 and v7
under `ts/e2e-tests/runtimes/node/vercel-ai-sdk-v{6,7}`, auto-discovered
by the existing e2e matrix (so PR CI exercises them)
- each installs the packed `@composio/vercel` tarball, typechecks the
provider against the target `ai` major, and asserts runtime tool
wrapping/execution (object inputs, JSON-string normalization via
`normalizeToolArguments`, `ToolSet` shape)
- the v7 suite additionally exercises v7's `ToolExecutionOptions` passed
to `tool.execute`
- ships a `minor` changeset (the peer-range narrowing removes a
previously-supported major)
- breaking:
- `ai@5` is no longer an accepted peer of `@composio/vercel`; v5
consumers should stay on the prior minor
2026-06-26 14:08:09 +04:00
Alberto Schiabel 20bf1b6345 chore(ts): quiet tsdown build warnings (#3665)
This PR:
- migrates shared tsdown dependency config from deprecated `external` /
`noExternal` aliases to `deps.neverBundle` / `deps.alwaysBundle`
- disables noisy Rolldown plugin timing and ineffective dynamic-import
diagnostics in shared config while keeping build checks enabled
- fixes the `json-schema-to-zod` `JSONSchema7TypeName` import so it
stays type-only
- keeps the CLI bundle graph aligned with `next` while quieting the
dynamic-import warning through `checks.ineffectiveDynamicImport: false`
- makes the Node file E2Es treat the current external storage
`Unauthorized` upload response as an explicit `UPLOAD_UNAVAILABLE`/skip
outcome instead of failing unrelated SDK build PRs

Verification:
- `pnpm build`
- build log scan for `WARN`, deprecated `external` / `noExternal`,
`deps.onlyBundle`, `PLUGIN_TIMINGS`, and `INEFFECTIVE_DYNAMIC_IMPORT`
- `pnpm --dir ts/packages/cli test -- --runInBand`
- `pnpm --dir ts/e2e-tests/runtimes/node/file-roundtrip typecheck`
- `pnpm --dir ts/e2e-tests/runtimes/node/tool-router-files typecheck`
- `pnpm lint:packages`
- CI: TypeScript build/typecheck/test and Node 22/24/25, Deno,
Cloudflare, and CLI e2e are green on the latest commit
2026-06-26 12:17:33 +04:00
Alberto Schiabel f8cd90ce5a chore(ts): adopt Node 24 and pnpm 11 toolchain (#3646)
This PR:

- uses plain `tsdown` package scripts and a shared typed
`tsdown.config.base.ts` so Node 24 builds work without loader flags
- switches the repo dev/build toolchain to Node `24.17.0` and pnpm
`11.8.0` through `mise.toml`, `mise.lock`, and `pnpm-lock.yaml`
- marks the root package as ESM with `type: module`, matching the
TypeScript packages
- keeps Node `22.22.3` in the runtime/E2E matrices as the minimum
supported user runtime
- changes the TypeScript build workflow back to a single build on the
mise-managed toolchain and broadens path filters for
package-manager/build config files
- adds pnpm 11 build-script policy with `allowBuilds` and intentionally
ignored `sharp` builds
- enables tsdown ESM shims for the packaged CLI wrapper so `composio
--help` runs under Node 22 and Node 24

Verified locally:

- `CI=true pnpm install --frozen-lockfile`
- `pnpm lint`
- `pnpm run build:packages`
- `COMPOSIO_E2E_NODE_VERSION=22.22.3 pnpm --filter
@e2e-tests/node-esm-basic --filter @e2e-tests/node-cjs-basic run
test:e2e:node`
- `node ts/packages/cli/bin/composio.mjs --help` under Node `22.22.3`
and `24.17.0`
2026-06-24 18:58:11 +04:00
Alberto Schiabel 4b76dbf70d fix(core): remove deprecated auth-config uuid field from V3 responses (#3633)
Replacement for #3528, preserving @lingala-composio's original commit,
so CI can run from a same-repository branch.

The original PR is from a fork. The TypeScript E2E workflow reads
`COMPOSIO_API_KEY`, `COMPOSIO_BASE_URL_STAGING`,
`COMPOSIO_USER_API_KEY`, `OPENAI_API_KEY`, and `ANTHROPIC_API_KEY` from
repository secrets, and GitHub does not expose those secrets to fork PR
workflow runs. That is why #3528's E2E checks failed with empty env
values before exercising this SDK change.

## What & Why

The Composio platform is removing the deprecated V1/V2 UUID-mirror
fields from V3 API responses. The TypeScript SDK read and re-exposed the
auth-config `uuid`, which was a deprecated mirror of the canonical
nanoid `id`. This stops the SDK from depending on the removed field.

## Changes

- Drop `uuid: authConfig.uuid` from
`transformAuthConfigRetrieveResponse`.
- Remove `uuid` from `AuthConfigRetrieveResponseSchema`.
- Update AuthConfigs tests and fixtures to match the new contract.
- Keep top-level `expectedInputFields` unchanged; only the deprecated
nested bag was removed.

## Verification

- `git diff --check origin/next...HEAD`
- `pnpm --filter @composio/core test AuthConfigs`

---------

Co-authored-by: lingala-composio <rahul.lingala@composio.dev>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 14:28:44 +04:00
Alberto Schiabel 23f9053804 chore(ts): clean up dependencies and bump toolchain (#3623)
This PR:

- consolidates and bumps TypeScript/npm dependencies across the
monorepo, docs, examples, and e2e fixtures — no runtime behavior changes
- **cleanup:** remove the unused `ansis` dependency from `@composio/cli`
(`picocolors` is the actual color lib), drop the dead `uuid` catalog
entry, catalog `dotenv` + `@types/bun` and repoint drifting examples/e2e
onto them, and replace `chalk` with `picocolors` in `@composio/core`
(smaller, ESM, already used by the CLI)
- **TypeScript 6:** bump `typescript` `5.9 → 6.0.3` everywhere (catalog,
CLI test fixtures, docs); drop vestigial `declaration`/`outDir` from the
provider `tsconfig.json`s to fix the TS 6 `rootDir` regression
(`TS6059`); add `ignoreDeprecations: "6.0"` in docs for the `baseUrl`
deprecation
- **toolchain:** `tsdown 0.18 → 0.22.3`, `vitest` + `@vitest/ui →
4.1.9`, `publint → 0.3.21`, `wrangler → 4.101.0` (each the latest
version within the 3-day `minimumReleaseAge` gate)
- **Effect + hono:** `effect 3.21.3`, `@effect/cli 0.75.2`,
`@effect/platform 0.96.1`, `platform-bun 0.90.0`, `platform-node-shared
0.60.0`, `language-service 0.86.2`, `@effect/vitest 0.29.0`, `hono
4.12.25`; pin the Effect peer cohort
(`printer`/`printer-ansi`/`typeclass`/`rpc`/`sql`/`cluster`/`experimental`/`workflow`)
as `@composio/cli` devDeps so the auto-installed peers resolve
coherently, and bump `@cloudflare/workers-types` to satisfy `wrangler`'s
peer
- changesets: `@composio/cli` patch (ansis removal) and `@composio/core`
patch (chalk → picocolors)
- verified: `build`, `typecheck` (tsgo + real `tsc` 6.0.3), and local
tests (excluding e2e) all pass
2026-06-21 00:54:27 +04:00
Alberto Schiabel 24e647fa16 test(ts/e2e): cover claude agent sdk on node current (#3620)
This PR:
- builds on top of https://github.com/ComposioHQ/composio/pull/3495
- adds a Node.js `current` e2e suite for `@composio/claude-agent-sdk`
- exercises the packaged provider through Claude Agent SDK
`createSdkMcpServer` / `query()` with a deterministic local tool
- forwards `ANTHROPIC_API_KEY` through Turbo, Docker e2e env
passthrough, and the Node e2e workflow
2026-06-20 02:08:34 +04:00
Alberto Schiabel 025a657597 feat(ts): drop CommonJS support (#3494)
This PR moves the TypeScript SDK support floor to the latest Node.js 22
release and uses that as the point where we stop carrying custom
CommonJS compatibility machinery. The e2e runtime coverage now exercises
the latest Node 22, Node 24, and Node 25 lines, so the SDK is tested
against the minimum supported version and the newer runtimes users are
likely to adopt next.

Because the SDK packages are still on `0.x`, the accompanying changeset
uses `minor` bumps while calling out that this is a breaking change
inside the existing 0.x line.

It also moves pnpm under mise on this Node 22 layer. That belongs here,
not in #3493, because the pinned `pnpm@10.28.2` requires Node.js
`>=22.13`. Removing Corepack is intentional: Node.js documents that
Corepack is no longer distributed starting with Node.js v25, so relying
on `corepack enable` would keep a toolchain dependency that is already
on the way out of the Node distribution.

## What changed

- Pins the local/toolchain Node.js floor to `22.22.3` in `mise.toml`,
`mise.lock`, `toolchain-versions.json`, and root `devEngines`.
- Pins pnpm in `mise.toml` as `"npm:pnpm" = "10.28.2"` and makes mise
the single source of truth for the pnpm version. Removes the root
`packageManager` / `devEngines.packageManager` Corepack pin entirely
(rather than keeping a second copy of the version that could drift) and
removes stale `packageManager` metadata from real TS packages/examples
and generators.
- Sets `dangerouslyDisablePackageManagerCheck: true` in `turbo.jsonc` so
Turbo discovers pnpm from `pnpm-lock.yaml` instead of requiring a
`packageManager` field. Without this, Turbo fails workspace resolution
(`Could not resolve workspaces -> Missing 'packageManager' field`),
which is the only reason the field would otherwise need to stay.
- Replaces `corepack enable` in the shared setup action with
mise-managed pnpm. The E2E Docker images install bun + pnpm directly
from `mise.toml`/`mise.lock` (with
`dangerouslyDisablePackageManagerCheck`-style separation: Node/Deno stay
on the base image as the test matrix axis and are disabled via
`MISE_DISABLE_TOOLS` so mise does not shadow them; the tool binaries are
symlinked into `/usr/local/bin`). No `BUN_VERSION`/`PNPM_VERSION` build
args are threaded from the host anymore, and bun+pnpm now carry
`mise.lock` checksum verification.
- Extends the install-time toolchain check to validate pnpm against mise
alongside Bun.
- Sets the Node E2E matrix and install fallback checks to `22.22.3`,
`24.16.0`, and `25.9.0`.
- Makes TS package builds ESM-only: `tsdown` now emits `.mjs` / `.d.mts`
only and uses the ATTW `esm-only` profile.
- Removes explicit `require` / `.cjs` / `.d.cts` package export paths
and internal import mappings from the public TS SDK packages.
- Marks public TS SDK packages as `type: module` where they were missing
it.
- Replaces the remaining runtime `require('pusher-js')` with dynamic ESM
import.
- Deletes the legacy CJS example.
- Reintroduces `node/cjs-basic` as a modern Node `require(esm)` interop
E2E: it verifies `require('@composio/core')` works through Node's native
ESM loader on Node 22, 24, and 25 while resolving to `dist/index.mjs`,
not a `.cjs` artifact.
- Removes `.cjs` / `.cts` handling from example validation and CLI
project-language detection.
- Updates provider scaffolding so newly generated providers are
ESM-only.
- Adds a minor changeset warning that CommonJS callers can only rely on
Node's native `require(esm)` interop and that custom CommonJS
compatibility machinery is gone.

## Bundled behavior changes

Two changes here are technically independent of the CommonJS removal but
ride along because they touch the same files and ship in the same
release cut. Calling them out explicitly so they are not missed in
review:

- **`PusherUtils` realtime channel auth (`@composio/core`).** Replacing
the runtime `require('pusher-js')` with a dynamic ESM `import()` was
done alongside conforming `channelAuthorization` to pusher-js's typed
`customHandler(params, callback)` contract. The previous `(authOptions)
=> Promise` shape did not match pusher-js's actual calling convention —
it read `endpoint`/`headers`/`params` off an argument that pusher-js
never passes — so this also fixes that latent mismatch. New unit tests
(`ts/packages/core/test/utils/pusher.test.ts`) cover the auth request
shape (endpoint, `x-api-key` header, JSON `socket_id`/`channel_name`
body) and the success / invalid-JSON / network-failure callback paths.
- **CLI meta-tool slug list (`@composio/cli`).** Drops
`COMPOSIO_UPSERT_RECIPE` and `COMPOSIO_GET_RECIPE` from
`META_TOOL_SLUG_LIST` in `tools-executor.ts`; `@composio/client`
alpha.74 removed those slugs from the `SessionExecuteMetaParams['slug']`
union. The list is declared `satisfies
ReadonlyArray<SessionExecuteMetaParams['slug']>`, so this is enforced at
compile time (`pnpm typecheck`) — keeping the stale slugs would be a
type error — and needs no separate runtime test.

## Verification

- Verified latest Node 22/24/25 releases from the official Node dist
index: `22.22.3`, `24.16.0`, `25.9.0`
(https://nodejs.org/dist/index.json).
- Verified Node docs state Corepack is no longer distributed starting
with Node.js v25:
https://nodejs.org/download/release/v22.22.3/docs/api/corepack.html
- `mise exec -- pnpm --version` -> `10.28.2`
- `mise exec -- pnpm install --frozen-lockfile`
- `mise exec -- bun run ts/scripts/pre-install/check-toolchain.ts`
- `mise exec -- pnpm --filter @e2e-tests/utils typecheck`
- `mise exec -- pnpm --filter @e2e-tests/node-cjs-basic typecheck`
- `mise exec -- pnpm --filter @e2e-tests/node-cjs-basic test:e2e:node`
- `mise exec -- pnpm --filter @e2e-tests/node-esm-basic typecheck`
- `mise exec -- pnpm --filter @composio/cli typecheck`
- `mise exec -- pnpm --filter @composio/cli test -- --runInBand`
- `mise exec -- pnpm --filter @composio/core typecheck`
- `mise exec -- pnpm --filter @composio/core exec vitest run
test/utils/pusher.test.ts`
- `mise exec -- pnpm run build:packages`
- `mise exec -- turbo run build --dry-run` resolves all workspace
packages with no root `packageManager` field (pnpm discovered from
`pnpm-lock.yaml`).
- `mise exec -- pnpm --filter @composio/cli exec vitest run
test/src/services/project-environment-detector.test.ts`
- `mise exec -- pnpm exec prettier --check ...`
- `docker build -f ts/e2e-tests/_utils/Dockerfile.node --build-arg
NODE_VERSION=24.16.0 -t composio-e2e-node:misecheck .` (also
`Dockerfile.deno` with `DENO_VERSION=2.6.7 NODE_MAJOR=22`) — both build
green; runtime resolves Node/Deno from the base image and pnpm 10.28.2 /
bun 1.3.10 from mise.
- `docker manifest inspect node:24.16.0-slim`
- `docker manifest inspect node:25.9.0-slim`
- `bash -n ts/scripts/create-provider.sh && git diff --check`
- `ruby -e "require 'yaml';
YAML.load_file('.github/workflows/ts.test-e2e.yml')"`
- Tracked example validation in a clean temporary tree: `Validated 21
example packages.`
2026-06-19 22:22:17 +04:00
Alberto Schiabel d7d5d46f4d fix(ts/e2e): stabilize Tool Router e2e tests (#3605)
This PR:

- addresses the Mastra Tool Router E2E timeout seen in
https://github.com/ComposioHQ/composio/actions/runs/27758637694/job/82126898492
- addresses the Cloudflare Tool Router AI failure seen in
https://github.com/ComposioHQ/composio/actions/runs/27759741357/job/82130692480
- addresses the follow-up Cloudflare basic timeout seen in
https://github.com/ComposioHQ/composio/actions/runs/27760548665/job/82133483582
- uses the existing `TIMEOUTS.LLM_LONG` live-LLM budget for both Mastra
Tool Router zod-v3 and zod-v4 suites
- raises the HTTP MCP connection-phase timeout from Mastra's implicit 3s
default to 15s in both zod-v3 and zod-v4 suites
- keeps the Cloudflare AI test's `Output.object({ karma })` structured
output and validates the returned `response.karma`
- asserts that `HACKERNEWS_GET_USER` was called and that
`response.karma` equals the structured MCP tool output
- removes the extra Cloudflare `prepareStep` steering and
`findNumberProperty` extraction helper
- avoids explicit `@ai-sdk/mcp` HTTP client close calls in workerd
because the close path aborts the pending stream and Vitest reports it
as unhandled
- gives the live Cloudflare HackerNews compatibility test a 30s budget
while leaving the fast smoke tests on Vitest's default timeout
- fixes the zod-v3 test label so it reports `zod 3` instead of `zod 4`

Verification:

- `./ts/e2e-tests/_utils/node_modules/.bin/tsc --noEmit -p
ts/e2e-tests/runtimes/node/mastra-tool-router-zod-v3/tsconfig.json`
- `./ts/e2e-tests/_utils/node_modules/.bin/tsc --noEmit -p
ts/e2e-tests/runtimes/node/mastra-tool-router-zod-v4/tsconfig.json`
- `pnpm exec vitest run -t "should connect to MCP server"` from
`ts/e2e-tests/runtimes/cloudflare/cf-workers-tool-router-ai`
- `pnpm exec tsc --noEmit --target es2022 --lib es2022 --module es2022
--moduleResolution Bundler --resolveJsonModule
--allowSyntheticDefaultImports --strict --skipLibCheck --types
@cloudflare/workers-types src/index.ts` from
`ts/e2e-tests/runtimes/cloudflare/cf-workers-tool-router-ai`
- `pnpm exec vitest run -t "should fetch HackerNews user pg
successfully"` from `ts/e2e-tests/runtimes/cloudflare/cf-workers-basic`
- `pnpm exec vitest run` from
`ts/e2e-tests/runtimes/cloudflare/cf-workers-basic`
- `pnpm exec prettier --check
ts/e2e-tests/runtimes/cloudflare/cf-workers-basic/test/platform.spec.ts`
- `pnpm exec prettier --check
ts/e2e-tests/runtimes/cloudflare/cf-workers-tool-router-ai/src/index.ts
ts/e2e-tests/runtimes/cloudflare/cf-workers-tool-router-ai/test/tool-router-ai.spec.ts
ts/e2e-tests/runtimes/node/mastra-tool-router-zod-v3/e2e.test.ts
ts/e2e-tests/runtimes/node/mastra-tool-router-zod-v4/e2e.test.ts`
- `git diff --check`

CI:

- `E2E Test Typescript SDK` passed on
https://github.com/ComposioHQ/composio/actions/runs/27768379357

Note: the full Cloudflare AI test was not run locally because this
checkout's local `OPENAI_API_KEY` is invalid; CI has the repo secret for
that path.
2026-06-18 19:01:02 +04:00
Alberto Schiabel 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>
2026-06-15 19:38:51 +04:00
Alberto Schiabel 4fe776898a chore(toolchain): finish mise migration (#3493)
## Summary

Depends on #3492.

This completes the Phase 2 migration by removing the transitional
version-file layer and making `mise.toml` plus `mise.lock` the
repository toolchain source of truth. It also moves runtime test
matrices into `toolchain-versions.json`, so CI matrix changes are
explicit and reviewable without reintroducing `.nvmrc`, `.dvmrc`,
`.bun-version`, or `.python-version`.

The Node.js e2e matrix now starts at the latest Node 22 LTS line and
also covers the latest Node 24 and Node 25 lines. That removes Node 20
from the well-known e2e versions while keeping us covered on the
runtimes SDK users are moving toward.

## Rationale

Phase 1 introduced mise side by side with the existing version files to
keep the first PR low-risk. Phase 2 removes that compatibility layer so
there is one place to update tool versions. That avoids silent drift
between local setup, GitHub Actions, Docker E2E images, release docs,
and install-time checks.

The composite setup actions now install Node, Bun, Python, and uv
through mise by default, with explicit version overrides only where a
matrix needs them. New GitHub actions added in this PR are pinned by
release commit SHA and include the release version comment.

## What changed

- Deleted the transitional root/version files: `.nvmrc`, `.bun-version`,
`.dvmrc`, root `.python-version`, and `python/.python-version`.
- Removed `idiomatic_version_file_enable_tools` from `mise.toml` and
added a committed `mise.lock` for linux/macOS x64/arm64 tool resolution.
- Replaced `BYPASS_BUN_VERSION_CHECK` with `BYPASS_TOOLCHAIN_CHECK`, and
made Docker E2E image installs use that bypass because they receive
explicit build args instead of installing mise.
- Updated Node/Bun and Python/uv composite actions to default to mise,
remove `*-version-file` inputs, report resolved versions, and cache pnpm
after `corepack enable`.
- Centralized CI runtime matrices in `toolchain-versions.json` for TS
E2E, Python tests, and CLI npm fallback coverage.
- Updated the Node E2E matrix to `22.22.3`, `24.16.0`, and `25.9.0`,
removing Node 20 from the well-known runtime versions.
- Updated workflows, docs, E2E helpers, Dockerfiles, and release
guidance to reference `mise.toml` / `mise.lock`.

## Verification

- Verified latest Node 22/24/25 releases from the official Node dist
index: `22.22.3`, `24.16.0`, `25.9.0`
(https://nodejs.org/dist/index.json).
- `pnpm install --frozen-lockfile`
- `pnpm --filter @e2e-tests/utils typecheck`
- `pnpm --filter @e2e-tests/utils exec tsc --noEmit --target es2022
--module esnext --moduleResolution bundler --types bun
--resolveJsonModule --skipLibCheck --strict scripts/docker-build.ts`
- `bash -n ts/scripts/pre-install.sh && bun run
ts/scripts/pre-install/check-toolchain.ts && BYPASS_TOOLCHAIN_CHECK=1
bash ts/scripts/pre-install.sh`
- `pnpm exec prettier --check ...` on touched YAML/Markdown/TS/JSON
files
- `ruby -e "require \"yaml\"; ARGV.each { |f| YAML.load_file(f) }" ...`
on touched actions/workflows
- `mise lock --platform linux-x64,linux-arm64,macos-arm64,macos-x64 &&
git diff --exit-code mise.lock`
- `mise exec node@22.22.3 -- pnpm --filter @e2e-tests/utils typecheck`
- `mise exec node@22.22.3 -- pnpm --filter @e2e-tests/node-esm-basic
typecheck`
- `mise exec node@22.22.3 -- pnpm --filter @e2e-tests/node-cjs-basic
typecheck`
- `docker manifest inspect node:24.16.0-slim`
- `docker manifest inspect node:25.9.0-slim`
- `git diff --check`
2026-06-15 14:03:21 +04:00
Alberto Schiabel 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.
2026-06-04 23:53:58 -07:00
Dhawal Upadhyay 82e0038c7c bump generated clients for v3.1 2026-05-05 14:44:43 +05:30
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
Alberto Schiabel a10288aa87 fix(core): restore session.toolkits() pagination (#3193) 2026-04-16 12:02:23 -07:00
Alberto Schiabel f9887042a8 test: fix pre-existing CI failures across CLI and e2e suites (#3102)
This PR:

- fixes the stale beta version expectation in `upgrade-binary.test.ts`
(\`0.2.18\` → \`0.2.19\`) that broke the "selects the latest prerelease"
test
- replaces live \`composio generate ts\` call in the
\`typescript-mjs-import-nodenext\` e2e suite with checked-in fixture
files, removing the \`COMPOSIO_API_KEY\` dependency
- adds \`mock-toolkits-server.ts\` — a deterministic mock HTTP server
for \`/api/v3/toolkits\` and \`/api/v3/toolkits/:slug\` endpoints
- migrates \`toolkits/list\`, \`toolkits/info\`, and \`toolkits/search\`
CLI e2e suites from live API calls to the mock server, removing the
\`COMPOSIO_USER_API_KEY\` requirement
- adds \`--add-host host.docker.internal:host-gateway\` to Docker e2e
runner so CLI containers can reach host-side mock servers
- closes
[PLEN-2012](https://linear.app/composio/issue/PLEN-2012/cli-fix-cli-e2e-tests)

All three failures are pre-existing on \`next\` — this PR makes CI green
again.

## Testing

```bash
pnpm --dir ts/packages/cli exec vitest run test/src/services/upgrade-binary.test.ts
pnpm typecheck
pnpm --dir ts/e2e-tests/_utils typecheck
pnpm --filter @e2e-tests/cli-toolkits-info typecheck
pnpm --filter @e2e-tests/cli-toolkits-list typecheck
pnpm --filter @e2e-tests/cli-toolkits-search typecheck
```

> **Stack:** 1/2 — followed by #3099 (org switch limit display feature)

---------

Co-authored-by: jkomyno <12381818+jkomyno@users.noreply.github.com>
Co-authored-by: Rahul Tarak <cryogenicplanet@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 00:16:32 -07:00
Rahul Tarak 456ee40e58 fix(cli): bundle mcp server into subagent helper (#3049)
## Summary
- replace runtime MCP SDK path resolution with static imports in the
structured-output helper
- ensure the helper works when shipped next to the standalone CLI binary
without repo-local node_modules

## Verification
- pnpm --filter @composio/cli run typecheck:src
- pnpm --filter @composio/cli test
test/src/services/run-subagent-acp.test.ts
- built and executed the bundled helper from a temp directory outside
the repo
2026-03-27 10:12:09 -07:00
Rahul Tarak 97a5218dc6 Move CLI manage commands under dev namespace (#3010)
## Summary
- Moved developer-oriented CLI commands from `manage` to the `dev`
namespace.
- Updated command registrations, help text, hints, and examples across
auth configs, connected accounts, toolkits, triggers, logs, tools, orgs,
and projects.
- Removed the old `manage` entrypoint and adjusted command routing and
error guidance to match the new structure.
- Updated the affected CLI tests to reflect the new command paths.

## Testing
- Not run (not requested).
- Updated command test snapshots/expectations in the CLI test suite to
match the renamed namespace.
- Verified help text and inline hints were rewritten from `composio
manage ...` to `composio dev ...` in the touched commands.
2026-03-24 20:51:53 -07:00
Dhawal Upadhyay db8f08ba95 fix(tool-router): tighten annotation routing and e2e retries 2026-03-24 15:29:24 -07:00
Dhawal Upadhyay 6bcac5beb8 feat(core): custom tools, toolkits, and extension tools for tool router sessions (#2877)
## Summary

Add user-defined tools that execute locally (in-process) alongside
Composio's remote tools in tool router sessions. Aligned with backend PR
[hermes#8614](https://github.com/ComposioHQ/hermes/pull/8614).

**Three ways to define custom tools:**

1. **Standalone** — no auth, no toolkit association → `LOCAL_<SLUG>`
2. **Extension** — extends a Composio toolkit, inherits its auth →
`LOCAL_<TOOLKIT>_<SLUG>`
3. **Custom toolkit** — groups related no-auth tools →
`LOCAL_<TOOLKIT>_<SLUG>`

**Key capabilities:**
- `experimental_createTool(slug, opts)` and
`experimental_createToolkit(slug, opts)` factory functions
- Tools indexed by backend for semantic search (BM25), returned to LLM
via `COMPOSIO_SEARCH_TOOLS`
- `session.execute()` routes custom tools in-process, remote tools to
backend — accepts original slug, `LOCAL_`-prefixed slug, or lowercase
- `COMPOSIO_MULTI_EXECUTE_TOOL` interception: splits custom/remote
tools, executes in parallel, merges results
- `SessionContext` injected at runtime: `userId`, `execute()` (with
sibling local routing), `proxyExecute()`
- Slug validation: alphanumeric/underscores/hyphens, no `LOCAL_` prefix,
max 60 chars prefixed

## Usage

### Standalone tool (no auth)

```typescript
import { experimental_createTool } from '@composio/core';
import { z } from 'zod/v3';

const getUserDetails = experimental_createTool('GET_USER_DETAILS', {
  name: 'Get user details',
  description: 'Retrieve user profile by ID',
  inputParams: z.object({ user_id: z.string() }),
  execute: async (input) => {
    return { id: input.user_id, name: 'Alice', role: 'admin' };
  },
});
```

### Extension tool (inherits Composio toolkit auth)

```typescript
const formatEmail = experimental_createTool('FORMAT_GMAIL_EMAIL', {
  name: 'Format Gmail email',
  description: 'Format an email draft with HTML formatting',
  extendsToolkit: 'gmail',
  inputParams: z.object({ to: z.string(), subject: z.string(), body: z.string() }),
  execute: async (input, session) => {
    return { formatted: true, to: input.to, html_body: input.body.replace(/\n/g, '<br>'), user_id: session.userId };
  },
});
```

### Custom toolkit (groups no-auth tools)

```typescript
import { experimental_createToolkit } from '@composio/core';

const setUserRole = experimental_createTool('SET_USER_ROLE', {
  name: 'Set user role',
  description: 'Change user role',
  inputParams: z.object({ user_id: z.string(), role: z.enum(['admin', 'developer', 'viewer']) }),
  execute: async (input) => ({ user_id: input.user_id, new_role: input.role }),
});

const userManagement = experimental_createToolkit('USER_MANAGEMENT', {
  name: 'User Management',
  description: 'Tools for managing user profiles and roles',
  tools: [setUserRole],
});
```

### Creating a session

```typescript
const composio = new Composio({ apiKey, provider: new OpenAIAgentsProvider() });

const session = await composio.create('user_123', {
  toolkits: ['weathermap', 'gmail'],
  experimental: {
    customTools: [getUserDetails, formatEmail],
    customToolkits: [userManagement],
  },
});
```

### Executing tools

```typescript
// Custom tool — runs in-process
const r1 = await session.execute('GET_USER_DETAILS', { user_id: 'user-1' });
const r2 = await session.execute('LOCAL_GET_USER_DETAILS', { user_id: 'user-1' }); // prefixed
const r3 = await session.execute('get_user_details', { user_id: 'user-1' }); // case-insensitive

// Remote tool — identical API
const weather = await session.execute('WEATHERMAP_WEATHER', { location: 'Tokyo' });

// Agent flow — SDK intercepts MULTI_EXECUTE, routes custom/remote in parallel
const tools = await session.tools();
const agent = new Agent({ tools, model: 'gpt-5.2' });
```

## Backend API alignment

Payload sent under `experimental`:
- `custom_tools`: array of `{ slug, name, description, input_schema,
output_schema?, extends_toolkit? }`
- `custom_toolkits`: array of `{ slug, name, description, tools: [{
slug, name, description, input_schema }] }`

Standalone tools omit `extends_toolkit`. Extension tools set
`extends_toolkit` to a valid Composio toolkit slug.

## Files changed

| File | Change |
|---|---|
| `types/customTool.types.ts` | `CustomToolSlugSchema`,
`CreateCustomToolBaseSchema` (slug as 1st arg), `extendsToolkit`,
`outputParams`, `CustomToolkit`, `CustomToolkitDefinition` |
| `models/CustomTool.ts` | `createCustomTool(slug, opts)`,
`createCustomToolkit(slug, opts)`, `buildCustomToolsMap(tools,
toolkits?)`, `serializeCustomTools`, `serializeCustomToolkits` |
| `types/toolRouter.types.ts` | `customTools`/`customToolkits` under
`experimental`, `SessionProxyExecuteParams`, `proxyExecute` on Session |
| `models/ToolRouter.ts` | Read from
`experimental.customTools/customToolkits`, unified `experimental`
payload |
| `models/ToolRouterSession.ts` | Multi-execute interception,
`session.execute()` routing, `proxyExecute()` |
| `models/SessionContext.ts` | `proxyExecute()` implementation, sibling
local tool routing |
| `models/customToolExecution.ts` | Extracted `findCustomTool()`,
`executeCustomTool()` |
| `models/proxyParamsTransform.ts` | Transform SDK proxy params to
backend format |
| `index.ts` | `experimental_createTool`, `experimental_createToolkit`
exports |
| `experimental/index.ts` | `createCustomToolkit`, `CustomToolkit`,
`CreateCustomToolkitParams` |
| `docs/api/tool-router.md` | Custom tools section,
`execute`/`search`/`proxyExecute` docs |
| `examples/tool-router/src/custom-tools-agent.ts` | Full agent example
with all 3 tool types |

## Test plan

### Unit tests (79 across 2 files)

- `createCustomTool()`: slug validation (regex, no LOCAL_, invalid
chars), `extendsToolkit`, `outputParams`, Zod to JSON Schema, execute
signatures
- `createCustomToolkit()`: validation, rejects tools with
`extendsToolkit`
- `buildCustomToolsMap()`: 3 prefix patterns, length validation,
cross-group collision detection
- `serializeCustomTools()`: `extends_toolkit` mapping, omit for
standalone, `output_schema`
- `serializeCustomToolkits()`: nested tool serialization
- `SessionContextImpl`: userId, remote delegation, proxyExecute, sibling
routing
- `ToolRouter.create()`: payload under `experimental`,
`extends_toolkit`, omit when empty
- `session.execute()`: original/prefixed slug, case-insensitive, remote
fallback, error handling, Zod defaults
- `MULTI_EXECUTE split/merge`: all-local/all-remote/mixed batches,
parallel execution, error merging, edge cases

### E2E tests

- Node.js fixture (`ts/e2e-tests/runtimes/node/custom-tools/`) against
live API
- Focused E2E script: 18 tests covering all 3 tool types, search
indexing, state mutations, error handling
- Agent example (`ts/examples/tool-router/src/custom-tools-agent.ts`)
verified against staging backend — standalone + extension + custom
toolkit + remote tools in a single agent run

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-03-18 13:38:37 -07:00
Rahul Tarak ddf871c1ec fix(e2e): add retry logic to tool-router-files download for eventual consistency
The download call can 404 immediately after upload due to API eventual
consistency. Add the same retry pattern already used for list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 19:58:34 -07:00
jkomyno 915ef25820 fix(cli): update e2e test to use new composio generate ts command path
The E2E test for TypeScript .mjs import resolution was still using
the old `composio ts generate` command which no longer exists as a
top-level command after the generate restructure.
2026-03-17 19:46:34 -07:00
Rahul Tarak 3415a4a15b feat(cli): add manage namespace for advanced commands (#2937)
## Summary

Introduces a `composio manage` namespace that groups resource management
commands (toolkits, tools, auth-configs, connected-accounts, triggers,
logs, orgs, projects) under a single parent command. This declutters the
top-level CLI help and creates a clearer separation between everyday
commands (`init`, `login`, `generate`) and advanced resource management.

## Changes
- Created `manage/manage.cmd.ts` with all resource subcommands
registered under `composio manage`
- Removed individual top-level imports (toolkits, tools, auth-configs,
etc.) from `index.ts` and replaced with single `manageCmd` import
- Updated alias mapping (`ALIAS_TO_PARENT`) to route through `manage`
(e.g., `search` → `manage tools`, `link` → `manage connected-accounts`)
- Updated `parseExecuteInputHelpSlug` to account for the new `manage`
prefix in argv parsing
- Consolidated the root help advanced commands section to show a single
`manage` entry

## Type of change
- [x] Refactor/Chore

## How Has This Been Tested?
- Verified CLI help output displays correctly with the new `manage`
namespace
- Tested that aliases (`composio search`, `composio execute`, `composio
link`, `composio listen`) still resolve correctly through the `manage`
prefix

## Checklist
- [x] I have read the Code of Conduct and this PR adheres to it
- [x] I ran linters/tests locally and they passed
- [x] I updated documentation as needed
- [x] I added tests or explain why not applicable
- [x] I added a changeset if this change affects published packages

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: jkomyno <12381818+jkomyno@users.noreply.github.com>
2026-03-17 19:44:44 -07:00
Dhawal Upadhyay ba97624843 refactor: session.customTools/customToolkits, early validation, ctx rename, COMPOSIO_ rejection
- Add session.customTools({ toolkit? }) and session.customToolkits() methods
  returning registered tools with final slugs, schemas, and resolved toolkit
- Early slug length validation in createCustomTool (standalone + extension)
  and createCustomToolkit (per tool), with buildCustomToolsMap as safety net
- Reject COMPOSIO_ prefix in CustomToolSlugSchema (prevents meta tool shadowing)
- Rename execute fn param from session → ctx everywhere (type def, docs, examples, tests)
- SessionContextImpl as singleton on ToolRouterSession (created once in constructor)
- Rename internal byPrefixed/byOriginal → byFinalSlug/byOriginalSlug
- Store resolved toolkit on map entries for session.customTools() lookups
- Add RegisteredCustomTool and RegisteredCustomToolkit types to Session interface
- JSDoc on extendsToolkit: must be a valid Composio toolkit slug

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 14:31:50 -07:00
Dhawal Upadhyay ff23edf844 refactor: single import path for custom tools via @composio/core
Remove @composio/core/experimental as primary import path. Users import
experimental_createTool and experimental_createToolkit from @composio/core.
The /experimental sub-path re-exports with the same names for backward compat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 11:40:54 -07:00
Dhawal Upadhyay 0270042316 feat: align custom tools API with backend refactor, add toolkits and extension tools
- Signature: `experimental_createTool(slug, opts)` / `experimental_createToolkit(slug, opts)`
- Three tool types: standalone (LOCAL_<SLUG>), extension (LOCAL_<TOOLKIT>_<SLUG>), custom toolkit
- Move customTools/customToolkits under `experimental` in session config
- Backend payload: `extends_toolkit` (not `toolkit`), omitted for standalone
- Slug validation: regex, no LOCAL_ prefix, max 60 chars prefixed
- Add `serializeCustomToolkits()`, `buildCustomToolsMap(tools, toolkits?)`
- Export `experimental_createTool`/`experimental_createToolkit` from `@composio/core`
- Add agent example with all 3 tool types (standalone, extension, custom toolkit)
- Update tool-router docs with custom tools section, session.execute/search/proxyExecute
- Update E2E fixtures and tests to new API

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 11:12:54 -07:00
Dhawal Upadhyay 3388afcc9b refactor(core): address review comments — rename API, add Zod validation
- Rename CustomTool() → createCustomTool() (camelCase convention)
- Rename CustomToolHandle type → CustomTool
- Rename connectedToolkit → toolkit with clear TSDoc
- Add CreateCustomToolBaseSchema (Zod) for string field validation
- Remove SessionContextImpl from public exports (internal only)
- Export CreateCustomToolParams type

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 11:12:54 -07:00
Dhawal Upadhyay cdc2606e82 test(e2e): expand custom tools fixture with mixed routing and error cases
- Add WEATHER_CHAIN tool: local tool calls remote WEATHERMAP_WEATHER via
  SessionContext.execute() — proves mixed local+remote in same session
- Add Zod validation failure test (wrong type → error, no crash)
- Add non-existent tool test (backend 400 → catchable error)
- Add STRICT_TOOL with z.number() schema for validation testing
- Switch from hackernews to weathermap toolkit (simpler, active connection)
- 12 test cases total, all passing against production API

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 11:12:54 -07:00
Dhawal Upadhyay 70e73c3efe refactor(core): review fixes + E2E tests for custom local tools
- Remove sessionId from public SessionContext interface (keep private in impl)
- Sort multi-execute merge: remote results first, local last (preserves remote file indexes)
- Add multi-execute test for non-prefixed local slug handling
- Tighten local_tools payload type from unknown to LocalToolDefinition[]
- Deduplicate test helpers (createSessionWithProvider/captureExecuteFn hoisted to top-level)
- Add E2E test suite for custom tools (Docker-based, hackernews no-auth toolkit)
- Fix JSDoc example: proxyExecute → session.execute()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 11:12:54 -07:00
Musthaq Ahamad 40a7dae840 Experimental release for files in tool-router (#2876) 2026-03-13 16:32:13 +05:30