Commit Graph

4231 Commits

Author SHA1 Message Date
Alberto Schiabel b346272572 chore(ci): use OIDC for TS npm releases, add needed attributes to package.json (#3611)
This PR:

- configures the TS release workflow to request GitHub Actions OIDC ID
tokens
- runs the TS release publish path on Node 24.17.0 so npm supports
trusted publishing
- leaves a TODO to centralize that release runtime in `mise.toml` after
https://github.com/ComposioHQ/composio/pull/3494 lands
- removes the long-lived `NPM_TOKEN` `.npmrc` setup before `changeset
publish`
- adds npm package support metadata (`repository.url`, `bugs.url`, and
`homepage`) for every public TS release workspace that Changesets can
publish
- marks `@composio/cli-local-tools` private so Changesets does not try
to publish it
@composio/llamaindex@0.9.3 @composio/mastra@0.9.3 @composio/langchain@0.9.3 @composio/google@0.9.3 @composio/core@0.11.0 @composio/openai-agents@0.9.3 @composio/cloudflare@0.9.3 @composio/cli-local-tools@0.0.5 @composio/claude-agent-sdk@0.9.3 @composio/openai@0.9.3 @composio/anthropic@0.9.3 @composio/vercel@0.9.3 @composio/cli@0.2.32-beta.267
2026-06-19 18:34:10 +04:00
Abir Taheer f6df489c0b Release: update version (#3429)
> [!WARNING]
> ## ⚠️ Breaking change — `@composio/core@0.11.0` (minor bump, pre-1.0)
>
> The legacy in-memory custom-tools registry
**`composio.tools.createCustomTool(...)` has been removed** (changeset
`44e5458`). Because `@composio/core` is pre-1.0, this ships as a
**minor** bump per semver convention — but it **is breaking**: any code
calling `composio.tools.createCustomTool(...)` will fail to compile/run
after upgrading. Consumers pinned to `^0.10.0` will **not** auto-upgrade
to `0.11.0` and must opt in explicitly.

### Migration: use Tool Router custom tools

Custom tools are now standalone factories bound to a **Tool Router
session**, instead of being registered into an in-memory registry on the
`composio.tools` namespace.

**Before (removed):**

```ts
// ❌ No longer available in 0.11.0
const tool = composio.tools.createCustomTool({ /* ... */ });
```

**After — a standalone tool (no auth):**

```ts
import { Composio, experimental_createTool } from '@composio/core';
import { z } from 'zod';

const composio = new Composio();

const grep = experimental_createTool('GREP', {
  name: 'Grep Search',
  description: 'Search for patterns in files',
  inputParams: z.object({ pattern: z.string(), path: z.string() }),
  execute: async (input) => ({ matches: [] }),
});

// Bind the custom tool(s) to a Tool Router session
const session = await composio.create(userId, {
  experimental: { customTools: [grep] },
});
```

**After — a tool that extends a Composio toolkit (inherits that
toolkit's auth):**

```ts
const getImportantEmails = experimental_createTool('GET_IMPORTANT_EMAILS', {
  name: 'Get Important Emails',
  description: 'Fetch high-priority emails',
  extendsToolkit: 'gmail',
  inputParams: z.object({ limit: z.number().default(10) }),
  execute: async (input, ctx) => {
    // ctx.execute() returns the standard { data, error, logId } shape
    const result = await ctx.execute('GMAIL_SEARCH', { query: 'is:important' });
    return { emails: result.data };
  },
});

const session = await composio.create(userId, {
  experimental: { customTools: [getImportantEmails] },
});
```

**After — grouping related tools into a custom toolkit:**

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

const devTools = experimental_createToolkit('DEV_TOOLS', {
  name: 'Dev Tools',
  description: 'Local developer utilities',
  tools: [grep], // tools here must NOT set `extendsToolkit`
});

const session = await composio.create(userId, {
  experimental: { customToolkits: [devTools] },
});
```

> Notes:
> - `experimental_createTool` / `experimental_createToolkit` are also
available from the dedicated `@composio/core/experimental` entry point.
> - Tool slugs are auto-prefixed with `LOCAL_` when exposed to the agent
(e.g. `GREP` → `LOCAL_GREP`; inside a toolkit, `DEV_TOOLS` + `GREP` →
`LOCAL_DEV_TOOLS_GREP`).
> - These APIs are intentionally namespaced `experimental_*` — they are
not yet stable and may change.

---

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.11.0

### Minor Changes

- a94715f: Forward `userId` when creating trigger instances so trigger
2FA flows can verify connected account ownership.
- 44e5458: Remove the legacy `composio.tools.createCustomTool(...)`
in-memory registry API. Use Tool Router custom tools via
`experimental_createTool`, `experimental_createToolkit`, and
`composio.create(..., { experimental: { customTools, customToolkits }
})` instead.

### Patch Changes

- 22a9171: Defer telemetry batch and error sends so instrumentation does
not wait for telemetry network requests before returning SDK results or
rethrowing SDK errors.
- 93b67e8: Fix automatic file upload/download substitution for file
schemas that accept either a single file or a list of files.

The file modifier now selects composed-schema branches by runtime value
shape, so `anyOf(file, array<file>)` uploads or downloads each file when
the tool receives a list while preserving existing single-file behavior.

- b69cef1: Tolerate dangling `$ref` pointers in tool schemas the
Composio API ships without a matching `$defs` entry. Some toolkits (e.g.
`GMAIL_FETCH_EMAILS`) emit `outputParameters` with `"$ref":
"#/$defs/FetchEmailsResponse"` while never declaring a top-level `$defs`
block. After the strict resolver shipped with the previous Mastra fix,
this caused `composio.tools.get(...)` to throw
`JsonSchemaRefResolutionError` upfront, making every Gmail / Slack /
Google-Calendar tool unusable through `MastraProvider`. The SDK now
degrades the unresolvable branch to a permissive object schema and
surfaces a single observability warning per `(toolSlug, ref)` pair
instead of crashing.
- `dereferenceJsonSchema` accepts a new optional second argument `{
onUnresolved?: 'throw' | 'sentinel'; onReplace?: (ref, reason) => void
}`. Default behavior is unchanged (`'throw'`) — first-party /
custom-tool schemas with a typo'd `$ref` still surface as a hard error.
Pass `'sentinel'` to replace unresolved branches with the cycle-break
sentinel (`{ type: 'object', additionalProperties: true }`) that the
resolver already uses for `$ref` cycles. The replaced sentinel carries a
default `description` hint so LLMs consuming the wrapped tool's schema
get an in-band signal that the branch is opaque; a caller-provided
`description` sibling overrides the default (Draft 2020-12
sibling-keyword merge). Safety caps (`MAX_REF_CHAIN_DEPTH`,
`MAX_NODE_DEPTH`) keep throwing in both modes. New
`UnresolvedRefStrategy`, `UnresolvedRefReason`, and
`DereferenceJsonSchemaOptions` type exports.
- `MastraProvider.wrapTool` opts both `inputParameters` and
`outputParameters` into `'sentinel'` mode and emits one `logger.warn`
per `(toolSlug, ref)` pair via the provider-scoped dedup `Set`.
User-controlled segments in the warning (`tool.slug`, `toolkit.slug`,
`ref`) are `JSON.stringify`d to neutralize embedded newlines / ANSI
escapes / control bytes that could otherwise forge log lines (CWE-117).
A matching one-shot telemetry event
(`composio.mastra.wrapTool.danglingRef`) fires next to the warn so the
Composio team has aggregate visibility into which toolkits are affected;
the event respects `COMPOSIO_DISABLE_TELEMETRY=true`.
- The `telemetry` instance from `@composio/core` is now publicly
re-exported alongside `logger`, so providers can emit aggregate signals
without reaching into the package's internals.
- Resolvable `$defs` / `definitions` continue to be inlined exactly as
before — no regression in the type-info preservation contract introduced
by the previous Mastra fix.

- 1ba66ca: Fix `tools.execute` (and `tools.get` / `tools.list`) failing
with a `ZodError` for every tool from an MCP-backed toolkit (e.g.
`granola_mcp`, `apify_mcp`, `tavily_mcp`).

MCP toolkits don't declare an output schema, and the Composio API
serializes that as `output_parameters: {}`. The SDK's `ParametersSchema`
required `{ type: 'object', properties: {...} }`, so
`transformToolCases` rejected the response and
`getRawComposioToolBySlug` — called by `execute` and the list path —
threw.

The SDK now normalizes empty (`{}`), `null`, and missing
`input_parameters` / `output_parameters` payloads to `undefined` before
validation. `outputParameters` was already declared `.optional()` in the
public `Tool` type, so this preserves the contract: "undefined means no
declared schema." Tools that _do_ declare a schema continue to be
validated strictly.

  No public API change; no toolkit allow-list.

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/cli-local-tools@0.0.5

### Patch Changes

- Updated dependencies [22a9171]
- Updated dependencies [93b67e8]
- Updated dependencies [b69cef1]
- Updated dependencies [1ba66ca]
- Updated dependencies [a94715f]
- Updated dependencies [ce4b213]
- Updated dependencies [44e5458]
  - @composio/core@0.11.0
## @composio/anthropic@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/claude-agent-sdk@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/cloudflare@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/google@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/langchain@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/llamaindex@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/mastra@0.9.3

### Patch Changes

- b69cef1: Tolerate dangling `$ref` pointers in tool schemas the
Composio API ships without a matching `$defs` entry. Some toolkits (e.g.
`GMAIL_FETCH_EMAILS`) emit `outputParameters` with `"$ref":
"#/$defs/FetchEmailsResponse"` while never declaring a top-level `$defs`
block. After the strict resolver shipped with the previous Mastra fix,
this caused `composio.tools.get(...)` to throw
`JsonSchemaRefResolutionError` upfront, making every Gmail / Slack /
Google-Calendar tool unusable through `MastraProvider`. The SDK now
degrades the unresolvable branch to a permissive object schema and
surfaces a single observability warning per `(toolSlug, ref)` pair
instead of crashing.
- `dereferenceJsonSchema` accepts a new optional second argument `{
onUnresolved?: 'throw' | 'sentinel'; onReplace?: (ref, reason) => void
}`. Default behavior is unchanged (`'throw'`) — first-party /
custom-tool schemas with a typo'd `$ref` still surface as a hard error.
Pass `'sentinel'` to replace unresolved branches with the cycle-break
sentinel (`{ type: 'object', additionalProperties: true }`) that the
resolver already uses for `$ref` cycles. The replaced sentinel carries a
default `description` hint so LLMs consuming the wrapped tool's schema
get an in-band signal that the branch is opaque; a caller-provided
`description` sibling overrides the default (Draft 2020-12
sibling-keyword merge). Safety caps (`MAX_REF_CHAIN_DEPTH`,
`MAX_NODE_DEPTH`) keep throwing in both modes. New
`UnresolvedRefStrategy`, `UnresolvedRefReason`, and
`DereferenceJsonSchemaOptions` type exports.
- `MastraProvider.wrapTool` opts both `inputParameters` and
`outputParameters` into `'sentinel'` mode and emits one `logger.warn`
per `(toolSlug, ref)` pair via the provider-scoped dedup `Set`.
User-controlled segments in the warning (`tool.slug`, `toolkit.slug`,
`ref`) are `JSON.stringify`d to neutralize embedded newlines / ANSI
escapes / control bytes that could otherwise forge log lines (CWE-117).
A matching one-shot telemetry event
(`composio.mastra.wrapTool.danglingRef`) fires next to the warn so the
Composio team has aggregate visibility into which toolkits are affected;
the event respects `COMPOSIO_DISABLE_TELEMETRY=true`.
- The `telemetry` instance from `@composio/core` is now publicly
re-exported alongside `logger`, so providers can emit aggregate signals
without reaching into the package's internals.
- Resolvable `$defs` / `definitions` continue to be inlined exactly as
before — no regression in the type-info preservation contract introduced
by the previous Mastra fix.

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/openai@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/openai-agents@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/vercel@0.9.3

### Patch Changes

- ce4b213: fix(providers): normalize string tool-call arguments across
all providers

Models occasionally emit tool-call arguments as a JSON string instead of
an
object (most visibly with `COMPOSIO_MULTI_EXECUTE_TOOL` on the Vercel AI
SDK),
  which broke downstream validation with errors like
  `tool_use.input: Input should be a valid dictionary`.

`@composio/core` now exposes a single `normalizeToolArguments` helper,
and every
provider routes model-supplied arguments through it. Object payloads
pass
through unchanged, JSON strings are parsed, empty/`null` payloads become
`{}`,
  and anything that cannot resolve to an object throws a typed
`ComposioInvalidToolArgumentsError` instead of a raw `SyntaxError` or a
silently
forwarded malformed string. This replaces the inconsistent per-provider
guards
  that previously existed only in vercel, cloudflare and openai-agents.
## @composio/cli@0.2.32

### Patch Changes

- Updated dependencies [22a9171]
- Updated dependencies [93b67e8]
- Updated dependencies [b69cef1]
- Updated dependencies [1ba66ca]
- Updated dependencies [a94715f]
- Updated dependencies [ce4b213]
- Updated dependencies [44e5458]
  - @composio/core@0.11.0
  - @composio/cli-local-tools@0.0.5

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@composio/cli@0.2.32-beta.266
2026-06-19 17:12:38 +04:00
Alberto Schiabel 82896858ec fix(docs): retry 429s in data sync scripts and lower concurrency (#3608)
This PR:

- adds a shared `fetchWithRetry` helper for the docs data-sync scripts
that retries `429` and transient 5xx responses, honoring `Retry-After`
(with jitter) and falling back to exponential backoff
- routes every request in `generate-toolkits.ts` and
`generate-meta-tools.ts` through it, so the `Docs - Update Data`
workflow rides out the staging rate limit (2000 req/min) instead of
hard-failing
- lowers toolkit fetch `batchSize` 10 → 5 (~30 → ~15 concurrent
requests) to soften burst pressure on the rate limit
- caps retry attempts so CI still fails fast when the backend is
genuinely down
- fixes the current `429 Too Many Requests` failure in `Generate meta
tools reference`, which inherited the rate-limit window exhausted by the
high-volume `generate-toolkits.ts` run
- verified with `bun run types:check` and an offline retry/backoff
behavior test (real end-to-end run needs the staging key in CI: `gh
workflow run docs-update-data.yml`)
- follow-up (separate PR): reduce per-toolkit request volume in
`generate-toolkits.ts` — left out here because it needs consumer and
search-quality validation
2026-06-18 20:37:42 +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
samvitjatia f032cd5f69 docs: clarify HubSpot scope configuration (#3603)
## Summary
- Tighten the HubSpot toolkit FAQ into five customer-facing questions
instead of many scope-adjacent entries
- Clarify HubSpot scope category matching: Composio `scopes` maps to
HubSpot required/conditionally required, and `optional_scopes` maps to
HubSpot optional
- Document managed-auth limitations, custom-auth examples,
Create/Get/Update Auth Config API usage, reconnect behavior, and grouped
troubleshooting checks
- Add guidance for HubSpot's unverified-app warning and Composio's
active app approval work

## Verification
- Confirmed live HubSpot auth config API responses expose
`credentials.scopes` and `credentials.optional_scopes`
- `git diff --check` passed
- `bun run scripts/validate-links.ts` could not run locally because docs
dependencies are missing: `fumadocs-mdx/bun`
2026-06-18 18:00:30 +05:30
sjd9021 77d883238a docs: clarify HubSpot scope configuration 2026-06-18 17:54:40 +05:30
jkomyno 0720b760e2 fix(docs): stabilize SDK reference auto PR checks 2026-06-18 16:13:17 +04:00
Alberto Schiabel eeaac651d8 chore(py): document pending releases (#3583)
This PR:
- documents the pending Python `0.14.0` and `0.15.0` releases in
`python/CHANGELOG.md`
- aligns `python/composio/__version__.py` with `python/pyproject.toml`
at `0.15.0`
- adds a release guard so Python package/provider versions, runtime
version, and changelog entries cannot drift silently
- leaves Python release tags and PyPI publishing untouched; `py@0.14.0`
should still be published before `py@0.15.0`
py@0.15.0
2026-06-18 12:33:42 +04:00
Alberto Schiabel 95843b37e3 fix(docs): use app token for data sync PRs (#3599)
This PR:

- adds the same `actions/create-github-app-token` setup used by the SDK
docs generator
- checks out the repository with the generated app token
- passes the app token to `peter-evans/create-pull-request`
- uses the app token for the optional reviewer request
- fixes the current `Docs - Update Data` failure where `CI_BOT_TOKEN`
cannot authenticate the git push for `docs/auto-update-data`
- verified with `go run
github.com/rhysd/actionlint/cmd/actionlint@latest
.github/workflows/docs-update-data.yml` and `git diff --check`
2026-06-17 20:36:57 +04:00
Alberto Schiabel 3374b477a6 fix(docs): simplify staging data sync URLs (#3596)
This PR:

- simplifies `COMPOSIO_BASE_URL_STAGING` handling by stripping optional
`/api/v3` or `/api/v3.1` suffixes before deriving both docs API
endpoints
- removes the URL-shape branching that rejected the current staging
secret
- keeps the production backend guard so the update-data workflow does
not use `https://backend.composio.dev`
- uses `CI_BOT_TOKEN` for `peter-evans/create-pull-request` and reviewer
requests because `GITHUB_TOKEN` cannot create pull requests in this repo
- verified with `go run
github.com/rhysd/actionlint/cmd/actionlint@latest
.github/workflows/docs-update-data.yml`, `git diff --check`, and shell
URL derivation checks
2026-06-17 18:42:50 +04:00
jkomyno 2724126199 fix(docs): normalize staging data sync URLs 2026-06-17 18:37:28 +04:00
palash-c 0026d50f94 docs: pin Changelog directly under Overview in API reference sidebar (#3595)
## What
Move the **Changelog** entry in the API Reference sidebar so it sits
**immediately below Overview** (second item from the top), instead of
after **Errors**.

## Why
Requested placement — Changelog should be pinned right under Overview at
the top of the Reference nav for visibility.

## How
The Changelog node is injected programmatically in
`app/(home)/reference/(v31)/layout.tsx` (it's not a `meta.json` page).
Previously it was inserted at `errorsIdx + 1`; now it's inserted at
`overviewIdx + 1`, with a safe fallback to position 1 if "Overview"
isn't found.

Before: `Overview → Authentication → Rate Limits → Errors → Changelog →
API Reference → …`
After: `Overview → Changelog → Authentication → Rate Limits → Errors →
API Reference → …`

Only affects the v3.1 (default) Reference layout; the v3 layout doesn't
inject a Changelog node.

## Verification
- `bun run types:check` passes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 18:01:50 +04:00
Alberto Schiabel 87464bf2ad fix(docs): use staging endpoints for data sync (#3591)
This PR:

- configures `docs-update-data.yml` to source docs data from
`COMPOSIO_BASE_URL_STAGING`
- fails fast when the staging base URL is missing or does not include
`/api/v3`
- derives v3 and v3.1 OpenAPI URLs from the staging secret so the job
does not fall back to production
- updates the generated data-sync PR copy to say OpenAPI specs are
fetched from staging
- quotes `$GITHUB_OUTPUT` redirects so `actionlint` stays clean
- verified with `go run
github.com/rhysd/actionlint/cmd/actionlint@latest
.github/workflows/docs-update-data.yml`, `git diff --check`, and shell
endpoint derivation checks
2026-06-17 17:46:39 +04:00
Alberto Schiabel eba6c6d7ef fix(release): keep provider peer bumps range-aware (#3582)
This PR:
- prevents the open Changesets release PR from promoting provider
packages to `1.0.0` when `@composio/core` gets a minor bump that still
satisfies their peer range
- points Changesets at `next`, matching the active TypeScript release
branch and workflow trigger
- enables `onlyUpdatePeerDependentsWhenOutOfRange` so peer dependents
only major-bump when the new dependency version leaves their declared
range
- adds a release workflow guard that runs Changesets against a fixture
and verifies `@composio/core@0.10.0` -> `0.11.0` keeps
`@composio/openai` on `0.9.3`
- leaves https://github.com/ComposioHQ/composio/pull/3429 to regenerate
after this lands on `next`
2026-06-16 16:04:25 +04:00
Anshu Garg 56e0d781f3 fix(triggers): handle V3 envelope in realtime subscribe path [SUP-392] (#3567)
## Summary

`triggers.subscribe()` crashes with `KeyError: 'nanoId'` on the **first
event** for any project configured with webhook version **V3**. The
realtime (Pusher) channel now delivers the modern V3 envelope
(snake_case: `metadata.trigger_id` / `connected_account_id` /
`auth_config_id`, with no top-level `nanoId`), but the realtime parser
(`TriggerSubscription._parse_payload`) only understood the **legacy**
envelope and accessed `data["metadata"]["nanoId"]` directly — so the
very first inbound frame raises inside the Pusher `_on_message` callback
and the registered handler is never invoked.

The SDK already knows how to normalize the V3 envelope — it does so on
the webhook path (`_normalize_v3_payload`) — that logic was simply never
wired into the realtime path.

This has affected the realtime subscribe path for V3 projects since the
V3 trigger payload format was introduced; webhook-version V1/V2 projects
are unaffected (they still receive the legacy realtime envelope).

## Changes

- Extract the V3 → `TriggerEvent` normalization into a shared
module-level helper (`_build_trigger_event_from_v3`) plus an envelope
detector (`_is_v3_envelope`); the webhook path's `_normalize_v3_payload`
now delegates to it, so webhook and realtime share one source of truth.
- `TriggerSubscription._parse_payload` now detects the V3 envelope and
normalizes it, and keeps the existing legacy mapping for V1/V2 payloads.
- Harden `_parse_payload`: unknown/malformed frames are logged and
skipped (return `None`) instead of raising, so a single bad frame can no
longer tear down an active subscription.
- Add tests covering V3 realtime parsing, legacy realtime parsing, and
malformed-frame handling.

## Type of change
- [x] Bug fix
- [ ] New feature
- [ ] Refactor/Chore
- [ ] Documentation
- [ ] Breaking change

## How Has This Been Tested?

- `ruff check` + `ruff format` (config/ruff.toml) — clean.
- `uv run pytest tests/test_triggers.py` — **52 passed** (49 existing +
3 new).
- New tests:
- `test_parse_payload_v3_realtime_envelope` — a V3 realtime frame parses
to a `TriggerEvent` (no `KeyError`).
- `test_parse_payload_legacy_envelope` — V1/V2 legacy frame still parses
correctly.
- `test_parse_payload_malformed_returns_none` — bad/partial frames are
skipped, not raised.

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

## Additional context

The realtime envelope is identical in shape to the V3 webhook envelope,
so the shared normalizer keeps the two delivery channels consistent. No
public API changes.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: jkomyno <alberto@composio.dev>
Co-authored-by: Alberto Schiabel <jkomyno@users.noreply.github.com>
2026-06-16 15:39:23 +04:00
Alberto Schiabel 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>
@composio/cli@0.2.32-beta.265
2026-06-16 15:07:23 +04:00
XananasX 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>
2026-06-16 13:48:45 +04:00
Alberto Schiabel a9b948bac2 fix(ci): use app token for SDK docs PRs (#3577)
This PR:
- fixes
https://github.com/ComposioHQ/composio/actions/runs/27606982132/job/81621371312
- mints the existing release-bot GitHub App token in both SDK docs jobs
- passes the App token to checkout and `peter-evans/create-pull-request`
- uses the same App token for the reviewer-assignment `gh pr edit` step
- keeps the TypeScript and Python docs generation commands unchanged

Verification:
- `git diff --check`
- `ruby -e \"require 'yaml';
YAML.load_file('.github/workflows/generate-sdk-docs.yml'); puts 'yaml
ok'\"`
- `bash .github/scripts/check-action-repos.sh`
- confirmed `RELEASE_BOT_APP_ID` and `RELEASE_BOT_APP_PRIVATE_KEY` exist
in repo secrets
2026-06-16 13:24:11 +04:00
Anshu Garg 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>
2026-06-16 13:10:37 +04:00
Alberto Schiabel 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>
2026-06-16 12:49:37 +04:00
Malay Vasa d8ec506ec8 fix docs Decimal widget loading (#3575)
## Summary
- stop loading the Decimal widget globally from the docs root layout
- load the Decimal script only when the user clicks Ask AI or uses the
shortcut
- preserve Decimal theme syncing after the widget has loaded

## Why
Slack/GSC investigation pointed at mobile CLS regressions on docs pages.
Lighthouse trace comparison isolated the layout shift to the Decimal
iframe/sidebar; blocking Decimal took /docs CLS from ~0.302 to 0, while
blocking PostHog did not change CLS.

## Validation
- bun run types:check
- bunx eslint app/layout.tsx components/ask-ai-button.tsx
components/custom-search-dialog.tsx components/decimal-widget.ts
- bun run test
- local Playwright check on http://localhost:3000/docs: no getdecimal
scripts or requests before interaction; after clicking Ask AI the
Decimal script loads and the sidebar opens

## Notes
- full `bun run lint` is still red on existing unrelated docs lint
issues on next, including @next/next/no-html-link-for-pages and
react-hooks compiler rules in other files
2026-06-15 18:10:36 -07:00
shams haroon e2e6b5974d docs: add MCP, files, and realtime routes to scoped API key permissions (#3550)
Updates the scoped project API key permissions reference with the routes
cataloged in ComposioHQ/platform#10638 (PLEN-2623):

- **Sessions** — now covers MCP server management (`/mcp/servers*`,
`/mcp/{id}`, instances), the MCP runtime transport, and the tool router
MCP transport
- **Tool execution** — adds `POST /files/upload/response` and `GET
/files/list` (file legs of tool execution)
- **Triggers** — adds the SDK/CLI realtime subscribe endpoints
(`triggers.subscribe()` / `composio triggers listen`)

Tables mirror `PROJECT_API_KEY_PERMISSION_CATALOG` as of the platform
merge.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-15 15:11:39 -07:00
shams haroon 99cfe17b18 docs: rename scoped API keys page title to "Scoped Project API Key"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-15 15:08:54 -07: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>
@composio/cli@0.2.32-beta.264
2026-06-15 19:38:51 +04:00
Alberto Schiabel 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`
@composio/cli@0.2.32-beta.263
2026-06-15 15:27:21 +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
Sarah Simionescu 382f0b1c72 Create box-integration.mdx (#3565)
Adds a hidden Box integration docs page for use as the "Add" button link
in the Box app directory submission.
2026-06-14 21:20:30 -07:00
Aaliya 938eade263 Create box-integration.mdx 2026-06-14 13:05:28 -05:00
palash-c 1124aed57a docs: MCP servers → Sessions migration guide (twoslash-fixed re-add of #3551) (#3553)
Re-adds the MCP servers → Sessions migration guide that landed in #3551
and was reverted in #3552 because the docs build broke.

**Root cause of the original break:** the docs site type-checks every TS
code block via twoslash. The standalone snippets (direct-tools preset,
`session.tools()`, `session.execute()`) referenced `composio` /
`session` without declaring them → `[2552] Cannot find name 'composio'`.
Fixed by adding a hidden `import` + `const composio` + `// ---cut---`
setup preamble to each block (the same pattern
`configuring-sessions.mdx` uses), and lifting the tools/execute examples
out of nested list bullets into their own section.

**Verified locally** against latest `next`: `bun run build` → `✓
Compiled successfully` + `✓ Generating static pages (1410/1410)`, exit
0.

Files: new
`docs/content/docs/migration-guide/mcp-servers-to-sessions.mdx` +
registered in `migration-guide/meta.json`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-06-12 15:25:56 +05:30
Palash Kala 39af0f007c docs: drop client names + connect.composio.dev link, add guide to migration index
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 15:03:43 +05:30
Palash Kala a6acec9071 docs: add MCP servers → Sessions migration guide (twoslash-safe re-add of #3551)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:54:31 +05:30
Rahul Tarak 08810af023 Revert "docs: add MCP servers → Sessions migration guide" (#3552)
Reverts ComposioHQ/composio#3551
2026-06-12 01:09:22 -07:00
palash-c b77dbe8444 docs: add MCP servers → Sessions migration guide (#3551)
Adds a migration guide for developers moving from **MCP servers**
(`composio.mcp.create` / `composio.mcp.generate`, the "Single Toolkit
MCP" flow) to **sessions**.

New page:
`docs/content/docs/migration-guide/mcp-servers-to-sessions.mdx`
(registered in `migration-guide/meta.json` after `direct-to-sessions`).

### What it covers
- What carries over (tools, auth configs/connected accounts — no
re-auth, the MCP URL pattern, per-user isolation, fixed tool lists)
- Old → new mapping table + the *why*
- 3-step migration (`composio.create` replaces server+generate · point
the client at `session.mcp.url` · direct-tools preset for a fixed tool
list)
- Things to know: reuse one session, `session.tools()` as native
framework tools, `session.execute()` for tool execution without an LLM,
shared connections, tenant params, white-labeling, triggers, and a
pointer to **Composio For You** (connect.composio.dev) for
no-code/personal app connections

### Before merge
- [ ] Confirm cross-links resolve in preview
(`/docs/configuring-sessions`,
`/docs/authenticating-users/shared-connections`,
`/docs/white-labeling-authentication`, `/docs/how-composio-works`)
- [ ] Sanity-check the `session.execute` / `session.tools` /
direct-tools-preset snippets against the current SDK
- [ ] Confirm the `https://connect.composio.dev` link + product-switcher
wording for Composio For You

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 00:59:52 -07:00
Tri 6478b80169 docs: add HVTracker badge to README (#3501)
Closes #3490
2026-06-11 22:05:12 -04:00
shams haroon 84445bcacb docs: add MCP, files, and realtime routes to scoped API key permissions
Catalog additions from ComposioHQ/platform#10638 (PLEN-2623):
- sessions now covers MCP server management and both MCP transports
- tool execution adds files upload/response and files list
- triggers adds the SDK/CLI realtime subscribe endpoints

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 10:21:45 -07:00
Dushyant Acharya 114ce807cb docs: add HVTracker badge to README 2026-06-10 19:49:26 -04:00
shams haroon 094aed6b98 rename scoped API key reference (#3534)
## Summary
- Rename the scoped key reference page title to `Scoped project API
keys`
- Update the two cards that link to the page so the visible label is
consistent

## Validation
- `bun run lint:links`
- `bun run types:check`
2026-06-09 20:27:15 -07:00
Rahul Tarak 4abf06b23f ci: use GitHub App token for the release bot (replaces expired CI_BOT_TOKEN) (#3539)
## Problem

The changeset release bot (`ts.release.yml` → `changesets/action`)
authenticated with the **`CI_BOT_TOKEN`** personal access token. That
PAT expired, so **every "TS SDK Release" run since 2026-06-04 failed**
with:

```
HttpError: Bad credentials - https://docs.github.com/rest
```

`changeset version` ran fine, but the GitHub API call to create/update
the "Release: update version" PR failed — so no version PR, no publish.
(This is why 0.2.31 had to be shipped via a manual version bump in
#3538.)

## Fix

Mint a **short-lived GitHub App installation token** with
[`actions/create-github-app-token`](https://github.com/actions/create-github-app-token)
(pinned to `bcd2ba4` / v3.2.0) and use it for both `checkout` and the
`changesets/action` step, instead of the PAT.

Why an App token over a PAT or the default `GITHUB_TOKEN`:
- **No silent expiry** — minted per run; nothing to rotate manually
(exactly what just broke).
- **Triggers downstream workflows** — the default `GITHUB_TOKEN` is
blocked from triggering other workflows, so the version-PR merge would
never kick off `build-cli-binaries.yml` to publish. App-token-created
events *do* trigger them (same as a PAT, better hygiene).
- **Not tied to a personal account.**

(OIDC was considered but doesn't apply here — it authenticates to
*external* services like cloud/npm trusted-publishing, not
GitHub-internal PR/push operations.)

## Required setup before this lands

Create a **GitHub App** (org-owned), installed on this repo, with
repository permissions:
- **Contents: Read & write**
- **Pull requests: Read & write**

Then add two repo secrets:
- `RELEASE_BOT_APP_ID` — the App's ID
- `RELEASE_BOT_APP_PRIVATE_KEY` — a generated private key (full PEM)

Once those exist, the next push to `next` with pending changesets will
regenerate the "Release: update version" PR correctly. `CI_BOT_TOKEN`
can then be deleted.

## Out of scope / follow-up

`docs.sync-connect-clients.yml` also uses `CI_BOT_TOKEN` (as
`GH_TOKEN`). It can be migrated to the same App token in a follow-up;
left untouched here to keep this focused on the release pipeline.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 02:23:36 -07:00
Rahul Tarak 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>
0.2.31 @composio/cli@0.2.31 @composio/cli@0.2.31-beta.259
2026-06-09 02:18:21 -07:00
Rahul Tarak df104ec1fa chore: CLI 0.2.31 patch release (#3536)
## Changes since `@composio/cli@0.2.30`

### Features
- **feat(cli): `composio upgrade <version>`** (#3428) — install a
specific stable or beta release (`0.13.1`, `0.13.1-beta.42`, or full
tag). No-arg behavior unchanged; `--beta` still controls the
latest-prerelease case.
- **feat(cli): send `x-cli-session-id` header** (#3430) — attach the
per-cwd CLI session id to every client request so tool execution logs
can be grouped by CLI session.
- **feat(cli): refresh approval fallback page** (#3431) — browser
fallback tool-approval prompt restyled in the CLI landing-page visual
language and served directly from the loopback callback server; native
macOS sidecar remains preferred.

### Fixes
- **fix(cli): make output more LLM-friendly** (#3450) — route logger
output to stderr, gate human-only notices/prompts on interactive TTYs,
keep `composio run` helper/subagent logs off stdout.
- **fix(cli): permission allows expire after 1 hour** (#3449) — prompt
action relabeled "Allow for 1 hr"; cached allow decisions expire after
1h with stale-entry pruning.
- **fix: fish completion install paths** (#3162) — write completions to
`~/.config/fish/completions/composio.fish` and sanitize lines that could
break parsing.

## Changeset

A single patch bump (`@composio/cli` → 0.2.31) aggregated from the
pending changesets:
- `.changeset/cli-upgrade-version-arg.md`
- `.changeset/cli-session-id-header.md`
- `.changeset/cli-permission-fallback-design.md`
- `.changeset/quiet-llm-friendly-cli.md`
- `.changeset/cli-fish-completions-and-permission-expiry.md` (new —
covers #3162 and #3449)

## Testing

### Phase 1: CI Types/Lint
- N/A for this branch — `ts.typecheck` / `ts.test` / `ts.build` are
gated on `paths: ts/**`, and this branch only adds a `.changeset/*.md`.
Each underlying CLI PR (#3428/#3430/#3431/#3449/#3450/#3162) already
passed CI when merged to `next`.

### Phase 2: Local Binary Test ✅
Built from source (`pnpm turbo build` → `build:binary`) and tested:
- `composio version` → `0.2.30` ✅ · `composio whoami` → JSON ✅ ·
`composio --help` ✅
- `composio run 'console.log(...)'` → clean stdout (LLM-friendly stderr
routing confirmed, #3450) ✅
- `composio upgrade` `<version>` arg wired (`normalizeReleaseTag`,
#3428) ✅
- `SLACK_SEND_MESSAGE` input validation correctly rejects unknown keys
(LLM-friendly errors) ✅
- **Slack integration test** ✅ — `SLACK_FIND_CHANNELS` →
`SLACK_SEND_MESSAGE` → `SLACK_FETCH_CONVERSATION_HISTORY` →
`experimental_subAgent` (structured output via `z` schema +
`result.prompt()`) → summary posted to `#buzz-skill-based-cli-testing`.

### Phase 3: Bundled Binary (CI) ✅ pipeline unblocked
The CI binary pipeline was briefly blocked by a new org policy requiring
SHA-pinned actions — **already resolved on `next` by #3531**
(`chore(ci): pin GitHub Actions to SHAs`). A validation `build-beta` on
an identically-pinned branch confirmed the fix: "Resolve Release
Metadata" passes and binaries build/test green across platforms.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-09 02:10:07 -07:00
shams haroon 43b2057847 docs: rename scoped api key reference 2026-06-08 20:43:53 -07:00
shams haroon e4ec5476a8 add project api key permissions docs (#3532)
## Summary
- Add a Project API key permissions reference page under `Reference >
Authentication`.
- List the routes covered by each permission area and access level.
- Add stable anchor links for dashboard Learn more links, for example
`/reference/authentication/project-api-key-permissions#webhooks`.
- Link the new page from the Reference authentication overview and the
Projects page.
- Fix two existing docs build blockers that prevented local
preview/build: quote SDK reference frontmatter and use `zod/v3` in the
migration-guide custom tool sample.

## Validation
- `bun run lint:links`
- `bun run types:check`
- `bun run build`
- `curl -I
http://localhost:3000/reference/authentication/project-api-key-permissions`
returned `200` locally.
2026-06-08 17:45:15 -07:00
Alberto Schiabel 90a436e393 chore(ci): pin GitHub Actions to SHAs (#3531)
## Summary
- Pin every remote GitHub Action used by `.github/workflows` and
`.github/actions` to a full 40-character commit SHA with a version
comment.
- Update each action to the latest upstream tag available at the time of
this change.
- Migrate Slack incoming-webhook steps to the latest
`slackapi/slack-github-action` major by passing `webhook` and
`webhook-type: incoming-webhook` explicitly.
- Keep the live Python integration test step non-blocking so an external
credential issue does not fail unrelated PR CI.

## Upgrade notes
- Read README/release notes for major-version upgrades:
`actions/checkout`, `actions/cache`, `actions/download-artifact`,
`actions/github-script`, `actions/setup-node`, `actions/setup-python`,
`actions/upload-artifact`, `astral-sh/setup-uv`, `pnpm/action-setup`,
and `slackapi/slack-github-action`.
- The GitHub-owned action upgrades keep existing workflow inputs
compatible; their README notes are mainly Node 24/runtime and minimum
runner-version requirements.
- `actions/github-script@v9` no longer supports requiring
`@actions/github` internals, but these workflows only use injected
`github`, `context`, and `core`.
- `slackapi/slack-github-action@v3` requires explicit webhook technique
configuration, now added in the four Slack notification steps.

## Verification
- Strict local audit: 83 remote `uses:` entries across 21 action
repos/reusable workflows are full SHAs with expected comments.
- Remote metadata audit: all 21 pinned remote refs resolve, and each
action metadata file or reusable workflow file exists at the pinned SHA.
- `.github/scripts/check-action-repos.sh`
- `ruby -e 'require "yaml"; Dir[".github/workflows/*.{yml,yaml}",
".github/actions/**/*.yml", ".github/actions/**/*.yaml"].each { |f|
YAML.load_file(f); puts "ok #{f}" }'`
- `git diff --check`
- `go run github.com/rhysd/actionlint/cmd/actionlint@latest -shellcheck=
-pyflakes= -ignore 'label "depot-ubuntu-[^\"]+" is unknown'`

`actionlint` without the ignore only reports the existing custom Depot
runner labels in `cli.test-installation.yml`.
2026-06-08 14:39:33 -07:00
Alberto Schiabel 80448048a8 docs: remove legacy custom tools references and retarget redirects (#3510)
This PR is **part 3 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 **docs**
slice.

- builds on top of https://github.com/ComposioHQ/composio/pull/3509
(stacked — this PR's base is `remove-ts-custom-tools`)
- deletes the legacy `/docs/tools-direct/custom-tools` page and prunes
its `meta.json` entry
- retargets redirects for `/docs/tools-direct/custom-tools` and the
`:path*` wildcard to `/docs/toolkits/custom-tools-and-toolkits`, with
matching `redirects.test.ts` expectations
- updates migration-guide, glossary, proxy-execute, and executing-tools
prose; fixes the `ctx.proxyExecute` example to include the required
GitHub toolkit
- updates agent guidance (`AGENTS.md`, `building-agents` skills) to the
experimental custom tools API

## Notes

- This slice is a byte-identical subset of #3505 — the three split
branches recombine to that PR's exact tree. Docs link/redirect checks
could not run in the source checkout (missing docs deps); CI runs them
per PR.
2026-06-04 23:54:08 -07: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
Alberto Schiabel 2758287c87 feat(py): remove legacy custom tools (#3508)
This PR is **part 1 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 **Python**
slice.

- removes the legacy `composio.tools.custom_tool` registry path:
`core.models.custom_tools`, `ExecuteRequestFn`, the old fallback
execution wiring, the security tests, and the example
- preserves the 2026 tool-router APIs: `composio.experimental.tool()`,
`composio.experimental.Toolkit`, inline custom-tool execution,
preload/attach/use flows, and `session.custom_tools()`
- bumps the Python workspace and all provider packages `0.13.1` →
`0.14.0`

## Notes

- 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
local verification logs (`uv run --frozen nox -s chk`, targeted pytest);
CI re-runs per PR.
2026-06-04 23:53:26 -07:00
Alberto Schiabel 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>
2026-06-04 23:53:13 -07:00
Alberto Schiabel 07160d14fa feat(toolchain): introduce mise.toml as single source of truth (#3492)
## Summary

This PR starts Phase 1 of PLEN-1368 by adding `mise.toml` as the
repo-owned source for the primary toolchain versions:

- Node `20.20.2`
- Bun `1.3.10`
- Deno `2.6.7`
- Python `3.12`
- uv `0.8.19`

It also keeps pnpm corepack-driven through
`package.json#packageManager`, adds `devEngines` for Node/pnpm
visibility, documents the new `mise install && corepack enable && pnpm
install` bootstrap path, ignores `.mise.local.toml`, and fixes stale
release-doc prerequisites.

## Why

The repo already has real toolchain drift, not just duplicated version
strings. The internal release docs had stale Node/Bun/pnpm versions,
Deno is repeated across workflows, Dockerfiles, docs, and e2e helpers,
and Python local setup still has a separate `3.11` venv path while the
repo pins `3.12`.

A composite-action cleanup would improve CI, but it would not solve
local development. `mise.toml` gives us one file that declares the
versions and lets contributors install or switch them with one command.
That is the main value proposition here: make the repo declare its own
toolchain, then let CI consume the same declaration in the next phase.

## Rollout

This is deliberately additive. It does not remove `.nvmrc`,
`.bun-version`, `.python-version`, or `.dvmrc`, and it does not change
CI behavior yet. Contributors who do not use mise can keep working as
before; contributors who do use mise get managed Node/Bun/Deno/Python/uv
immediately.

Phase 2 can migrate the existing composite actions to
`jdx/mise-action@v4`. Phase 3 can remove the legacy version files and
add the lockfile once the transition is complete.

## Out of Scope

- Migrating CI to `jdx/mise-action@v4`
- Removing legacy version files
- Adding `mise.lock`
- Updating nested TS package/example `packageManager` fields that still
say `pnpm@10.28.0`; that is pre-existing metadata drift and should be
handled separately to avoid broadening Phase 1

## Verification

- `git diff --check origin/next...HEAD`
- `mise install && mise current`
- `pnpm --version` -> `10.28.2`
- `pnpm dlx prettier@3.8.1 --check package.json`

Refs: PLEN-1368
2026-06-04 23:50:59 -07:00
palash-c f4ac55652b changelog: link Workbench session reference to the sessions doc (#3519)
Small follow-up to #3517 (merged). Adds a docs link to the **Workbench**
changelog item — the only outstanding ask from the review thread
(Karan/Palash):

> Code execution through the remote workbench … now runs only inside a
[Composio session](https://docs.composio.dev/docs/how-composio-works).

No other changes; the rest of the entry is as merged.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 13:53:37 -07:00
palash-c 17525ecb67 changelog: api security updates (2026-06-04) (#3517)
Adds one concise changelog entry:
`docs/content/changelog/06-04-26-security-reliability-hardening.mdx`.

Summarizes the post-incident wave of changes, link-forward (no
migration-guide links), matching the existing
`docs/content/changelog/*.mdx` format. Source of truth + rationale live
in Linear PRO-255 (Customer Comms).

### What it covers
- **Auth / API keys:** MCP auth required, cookie/session auth removed on
v3.1, non-recoverable keys, **scoped API keys** (Proxy Execute opt-in at
creation, off by default), auto-added IP allowlists, **MFA available for
Dashboard sign-in (off by default)**.
- **Connections:** managed-OAuth `initiate` → `link` (Jul 3 cutover),
token redaction across **managed + custom** auth configs, Proxy Execute
for provider actions.
- **Webhooks / Endpoints:** public-URL + signed deliveries;
`/api/rerouted/v1` and `/v2` retired (`410`).
- **Dashboard:** `platform.composio.dev` → `dashboard.composio.dev`
redirect, restoration-period `401`s (API/SDK stay functional), MCP
configs view removed (use the MCP API / move to Composio sessions).

### Before merge (reviewer checks)
- [ ] Confirm links resolve: Proxy Execute, Webhook Subscriptions API,
MCP API reference, Composio sessions.
- [ ] Re-confirm live state: MFA is opt-in (not required);
destructive-tool denylist was re-enabled.
- [ ] Confirm the per-project two-factor toggle is intentionally
excluded (distinct from Dashboard MFA).
- [ ] Confirm publish date (`2026-06-04`).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Rahul Tarak <cryogenicplanet@gmail.com>
2026-06-04 13:38:17 -07:00