Commit Graph

1095 Commits

Author SHA1 Message Date
jkomyno 16b167c94a docs(cli): document COMPOSIO_BIN_DIR and the install abort contract
COMPOSIO_BIN_DIR was discoverable only by reading the changelog: it is
read through a raw ConfigProvider and appeared in no help text. Add it to
the README env-var table with its resolution order, and name it in the
install command description so `composio install --help` mentions it.
No --bin-dir flag: the env var is the right shape for an installer
handoff.

The changelog entry also picks up the behavior changes it was missing —
the non-zero exit on abort and what it means for install.sh's fallback,
both abort conditions, the narrowed character set, legacy-block
migration, and a note for custom-install-dir users reinstalling without
re-specifying COMPOSIO_INSTALL_DIR.
2026-08-04 19:17:14 +05:30
jkomyno 745bd67cef fix(cli): make composio install reconcile stale managed blocks
Three changes to the PATH writer, all around the same failure mode: the
command reporting success while leaving a shell unable to find composio.

- The unsafe-path denylist rejected characters that are literal inside
  the double quotes the bin dir is always written in. Keep only what
  bash, zsh, and fish still expand there, plus newline and the PATH
  separator, which are structural. /Users/o'brien/.composio now works.
- A file carrying the marker was treated as configured forever, so the
  legacy three-line block written by install.sh's fallback or by an
  older CLI was never migrated. Skip only on the exact rendered PATH
  line for the resolved bin dir; otherwise splice the current block over
  the stale one in place.
- The reachability skip used the invoking process's $PATH as evidence
  about future shells, so an ad-hoc export or a mise/direnv shim made
  the command persist nothing and exit 0. A redundant PATH line is
  harmless, and the content check already prevents duplicates.

installShellIntegration no longer takes an execPath override; it always
reads NodeProcess, and tests thread their exec path through the test
layer instead.
2026-08-04 19:16:09 +05:30
Alberto Schiabel 331a1373de Merge branch 'next' into feat/cli-install-shell-flag 2026-08-04 18:25:57 +05:30
Alberto Schiabel 15c07ec6c7 docs(cli): restore 0.3.0 and 0.3.1 changelog entries (#4048)
This PR:
- restores missing `0.3.0` and `0.3.1` sections in
`ts/packages/cli/CHANGELOG.md`
- moves the plugin hint and telemetry changes out of `0.2.33`
- records post-`0.3.1` connected-account and login fixes under
`Unreleased`
- rewrites the restored notes as concise, user-facing bullets
- validates the ignored-package boundary with `pnpm validate:changesets`
2026-08-04 17:10:43 +05:30
Alberto Schiabel 1503786358 refactor(core): forbid explicit any and type JSON Schema recursively (#3968)
This PR:

- is refreshed directly onto the current next branch now that #3966 and
#3967 have merged; the PR contains only its intended type-safety work
- enforces no explicit any through the standard .oxlintrc.json, pnpm
lint, and plain oxlint --fix in lint-staged; docs remain covered by
their nested configuration
- replaces the loose JSONSchemaProperty in @composio/core with a
concrete recursive interface, removing explicit any reachable through
Tool.inputParameters and Tool.outputParameters
- includes a minor changeset documenting the type narrowing for
properties, default, and enum consumers
- adds a compile-only public-contract test for recursive schemas,
known-key validation, extension keywords, and Tool reachability
- removes explicit any from FileToolModifier, ts-builders, core and CLI
tests, provider tests, and json-schema-to-zod tests
- keeps TypeScript ESLint-parity rules enabled and closes the
tool-router example lint/typecheck gap
- makes no lockfile changes and no runtime behavior changes

## Context

Final PR from the original #3958 split. The migration foundations are
already on next via #3966 and #3967, so this branch no longer carries a
stacked base commit.
2026-08-03 22:24:57 +05:30
jkomyno 7198dcce8d docs(cli): explain the bash login-override special case 2026-08-03 21:41:18 +05:30
jkomyno 648e95727a fix(cli): exit non-zero when shell setup aborts
Both abort branches (unsafe or relative resolved bin dir) printed an error
and returned, so the effect succeeded and the process exited 0. install.sh
gates its inline PATH fallback on a non-zero exit from 'composio install',
so an aborted setup looked green and left the user with no PATH setup at
all. Raise a typed ShellSetupAbortError after printing the abort reason;
cli-main.ts maps it to exit code 1 without printing anything further, so
install.sh now takes its fallback branch.
2026-08-03 20:29:52 +05:30
jkomyno 48f3ebe2a1 refactor(cli): type the install test helper's shell param with the Shell union
The helper widened shell to string and cast it back to the union, bypassing
the checker. Export Shell from install.cmd.ts and use it directly.
2026-08-03 20:26:09 +05:30
jkomyno 021125b7a8 fix(cli): create the rc tmp copy with the preserved file mode
The tmp copy was written with the default 0644 mode and only chmod'd to the
target's mode afterwards, so a 0600 private rc's contents sat world-readable
in <target>.composio-tmp for the duration of the window. Create the tmp file
with the preserved mode from the start; open(2) masks that mode with the
umask (only ever clearing bits), so the follow-up chmod stays to pin the
exact mode before the rename.
2026-08-03 20:25:37 +05:30
jkomyno 6d0e14f155 fix(cli): only prefer ~/.local/bin when its composio entry is this executable
A bare exists-check let any leftover ~/.local/bin/composio (e.g. a pip or
pipx install) win bin-dir resolution, so the PATH line pointed shells at a
foreign program while the installer reported success. Prefer ~/.local/bin
only when its entry realpath-resolves, following symlinks, to the running
executable; otherwise fall through to the runtime executable's directory.
The COMPOSIO_BIN_DIR override stays highest precedence.
2026-08-03 20:23:14 +05:30
Alberto Schiabel 10e93add6b fix(cli): address bugbot review findings from the guardrails stack (#3886)
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.
2026-08-03 19:20:45 +05:30
Rajarshi Datta ef1ec91486 fix(core): name @composio/core in the upgrade notice instead of the v2 composio-core package (#4031)
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.
2026-08-03 16:43:01 +05:30
Rajarshi Datta 677508f17b docs(core): correct getToolkitVersionsFromEnv precedence in JSDoc (#4033)
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.
2026-08-03 16:39:40 +05:30
Alberto Schiabel 51056129ee fix(core): detect filesystem case sensitivity for uploads (#4036)
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
2026-08-03 16:32:40 +05:30
jkomyno 40f6b8b54e feat(cli): add explicit shell setup to install 2026-07-31 18:54:15 +05:30
Kshitij Jhunjhunwala faaed16fa9 fix(cli): ignore blank plugin host paths 2026-07-30 11:42:22 -07:00
Kshitij Jhunjhunwala 2e361e0f5a Merge remote-tracking branch 'origin/next' into codex/pr3981-merge
# Conflicts:
#	ts/packages/cli/CHANGELOG.md
2026-07-30 11:41:25 -07:00
Kshitij Jhunjhunwala f5aaa0b3d6 feat(cli): stamp telemetry with journey_stage + cli_channel; tag installer origin (#3928)
**Stacked on #3927** (A1 — direct-to-PostHog + install→Apollo identity).
Targets that branch; will auto-retarget to `next` when #3927 merges.
Review only this diff.

## What

Makes every CLI event self-describe its funnel stage, so the adoption
funnel can be queried without string-matching event names — which is how
it silently broke in the first place.

- **`journey_stage`** on every event: `install | setup | login | connect
| execute | other`. Declared as an exported typed const plus a single
exhaustive map, `as const satisfies Record<CliAnalyticsEventName,
CliJourneyStage>` — so **the compiler refuses to build if a future event
has no stage**. No per-event literals; stamped in one shared builder.
- **`cli_channel`** alongside `cli_version`, reusing the existing
`inferSkillReleaseChannel()` / `CLI_RELEASE_CHANNELS`. Makes "did this
fix reach stable users?" answerable — the question that went unanswered
in the 0.2.30 assetless-release incident.
- **Installer origin fix:** `install.sh` ran `"$exe" install` *without*
`COMPOSIO_CLI_INVOCATION_ORIGIN=installer` (the `setup` call on line 410
had it), so a genuine install was indistinguishable from a user running
`composio install` by hand. Now tagged, with a regression test that
reads `install.sh` and asserts it.

## Stage mapping (reviewed against 30d volume)

`install` = `CLI_INSTALL_*` · `setup` = `CLI_SETUP_*` + `CLI_PLUGIN_*` ·
`login` = `CLI_LOGIN_*` · `connect` = `CLI_LINK_*` · `execute` =
`CLI_EXECUTE_*` + `CLI_TOOL_INVOCATION_*` · `other` = `CLI_COMMAND_*`,
`CLI_SEARCH_*`, `CLI_PROXY_*`, `CLI_RUN_*`, `CLI_LOGOUT_*`

Judgment calls, made with data rather than by default:
- **`proxy` → `other`.** 2,060 of 2,140 proxy users (96%) already
execute; only 80 are proxy-only. Reclassifying would move the activated
cohort ~1%, so `execute` stays precisely "tool execution".
- **`run` → `other`.** `run` children emit their own execute events
carrying `parent_run_id`; staging the parent as `execute` would
double-count.
- **`search` → `other`.** Not a required funnel stage. Candidate for a
"discovery" step later if the flow page wants one.

## Note for whoever builds the flow page

`CLI_TOOL_INVOCATION_*` and `CLI_EXECUTE_FAILED` can both fire for a
single failure, so the `execute` stage **double-counts at the event
level**. Count **distinct users per stage**, not events.

## Known coverage limit

npm and Homebrew installs don't run `install.sh`, so they emit no
`CLI_INSTALL_*`. The `install` stage means "installed via install.sh",
not all installs.

## Verification

`pnpm typecheck` clean · `validate:boundaries` OK (46 disables, **zero
added**) · CLI suite **107 files / 971 passed** (+15 tests) ·
`dispatch.ts` identity/transport untouched.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-07-30 11:37:53 -07:00
Kshitij Jhunjhunwala 533bfb44b9 fix(cli): detect setup after root flags 2026-07-30 11:13:38 -07:00
Kshitij Jhunjhunwala 69a73648b3 fix(cli): preserve selected org on manual link 2026-07-30 11:13:38 -07:00
Kshitij Jhunjhunwala f9ddd94e10 Merge next into analytics identity 2026-07-30 11:13:31 -07:00
Kshitij Jhunjhunwala 11e20d9d49 Merge branch 'next' into kj/prde-1153-plugin-hint 2026-07-30 11:01:59 -07:00
Alberto Schiabel 7bf09cdbb8 fix(cli): make GitHub releases the version authority (#3993)
This PR:
- fixes https://github.com/ComposioHQ/composio/issues/3932
- replaces the private CLI package semver with the non-release
`0.0.0-development` sentinel
- injects the exact GitHub release tag version into every standalone
binary and verifies it during the build
- makes every push to `next` a beta, with explicit semver selection for
intentional minor or major betas and stable releases only through beta
promotion
- resolves skill installation, setup repair, companion repair, and
upgrades from packaged `release-tag.txt` metadata
- adds regression coverage for release selection, compiled version
identity, and packaged-tag asset lookup; all 1,009 CLI tests and the
monorepo typecheck pass
- updates the direct CLI changelog and release guidance; no Changeset is
added because CLI packages are excluded from Changesets
2026-07-30 21:20:41 +05:30
Alberto Schiabel 7c5e22c3ce fix(cli): unblock release checksum generation (#3990)
This PR:
- fixes
https://github.com/ComposioHQ/composio/actions/runs/30535159056/job/90850055191
by keeping checksum generation independent of unbuilt CLI runtime
packages
- extracts the shared Effect teardown into a dependency-light module
while preserving existing script imports
- adds an executable release regression that generates a checksum
manifest from a clean fixture
- verifies the fix with `pnpm test:release-workflow`, `pnpm
build:packages`, CLI typecheck, the full CLI test suite, and `pnpm
validate:changesets`
2026-07-30 18:15:21 +05:30
Rahul Tarak d7b6e7eb30 chore(agents): restore good-docs-writing and good-docs-audit skills (#3991)
## What

Restores the two docs-prose skills that were dropped from the skill
tree:

- `good-docs-writing` — the house documentation style guide (Voice,
Structure, Terminology, Punctuation, Code examples, Formatting), for
drafting or revising docs prose.
- `good-docs-audit` — the review process that audits a doc/README/prose
block against that guide and reports `file:line` findings with concrete
rewrites. Report-only by default.

## Why

Both existed at `d17a268d` under `.claude/skills/` and were deleted in
#3666 (`chore(agents): normalize repo guidance skills`), which renamed
the rest of the tree into the current taxonomy but did not carry these
two over. Nothing replaced them: there is no docs-voice guidance in the
repo today, and `docs-decisions` covers docs-site mechanics (Fumadocs,
changelogs, ADRs), not prose style.

## Shape of the restore

Rule content is restored unchanged from `d17a268d`. Only the file layout
differs, because the old flat single-file form no longer passes
`validate:agent-skills` (SKILL.md is now capped at 80 lines and a linked
`references/` directory is required):

```
.agents/skills/good-docs-writing/SKILL.md              # routing + the rules that matter most
.agents/skills/good-docs-writing/references/style-guide.md
.agents/skills/good-docs-audit/SKILL.md                # routing + non-negotiables
.agents/skills/good-docs-audit/references/audit-process.md
```

They live under `.agents/skills` (canonical); `.claude/skills` is a
symlink, so there is no second copy.

Wiring, all three places the taxonomy is asserted:

- `ts/scripts/validate-agent-skills.mjs` — added to the `expectedSkills`
gate
- `ts/scripts/test-skill-routing.mjs` — one routing probe each (the
validator fails on any skill without a probe)
- `AGENTS.md` — added to the Skill Routing list

## Test results

- `node ts/scripts/test-skill-routing.mjs` — passes, 18 probes over 18
skills. Both new probes resolve to a unique top match.
- `node ts/scripts/validate-agent-skills.mjs` — zero findings against
tracked files.
- `pnpm lint-staged` — no staged file matches a configured task
(patterns cover `ts/packages/**` and `python/**`).
- Markdown formatted with the repo Prettier config.

Two notes on how those were run. `pnpm validate:*` could not be used
locally: pnpm's pre-run dependency check tries to purge and reinstall
the workspace and aborts without a TTY, so the scripts were invoked
directly with `node` (same entrypoints the pnpm scripts use).
Separately, `validate-agent-skills` reports stale-guidance hits under
`docs/.eve/dev-runtime/snapshots/**` on my machine; those are untracked,
gitignored local eve snapshots, unrelated to this change, and won't
exist in CI. The commit used `--no-verify` because the pre-commit hook
is just the `pnpm lint-staged` wrapper that hits the same pnpm abort;
lint-staged was run manually instead.

No changeset: guidance and tooling only, no published package touched.

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

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 05:31:33 -07:00
sdkrelease[bot] fdbd44f9eb Release: update version (#3906)
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.14.1

### Patch Changes

- 577a3d4: Replace the backtracking leading/trailing-slash-trim regexes
in the Cloudflare Workers/Edge platform path helpers with index-walk
loops, closing a polynomial-time regular expression denial-of-service
(CodeQL js/polynomial-redos) on long runs of slash characters. Output is
unchanged for every input.
- 503b50a: Refresh runtime dependencies across the TypeScript SDK
packages.
- 2f63fe5: Guard Tool Router session URL uploads against SSRF,
revalidate redirect targets, and enforce a streamed 100 MiB response
limit across TypeScript URL upload paths.
## @composio/experimental@0.2.1

### Patch Changes

- 503b50a: Refresh runtime dependencies across the TypeScript SDK
packages.
## @composio/mastra@0.10.3

### Patch Changes

- 503b50a: Refresh runtime dependencies across the TypeScript SDK
packages.
## @composio/slim@0.14.1

### Patch Changes

- 503b50a: Refresh runtime dependencies across the TypeScript SDK
packages.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-30 16:25:33 +05:30
Kshitij Jhunjhunwala 52071ed5a0 fix(cli): resolve selected-org analytics identity 2026-07-29 19:23:46 -07:00
Kshitij Jhunjhunwala e0d184ede2 Merge PR 3927 fixes into telemetry taxonomy 2026-07-29 19:07:29 -07:00
Kshitij Jhunjhunwala d00a3b5576 fix(cli): keep analytics identity in sync with auth 2026-07-29 19:04:35 -07:00
Kshitij Jhunjhunwala 4bdbaecc10 fix(cli): simplify analytics identity dispatch 2026-07-29 18:07:02 -07:00
Kshitij Jhunjhunwala af772565f7 fix(cli): simplify and harden plugin hints 2026-07-29 18:05:31 -07:00
Kshitij Jhunjhunwala 53a4e7ca46 fix(cli): preserve configured analytics channel 2026-07-29 16:36:37 -07:00
Kshitij Jhunjhunwala 0f37be91e5 fix(cli): key identity stitch throttle by credential 2026-07-29 16:36:33 -07:00
Kshitij Jhunjhunwala 87236ff642 fix(cli): configure telemetry before invocation 2026-07-29 16:07:34 -07:00
Kshitij Jhunjhunwala ce2c3a4024 fix(cli): wait for analytics state locks 2026-07-29 16:07:26 -07:00
Kshitij Jhunjhunwala 5ab7dbbcc3 fix(cli): throttle plugin hints per host 2026-07-29 15:43:24 -07:00
Kshitij Jhunjhunwala 6d90bb3a1c fix(cli): report installed release channel 2026-07-29 15:43:07 -07:00
Kshitij Jhunjhunwala 2be90d765f fix(cli): serialize analytics identity state 2026-07-29 15:42:14 -07:00
Kshitij Jhunjhunwala 4bfae41c7a Merge remote-tracking branch 'origin/claude/cli-adoption-funnel-d95660' into codex/pr3928
# Conflicts:
#	ts/packages/cli/CHANGELOG.md
2026-07-29 15:12:32 -07:00
Kshitij Jhunjhunwala 9bfe6e3610 feat(cli): agent-aware plugin acquisition hint (PRDE-1153)
When the bare CLI runs inside a plugin-capable agent host (Claude Code,
Codex) and the Composio plugin is not installed there, print one
throttled stderr tip pointing at 'composio setup'. Deliberately visible
in non-TTY shells: the primary audience is the agent driving the CLI.

Host detection reads CLAUDECODE / CODEX_THREAD_ID / CODEX_SANDBOX under
their raw names (bypassing the COMPOSIO_-prefixing ConfigProvider).
Plugin presence comes from cheap host state reads: Claude Code's
installed_plugins.json and Codex's config.toml plugin section. Throttle
state lives in its own ~/.composio/plugin-hint.json to avoid colliding
with the update-check state file #3961 is rewriting.

Suppressed when: no host marker, plugin installed (or state unreadable),
shown within 24h, or COMPOSIO_CLI_INVOCATION_ORIGIN=run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 12:19:52 -07:00
Kshitij Jhunjhunwala bf87709d92 Merge remote-tracking branch 'origin/next' into claude/cli-adoption-funnel-d95660
# Conflicts:
#	ts/packages/cli/CHANGELOG.md
#	ts/packages/cli/test/src/commands/login.cmd.test.ts
2026-07-28 13:52:31 -07:00
Kshitij Jhunjhunwala fc9745040a feat(cli): make headless composio login agent-friendly (PRDE-1138) (#3945)
## What

Closes the PRDE-1138 gap: an unattended agent hitting plain `composio
login` in a pipe dead-ended at browser OAuth. Now the default headless
path either completes unattended or tells the agent exactly what to run
— without ever auto-creating an account for a human.

- **Offer**: non-interactive login instructions gain a second hint —
"For unattended agents: run `composio login --agent`" — alongside the
existing URL + `composio login --poll` flow.
- **Perform (reuse only)**: when `~/.composio/agent.json` already holds
a READY agent identity, plain headless `composio login` completes
unattended by reusing it. New `getStoredReadyAgent` in
`services/agents.ts` is the reuse-only counterpart of
`getOrSignupReadyAgent` — it never falls back to signup.
- **Guardrail** (the design constraint from the ticket): account
creation stays exclusively behind the explicit `composio login --agent`
/ `composio signup` commands. A human piping `composio login` with no
stored agent identity gets the same URL instructions as before and no
account. Asserted at both unit and E2E level (`/api/signup` is never
called on the default path).
- `install.sh --agent` login now sets
`COMPOSIO_CLI_INVOCATION_ORIGIN=installer` for analytics attribution.
- Root `.dockerignore`: host `node_modules` (pnpm store symlinks that
break outside the host) no longer enter the e2e image build context;
without this, e2e images cannot build from a checkout that has run `pnpm
install`.

## Verification

- `pnpm typecheck` green; `@composio/cli` suite green — 1001 passed, 1
skipped; `validate:boundaries` clean.
- New Docker E2E suite `ts/e2e-tests/cli/agent-signin` (10/10) against a
mock `agents.composio.dev` (`COMPOSIO_AGENTS_BASE_URL`): unattended
nothing→authenticated (`login --agent` then `whoami` in one container),
headless-human guardrail (instructions printed, zero signup calls),
stored-identity reuse (login completes + whoami reports `account_type:
agent`). No real accounts are created.

## Notes

- No VHS recordings: the visible change is piped-mode text output, which
VHS interactive recordings don't demonstrate.
- No changeset by design (`@composio/cli` is Changesets-ignored);
human-facing note added to `ts/packages/cli/CHANGELOG.md` under 0.3.0.
2026-07-28 13:48:28 -07:00
Kshitij Jhunjhunwala 0c6b09df19 fix(cli): never reuse a stored agent identity the agents API rejected
getStoredReadyAgent collapsed every whoami failure into Option.none via
Effect.option and fell back to the on-disk identity, so a revoked agent
key (HTTP 401/403) still completed headless login. Auth rejections now
return no agent; only transport-shaped failures keep the offline
fallback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-28 13:33:28 -07:00
Kshitij Jhunjhunwala 14011b9057 fix(e2e): scope node_modules dockerignore to the CLI image only
A root .dockerignore excluding **/node_modules broke Dockerfile.node's
runtime fixtures: suites without a setup phase (claude-agent-sdk) resolve
deps through node_modules copied in via COPY ts/e2e-tests/. BuildKit's
per-Dockerfile ignore keeps the exclusion for Dockerfile.cli, which
installs inside the image and must not see host pnpm symlinks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-28 13:21:49 -07:00
Kshitij Jhunjhunwala 0b182a3c0f Merge remote-tracking branch 'origin/claude/cli-adoption-funnel-d95660' into claude/posthog-a2-taxonomy
# Conflicts:
#	install.sh
#	ts/packages/cli/src/analytics/events.ts
2026-07-28 12:08:10 -07:00
Kshitij Jhunjhunwala 9aa3e4b1c6 Merge branch 'next' into claude/cli-adoption-funnel-d95660 2026-07-28 12:01:10 -07:00
jkomyno 6725d1c078 Merge branch 'next' into kj/decommission-npm-brew 2026-07-28 22:05:06 +05:30
Alberto Schiabel 27706a5081 fix(install): stop swallowing the CLI's PATH guidance (#3951)
This PR:

- follows up https://github.com/ComposioHQ/composio/pull/3943, replacing
its hardcoded message with a fix for the cause it worked around
- stops `install.sh` redirecting `composio install`'s stderr to a temp
file — that redirect is what silenced the command, since the CLI gates
every log, note and outro on stderr being a terminal, so the captured
file was always empty and the replay printed nothing
- probes `"$exe" --version` before delegating, so a binary that cannot
run still falls back to inline setup without spilling loader errors —
the reason the redirect existed in the first place
- makes `composio install` fall back to plain `ui.error` lines when
there is nothing to decorate, so container and CI installs that pipe the
session to a build log still get the report; interactive output is
unchanged. `canDecorate` is constant for a run, so each channel binds to
its decorated or plain form once rather than re-testing per message
- drops the unconditional "Composio was added to your PATH" line, which
printed on three paths where nothing was written: shell-not-detected and
unsafe-install-dir (both exit 0 after reporting manual setup), and the
inline fallback's unsupported-shell and unwritable-rc branches
- adds regression tests using the production `makeTerminalUI`
implementation with captured streams, so the real decoration gate is
exercised — the shared test double reports `canDecorate: false` but
prints everything anyway, which is why this went unnoticed through two
prior attempts

## Context

Measured against the released binary, `composio install` writes 0 bytes
when its stderr is not a terminal, and exits 0 without touching any rc
file when `$SHELL` is unset. Both were invisible to the installer:

| case | exit | stderr bytes | PATH block written |
| --- | --- | --- | --- |
| `2>file`, as `install.sh` did | 0 | 0 | yes |
| `$SHELL` unset | 0 | 0 | no |
| stderr on a terminal | 0 | full report | yes |

With the redirect gone, the delegated path prints what the user was
missing — `Updated ~/.zshrc` and `Restart your shell to apply changes` /
`source ~/.zshrc` — and the manual-setup text on the paths where PATH
genuinely was not touched. The closing block no longer needs a PATH
claim of its own, and the fallback keeps printing its own
`refresh_command`.

067c67b695 already tried to surface this
output by capturing it to a temp file and replaying it on success. That
replay has been a no-op for the same reason, so this guidance has never
reached a user since the delegation was introduced.

## How Has This Been Tested?

- new tests fail with `expected '' to contain 'PATH: will add'` (empty
output — the production bug) without the `install.cmd.ts` change, and
pass with it
- full CLI suite: 957 passed, 1 skipped; `pnpm typecheck` 14/14;
`validate:boundaries`, eslint and prettier clean, no new eslint disables
- released binary in a sandboxed `$HOME`: stderr to a file yields 0
bytes; stderr on a pty yields the full report
- CLI from source with stderr captured: 155 bytes of plain guidance
where it previously wrote nothing; decorated output on a terminal
unchanged
- `install.sh` driven through a harness built from the real script under
a pty: a working binary's stderr reaches the terminal, a broken binary's
loader noise stays suppressed and the fallback writes the PATH block and
prints `source ~/.zshrc`. The same harness against `next` shows the
swallow.

No changeset: `@composio/cli` is Changesets-ignored and `install.sh` is
not a published package. The CLI note went into `CHANGELOG.md` directly.

`install.sh` is served from `next`, so the installer half of this
reaches new installs on merge and works with already-released binaries.
The `install.cmd.ts` half only affects captured-stderr installs and
rides the next CLI release.
2026-07-28 21:40:48 +05:30
Alberto Schiabel 2b9571b17f fix(core): resolve typedoc against the TS6 compiler API (#3972)
This PR:
- restores TypeDoc generation after
https://github.com/ComposioHQ/composio/pull/3966 by resolving
`@composio/core`'s TypeScript dev dependency from `catalog:ts6`
- keeps core typechecking on the root TypeScript 7 compiler while
TypeDoc receives the TS6 compiler API
- documents the additional compiler-API consumer in the shared
TypeScript catalog
- commits the regenerated `session-files.mdx` output that could not be
produced while the workflow was broken
- verifies `generate:docs`, `typecheck`, and `build` for
`@composio/core`
2026-07-28 21:03:06 +05:30
Kshitij Jhunjhunwala fc1460995b feat(cli): make headless composio login agent-friendly (PRDE-1138)
Teach non-interactive login to reuse an existing READY agent identity without creating one implicitly. Preserve explicit --no-browser and --no-wait contracts, and branch on TerminalUI.canPrompt so piping stdout alone remains interactive.

Add unattended guidance, installer analytics attribution, and focused unit and Docker E2E coverage. Exclude host node_modules from Docker build contexts.
2026-07-28 20:13:57 +05:30