Follow-up to https://github.com/ComposioHQ/composio/pull/3885, which is
now merged into `next`.
This PR:
- reports pending-login cache read failures as I/O errors instead of
masking them as decode failures (`composio login --poll`)
- restores pairwise polarity assertions for the `semverComparator`
Array.sort compatibility case
- consolidates the duplicated ephemeral HTTP server test helper in
`test/__utils__/http-server.ts`
- makes server-owned connected-account statuses forward-compatible while
preserving the credential-stripping schema allowlist
- redacts raw payload values from connected-account parse warnings and
adds regression coverage for unknown statuses and secret-bearing
malformed payloads
- documents why the client-singleton test re-derives the consumer cache
cwd hash
## Rebase notes
Rebased onto `origin/next` at `ef1ec9148`.
- Dropped the empty `GITHUB_*` compatibility commit; that contract is
already present on `next` through
https://github.com/ComposioHQ/composio/pull/3880.
- Adapted the connected-account decoder rename to the service extracted
upstream in `connected-account-selection.ts`.
## Context
Fix-forward PR for actionable Cursor Bugbot findings on the guardrails
stack (#3877–#3885). The stale decode-error string match and unused
release helper were already resolved upstream, and the `vi.stubEnv(...,
undefined)` concern is not actionable on Vitest 4.1.10.
Apply verified code-review findings: write through symlinked startup
files with preserved mode and a per-process tmp name; verify delegated
CLI setup actually reconciled the managed block before trusting exit 0;
make managed-block reconciliation assignment-aware so annotated blocks
never lose user content or PATH precedence; clean up the CLI's tmp file
when an atomic write fails; assert the auto contract in the install
health-check canary; recommend composio install --shell in generated
release docs; record the new default in the CLI changelog.
COMPOSIO_INSTALL_SHELL grows auto (the new default) and none. auto
infers the login shell from $SHELL and always runs idempotent setup
for recognized shells; none keeps install-only behavior for CI and
dotfile managers. Final output follows the KD4 state matrix against a
pre-install PATH snapshot with physical-path identity, setup failures
never fail the install, and the managed PATH block reconciles stale
bin directories.
Fixes#4030
## Problem
`checkForLatestVersionFromNPM` queried the right package but named the
wrong one in the notice it printed:
```ts
// ts/packages/core/src/utils/version.ts:29
const packageName = '@composio/core';
...
// ts/packages/core/src/utils/version.ts:52
`🚀 Upgrade available! Your composio-core version (${currentVersionFromPackageJson}) is behind. …`
```
`composio-core` is the v2 npm package. A v3 user saw a notice naming a
package they had not installed, and the obvious next step — `npm i
composio-core@latest` — installs the legacy package. That is a downgrade
path, not just a wording slip.
Leftover string from the v2 SDK: the surrounding code was migrated to
`@composio/core`, the message was not.
## Fix
One line — interpolate the constant already in scope, as the issue
suggested:
```diff
-`🚀 Upgrade available! Your composio-core version (${currentVersionFromPackageJson}) is behind. …`
+`🚀 Upgrade available! Your ${packageName} version (${currentVersionFromPackageJson}) is behind. …`
```
I used the constant rather than hardcoding `@composio/core` so the
notice and the registry URL now derive from a single source and cannot
drift apart again.
## Verification
Ran the issue's reproduction against the fix, with the registry response
stubbed and `CI`/`DEVELOPMENT` unset:
```text
🚀 Upgrade available! Your @composio/core version (0.14.1) is behind. Latest version: 0.99.0.
registry URL actually queried: https://registry.npmjs.org/@composio/core/latest
```
The name in the message and the package actually queried now match
exactly.
| Check | Result |
|---|---|
| `tsc --noEmit` | exit 0 |
| Full core suite | 1037 passed / 3 failed — identical to unmodified
`next` |
The 3 failures are pre-existing and environmental on the Windows machine
used here: two `EPERM: symlink` (needs Developer Mode) and one POSIX
path-separator assumption in `fileUtils.test.ts`. Confirmed by stashing
and re-running against `next`.
## Notes
- No test added. Interpolating the constant makes this class of drift
structurally impossible, which is a stronger guarantee than asserting
exact log text. There is also a practical cost: #4026's branch
introduces `ts/packages/core/test/utils/version.test.ts`, so adding that
same new file here would create an add/add conflict between two open
PRs. Happy to add coverage as a follow-up once that one lands.
- Related, deliberately left out of scope.
`ts/packages/cli/src/effects/find-composio-core-generated.ts:38` has the
same stale name, and arguably worse:
```ts
const fix = `Install \`composio-core\` with \`${installCmd} composio-core\`, …`;
```
- The code twelve lines below probes `import composio` — the v3 Python
package — so a user following that message runs `uv pip install
composio-core`, installs v2, and the check still fails. I left it alone
because `@composio/cli` is a separate package with its own release
process (it is excluded from changesets), and the two are independent
string literals with no shared function, so there is no single root to
fix. Worth its own issue.
- I checked the other `composio-core` references repo-wide: the
changelog entries and `docs/content/docs/migration-guide/new-sdk.mdx`
correctly cite v2 as history, and the remainder are CLI test-fixture
directory names. Nothing else needed changing.
Fixes#4032
## Problem
The JSDoc on `getToolkitVersionsFromEnv` documented a precedence order
the function does not implement:
```ts
// ts/packages/core/src/utils/sdk.ts:65-69
* 2. Environment variables (COMPOSIO_TOOLKIT_VERSION_<TOOLKIT_NAME>)
* 3. User-provided toolkit version mappings (defaultVersions object)
```
The implementation spreads user-provided values last, so they win:
```ts
const toolkitVersions = {
...toolkitVersionsFromEnv,
...userProvidedToolkitVersions,
};
```
Three independent sources already agreed the code is right and the JSDoc
was the outlier:
1. The inline comment two lines above the spread — "user provided values
act as overrides" (`sdk.ts:91`).
2. `test/core/versions.test.ts:150` (`'should prioritize user-provided
versions over environment variables'`) and `:395` (`'should demonstrate
priority order: user object > env vars > fallback'`).
3. The Python SDK's docstring for the equivalent `get_toolkit_versions`,
which had the order correct.
This misleads anyone debugging a version pin: someone whose
`COMPOSIO_TOOLKIT_VERSION_GITHUB` appears to be ignored reads this and
concludes the env-var handling is broken, when the real cause is their
own `toolkitVersions` object overriding it.
## Fix
Swapped the two lines. Comment-only — no runtime behaviour changes.
```diff
- * 2. Environment variables (COMPOSIO_TOOLKIT_VERSION_<TOOLKIT_NAME>)
- * 3. User-provided toolkit version mappings (defaultVersions object)
+ * 2. User-provided toolkit version mappings (defaultVersions object)
+ * 3. Environment variables (COMPOSIO_TOOLKIT_VERSION_<TOOLKIT_NAME>)
```
I kept this to a pure swap rather than also rewording. The Python
docstring is the parity target, and the two lists are now item-for-item
identical:
1. If `defaultVersions` is a string, use it as global version for all
toolkits
2. User-provided toolkit version mappings (`defaultVersions` object)
3. Environment variables (`COMPOSIO_TOOLKIT_VERSION_<TOOLKIT_NAME>`)
4. Fallback to `'latest'` if no versions are configured
Adding clarifying prose on the TypeScript side alone would have traded
one cross-SDK drift for another.
## Verification
Exercised all four documented items against real behaviour, not just the
one in the report:
```text
env : COMPOSIO_TOOLKIT_VERSION_GITHUB=from_env_20250101_00, _SLACK=slack_from_env
user : { github: "from_user_20260101_00" }
result: { github: 'from_user_20260101_00', slack: 'slack_from_env' }
github winner : from_user_20260101_00 <- user-provided (doc item 2)
slack winner : slack_from_env <- env var, untouched by user (doc item 3)
string form : 20260101_00 <- doc item 1
empty form : latest <- doc item 4
```
The slack case is the one worth noting: items 2 and 3 are not a strict
either/or fallback — the two maps merge per toolkit, and env vars still
apply for toolkits the user's object does not mention. The numbered list
describes that correctly now, since what it orders is precedence.
| Check | Result |
|---|---|
| `tsc --noEmit` | exit 0 |
| `test/core/versions.test.ts` | 32 passed |
I ran the targeted suite rather than the full one: the change is a
comment and cannot affect anything outside this file, and those 32 tests
are exactly the ones asserting this precedence.
## Notes
- No changeset — comments only, nothing in the published output changes.
- No test added: the existing tests at `versions.test.ts:150` and `:395`
already lock this behaviour in. They are what proved the code was
correct and the doc was wrong, so the doc is now covered by them too.
This PR:
- fixes#4024
- supersedes #4025 with target-filesystem detection instead of
unconditional case folding
- uses `is-fs-case-sensitive` on the nearest existing directory so mixed
mounts and case-sensitive filesystem configurations are handled
correctly
- preserves exact matching on case-sensitive filesystems and falls back
to conservative case-insensitive matching when detection fails
- keeps Node-only detection behind `#platform` and mirrors its runtime
dependency in `@composio/slim`, preserving the workerd-safe bundle and
Slim import
- adds focused Node, workerd, and matcher regressions plus an
`@composio/core` patch changeset
- verifies 1,044 core tests, five CLI upload tests, the Slim
build/import smoke, typecheck, build, ATTW, publint, lint, formatting,
frozen install, and changeset validation
This PR:
- supersedes https://github.com/ComposioHQ/composio/pull/4010 and
credits @MGPOCKY for identifying the stale Cloudflare E2E Node override
- lets Cloudflare E2E resolve the exact Node.js version from mise.lock
through the shared setup action
- retains the release job's explicit Node.js 24.17.0 publishing pin and
corrects its outdated explanation
- verifies the release workflow guard, workflow YAML parsing,
formatting, and whitespace checks
Co-authored-by: MGPOCKY <kkm1447@naver.com>
The **I still need help** section of Composio Connect points users at
`tech@composio.dev`.
It's the only place in the docs that does. Every other reference uses
`support@composio.dev`:
- `docs/content/reference/errors.mdx`
- `docs/content/reference/v3/errors.mdx`
- `docs/content/changelog/12-30-25.mdx`
- `docs/content/changelog/01-29-26-sdk-major-update.mdx`
- `docs/content/changelog/03-25-26-mcp-endpoint-removed.mdx`
Composio Connect is the page consumer users land on when wiring up an
MCP client, so this was the most visible instance of the wrong address.
One line changed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Alberto Schiabel <jkomyno@users.noreply.github.com>
Replace the base installer's --shell flag with a COMPOSIO_INSTALL_SHELL
environment variable, matching the COMPOSIO_INSTALL_VERSION precedent
and reading more naturally in the curl-pipe form:
curl -fsSL https://composio.dev/install | COMPOSIO_INSTALL_SHELL=zsh sh
The variable is validated before any network call. Shell variants set
it explicitly when invoking the base installer, so the route stays
authoritative over any inherited value. The composio install --shell
CLI flag and the delegation/fallback behavior are unchanged.
Teach install.sh a --shell <zsh|bash|fish> flag that performs the same
shell setup the /install/<shell> variants do: delegate to
'composio install --shell' when the installed CLI supports it, fall
back to writing the # Composio CLI PATH block inline otherwise.
The shell variants become thin wrappers that fetch the base installer
and append '--shell <name>' to the forwarded arguments, so the
delegation and fallback logic now lives in exactly one script. This
also removes the double-configuration hazard of a variant blindly
forwarding a user-supplied --shell.
Shell setup no longer depends on the composio.dev/install/<shell>
redirect rules existing: post-install guidance, docs, and release
notes now print 'curl -fsSL https://composio.dev/install | sh -s --
--shell <shell>', which works through the single existing redirect.
The variant scripts and their raw-URL preview commands keep working
for when the routes land.
Coverage: direct --shell delegation, fallback on unsupported or
failing CLI, missing and invalid values failing before any network
call, and a Docker e2e leg for the idempotent --shell bash flow.
Adds the missing auth-config step to the existing Custom MCP page
(extending-sessions/custom-mcp.mdx): create the config with
`is_enabled_for_tool_router: true`, PATCH guidance for existing configs,
and updates the session + known-gaps sections from "don't rely on
auto-match" to "auto-match works when the flag is set".
Why: session account-matching only considers flagged auth configs, and
after the revert of platform#11223 there is no server-side default for
custom toolkits. A config created without the flag makes every session
execution fail with `NoActiveConnection`. The docs are what stands
between a pilot partner and that dead end.
Draft while the feature is experimental/LD-gated.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Session auto-match only considers auth configs with this flag, and the
custom flow has no default (platform#11223 was reverted), so configs
created without it fail session execution with NoActiveConnection. Adds
the auth-config creation step with the flag, a PATCH note for existing
configs, and updates the session and known-gaps guidance from "don't
rely on auto-match" to "auto-match works when the flag is set".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The is_enabled_for_tool_router step is load-bearing: after the revert of
platform#11223 there is no default, and configs created without the flag
make session execution fail with NoActiveConnection.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>