mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-10-27 04:30:59 +00:00
de96cef382d8daf27301f1f90ae4b5e7f665f73a
886 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
de96cef382 |
feat: add ultracode session config option (#1438)
Adds an **Ultracode** session config option. It turns on Claude Code's
dynamic workflows for every task, at any effort level. Clients that
support boolean config options get a native switch; the rest get an
On/Off select. This follows the Fast mode pattern.
## How the CLI handles ultracode (2.1.310, checked against the bundled
binary and a live session)
- **Which models:** ultracode works on exactly the models that support
`xhigh` effort. The CLI uses the same check for both. So Opus 4.7+,
Sonnet 5+, Haiku 5.5 and Fable qualify; Opus 4.6 and Haiku 4.5 don't.
Effort level no longer matters.
- **Workflows:** dynamic workflows must be enabled. They are off by
default on Pro plans, and org or managed policy can turn them off.
- **State reporting:** `query.getSettings()` returns
`applied.ultracodeAvailable` and `applied.ultracodeRequested`. The CLI's
schema says hosts should "offer an Ultracode control only while this is
true". This method exists at runtime but is missing from the SDK's
`.d.ts`, so the adapter reads it with a cast and falls back to settings
and model data when it is absent.
- **Unsupported requests:** `applyFlagSettings({ultracode})` is never
validated. The request is stored and stays in place across model
switches; it takes effect whenever the model supports it.
- **Effort changes:** an `effortLevel` change sent without an
`ultracode` key turns ultracode off.
## Behavior
- **Visibility:** at session start, one `getSettings()` call decides
availability and the starting value. Model switches combine the
workflows result learned at start with the new model's
`supportedEffortLevels`, so the switch path makes no extra control
request.
- **Value:** the session tracks the user's choice, like
`fastModeEnabled`. The option hides on unsupported models and comes back
with the same value.
- **Effort applies:** `effortFlagSettings` now carries the session's
toggle instead of `settings.ultracode`. This applies at the initial
apply, on model switch, and from the effort picker, so effort changes no
longer turn ultracode off.
- **Clear context:** the clear-context restart restores the toggle, as
it does Fast mode.
## Known limitation
If a user types `/effort ultracode on` as a prompt, the toggle does not
update. The adapter already doesn't pick up effort changes typed as
`/effort` commands.
## Testing
- New `src/tests/ultracode-config.test.ts`. It covers the helpers and
session behavior: seeding from the CLI's report, hiding while workflows
are off, following the model's support, keeping the value across effort
and model switches, and rejected applies.
- New clear-context restore test. `effortFlagSettings` tests updated.
- Live probe against CLI 2.1.310 confirmed the `getSettings` fields, the
`xhigh` proxy (`claude-opus-4-6` reports unavailable while the request
stays in place), and the effort/key behavior.
- `npm run check`, `npm run build`, `npm run test:run` all pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
v0.96.1-preview.8
|
||
|
|
a4957d17c1 |
fix: settle live steers folded into autonomous cycles (#1185)
#1233 fixed queued prompts folded into task-notification cycles. One case remains: a steer sent to the active prompt can be folded into an autonomous cycle, leaving `session/prompt` pending when the result names only the steer UUID. Keep queued prompt matching and also match the active turn's steer UUID. Exclude settled turns and turns held open for background tasks. Preserve plural UUID precedence. The six new settlement cases fail on main and pass with the fix; all 11 new tests pass. Build, lint and format checks pass. The full default suite reports 2,497 passed and 30 skipped with an identical Node binary at a separate path. At `/usr/bin/node`, it reports 2,496 passed, one failed and 30 skipped: an unchanged path-normalization test also fails on main. No test was weakened. No live-provider tests were run. Co-authored-by: Sean McCullough <sean@mcculloughs.io> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>v0.96.1-preview.7 |
||
|
|
bed795d261 |
fix: settle advisor tool results before completing turns (#1247)
When Claude uses the advisor server tool, a completed turn can fail with `ACP error -32603: Internal error: Claude ended the turn without returning results for tool calls: srvtoolu_...`. `server_tool_use` is tracked as a foreground call, but the matching `advisor_tool_result` is discarded, leaving that call unfinished at settlement. Route advisor results through the existing tool-result handler so they clear the outstanding call and publish a terminal update. Plaintext advice is displayed, redacted advice gets a readable completion message without exposing ciphertext, and advisor error results publish a failed tool status with the error code. Release the advisor's hook callback immediately because the server tool has no later client-side `PostToolUse` hook. Addresses the result-lifecycle part of #914. Validation: - Regression coverage through the real prompt consumer for plaintext, redacted, and error results, including the complete assistant message that dispatches the advisor call. All three cases fail without the fix. A dispatched advisor call without a result still fails with `incomplete_tool_call`. - `npm run test:run -- src/tests/incomplete-tools.test.ts`: 59 passed. - `npm run test:run`: 3,055 passed, 30 skipped. - `npm run build` and `npm run check`: passed. - Exact-head Linux CI passed in the fork: https://github.com/mrmans0n/claude-agent-acp/actions/runs/38595756003. The upstream PR workflows are waiting for maintainer approval to run. The required upstream `Build` check remains pending; the fork CI result does not satisfy that merge gate.v0.96.1-preview.6 |
||
|
|
434be13a33 |
fix: distinguish model options with duplicate labels (#1286)
Fixes #1246. When `availableModels` includes aliases and pinned IDs that inherit the same SDK display name, name-only model pickers show indistinguishable rows. Append the selectable model ID to names that remain duplicated after the existing version-label normalization. For example, the four `Opus 5.5` rows become `Opus 5.5 (opus)`, `Opus 5.5 (opus[1m])`, and their explicit-ID equivalents. Keep every option and its ID, description, selection, and recommendation behavior. Existing distinct labels stay unchanged. Regression tests exercise the real allowlist transformation and cover duplicate custom labels too. Validation: - Linux, locked dependencies and the repository's `lts/*` Node configuration: `npm run check`, `npm run build`, and the full test suite passed atv0.96.1-preview.5 |
||
|
|
2a1525e57c |
fix: keep the usage-limit error when it arrives after compaction (#1377)
Fixes #1370 After a compaction in the same turn, the synthetic usage-limit frame is dropped by the stale-frame suppression before its failure details are read. The prompt then ends with a generic internal error instead of the quota error, so clients can't show the limit UI. The suppression branch now records the usage-limit title and error before it skips the frame. Only recognized usage-limit frames are read there, so a stale replayed frame still can't overwrite the failure of the current turn. Added a test for a usage-limit frame after a completed compaction, for both the legacy `errorKind` and the typed session failure, plus a stale frame arriving after it. It fails without the change. `npm run check`, `npm run build` and `npm run test:run` pass. |
||
|
|
54f1e21bc4 |
test: retry the acp-v2 teardown rm on Windows (#1373)
## What breaks
On Windows, `npm run test:run` fails inside `src/tests/acp-v2.test.ts`,
and every failure is raised by the teardown rather than by the behaviour
the test checks. Measured on Windows 11 build 26200, Node 22.22.3,
vitest 5.0.4, two runs:
```
$ node node_modules/vitest/vitest.mjs run src/tests/acp-v2.test.ts
Test Files 1 failed (1)
Tests 45 failed | 91 passed (136)
Duration 11.75s (tests 91%, transform 7%, import 2%)
```
```
Test Files 1 failed (1)
Tests 53 failed | 83 passed (136)
Duration 11.79s (tests 96%, import 2%, transform 2%)
```
Exit code 1 both times. Every failure is the same error, and it comes
from `afterEach`, after the test body has finished:
```
FAIL src/tests/acp-v2.test.ts > ACP v2 prompts > does not report the next turn as waiting for a question that its client never settled
Error: EBUSY: resource busy or locked, rmdir 'C:\Users\...\Temp\acp-v2-TNkkd2\project-J9PwxJ'
FAIL src/tests/acp-v2.test.ts > ACP v2 prompts > the tool calls that a cancel stops > ends a stopped tool call and its subagent's as cancelled, before it reports idle cancelled
Error: EBUSY: resource busy or locked, rmdir 'C:\Users\...\Temp\acp-v2-O3wrrr\project-NgBUMz'
```
The string `EBUSY` occurs 45 and 53 times in those two logs, matching
the two failure counts. The failing set moves between runs; which test
loses the race depends on when Windows releases each directory handle.
CI runs the suite on `ubuntu-latest` only
(`.github/workflows/ci.yml:20`, `:45`), so CI cannot show this. Anyone
who runs the documented `npm run test:run` on Windows gets a red file
and a non-zero exit.
## Why
The per-test teardown at `src/tests/acp-v2.test.ts:156` is:
```ts
await rm(tempDir, { recursive: true, force: true });
```
`force: true` suppresses ENOENT only; it does not retry EBUSY. Each
test's cwd is a child of `tempDir` (`cwd = await
mkdtemp(path.join(tempDir, "project-"))`, line 147), and Windows keeps a
directory busy briefly after the process holding it exits, so `rmdir`
returns EBUSY, `afterEach` rejects, and vitest marks the test failed.
## The fix
```diff
- await rm(tempDir, { recursive: true, force: true });
+ await rm(tempDir, { recursive: true, force: true, maxRetries: 10 });
```
`maxRetries` is Node's own retry loop for `fs.rm`, covering EBUSY,
EMFILE, ENFILE, ENOTEMPTY and EPERM with a backoff between attempts. The
repository already uses it for the same class of problem in
`src/tests/session-hooks.test.ts:150`:
```ts
// The CLI may still write the transcript of the last session after dispose.
if (root) await rm(root, { recursive: true, force: true, maxRetries: 10 });
```
## Measured after
```
$ node node_modules/vitest/vitest.mjs run src/tests/acp-v2.test.ts
Test Files 1 passed (1)
Tests 136 passed (136)
Duration 16.16s (tests 96%, transform 2%, import 2%)
```
A second run after restoring the patched file: `Tests 136 passed (136)`,
`Duration 16.56s`, exit code 0, `EBUSY` count 0. `npm run check` (eslint
plus `prettier --check .`) also passes, and `npm run build` (`tsc`,
whose `include` covers `src/**/*.ts` so the test file is typechecked
too) exits 0.
## Scope
1 file changed, 1 insertion, 1 deletion: `src/tests/acp-v2.test.ts`.
Deliberately not changed:
- No other test file, and no teardown other than this one call.
`session-hooks.test.ts` is untouched.
- No assertion, fixture, mock or production code, so the 136 tests still
check exactly what they checked before.
- No CI change. Adding a Windows job is a separate call about CI time
and runner budget, and this fix can be verified on Windows without one.
## Unproven
- I have one Windows 11 machine. On `ubuntu-latest` the teardown did not
fail here before or after the patch, and I did not run the job on Linux;
the Linux side is "no behaviour change" by inspection, not something I
measured.
- `maxRetries: 10` covers a handle that closes shortly after the process
exits. A handle held for longer than the whole retry window would still
surface EBUSY; I did not observe one.
- I ran only this file, not the full suite, so I cannot say whether
other files fail on Windows for other reasons.
v0.96.1-preview.4
|
||
|
|
01b686713d |
ci(deps): Bump actions/create-github-app-token from 3.2.0 to 3.3.0 (#1383)
Bumps [actions/create-github-app-token](https://github.com/actions/create-github-app-token) from 3.2.0 to 3.3.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/create-github-app-token/releases">actions/create-github-app-token's releases</a>.</em></p> <blockquote> <h2>v3.3.0</h2> <h2><a href="https://github.com/actions/create-github-app-token/compare/v3.2.0...v3.3.0">3.3.0</a> (2026-10-12)</h2> <h3>Features</h3> <ul> <li>update permission inputs (<a href="https://redirect.github.com/actions/create-github-app-token/issues/399">#399</a>) (<a href=" |
||
|
|
6a33dedcbb |
fix: pass --settings before the auth status subcommand (#1392)
`runCliAuthProbe` builds `["auth", "status", "--json"]` and, when the
session has a settings
override, appends `--settings <json>`. `--settings` is a global option
of the Claude Code CLI;
the `auth status` subcommand only accepts `--json` and `--text` (see
`claude auth status --help`).
So every probe with an override fails with `error: unknown option
'--settings'` and an empty
stdout. The catch branch logs `claude auth status failed: …` on every
call and returns
`undefined`. For sessions that pass `_meta.claudeCode.options.settings`,
the session-creation and
per-prompt refreshes therefore never update the auth status. Only the
initialize probe, which has
no override, still works.
This moves `--settings <json>` in front of the subcommand. Without an
override the argv is
unchanged.
**Reproduce** (no credentials needed; an empty config dir answers "not
logged in"):
```sh
d=$(mktemp -d)
env -i HOME="$d" PATH="$PATH" CLAUDE_CONFIG_DIR="$d/.claude" \
claude auth status --json --settings '{}'
# error: unknown option '--settings'
env -i HOME="$d" PATH="$PATH" CLAUDE_CONFIG_DIR="$d/.claude" \
claude --settings '{}' auth status --json
# {"loggedIn": false, "authMethod": "none", ...}
```
The option is applied in the global position, not just parsed:
`claude --settings '{"apiKeyHelper":"/bin/echo rt-fake-key"}' auth
status --json` reports
`"loggedIn": true, "authMethod": "api_key_helper"`.
Tested with 10 native Claude Code binaries (linux-x64), each in an empty
`HOME`:
| Claude Code | `auth status --json --settings '{}'` | `--settings '{}'
auth status --json` |
|---|---|---|
| 2.1.286 | unknown option | JSON |
| 2.1.294 | unknown option | JSON |
| 2.1.295, 2.1.296, 2.1.299 | unknown option | JSON |
| 2.1.300, 2.1.301, 2.1.302 | unknown option | JSON |
| 2.1.303 (the SDK's `claudeCodeVersion`) | unknown option | JSON |
| 2.1.304 | unknown option | JSON |
The existing test in `auth-status.test.ts` pinned the old order; it now
expects `--settings`
first. Its mock and `statusCalls()` matched probes by `args[1] ===
"status"`, which a leading
global option shifts, so both now locate the subcommand instead.
`npm run build`, `format:check`, `lint` and `test:run` pass, apart from
one test that fails
identically on `main` without this change.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
v0.96.1-preview.3
|
||
|
|
e369479f93 |
fix: preserve foreground fork reports until launch completes (#1431)
A foreground fork can stream a copied `tool_result` for the Agent call that launched it. That placeholder completed the call and removed its tracked state, so the real report arriving later was dropped. Ignore only results whose tool ID equals the message's parent tool ID, keeping the launching call open for its actual report. Keep other results in the same message and discard the message-level `tool_use_result` sidecar when its launch result was removed, so it cannot be attributed to a remaining tool result. Regression coverage exercises plain and Air clients, root and nested launch results, and a mixed message containing a genuine nested Agent result. Fixes #1389. Validation: - [Linux CI](https://github.com/agentclientprotocol/claude-agent-acp/actions/runs/40217593917) passes the full suite: 3,304 passed, 32 skipped (57 test files passed, 4 skipped). All PR checks are green. - `npm run check` and `npm run build` pass. - `vitest run src/tests/acp-agent.test.ts --maxWorkers=1`: 712 passed, 10 skipped. The four new regression cases fail on the original code and pass with the fix. - Eight actual-SDK runs against localhost fake gateways complete successfully without model calls: plain and Air foreground forks, native Air child sessions, nested forks with the background option omitted or false, the SDK's fork-inside-fork rejection, a background launch receipt, and history replay. Foreground reports arrive exactly once and no launch-result tracking warning remains. The local full-suite run encountered 19 failures in `session-index.test.ts` and then stopped progressing, so it was interrupted. A standalone recursive-file-watcher probe also emits `EMFILE` on this machine. The successful Linux CI run above provides the complete-suite verification. Review dependencies (updated 26 October): | Related proposal | Relationship to this PR | | --- | --- | | [#1408](https://github.com/agentclientprotocol/claude-agent-acp/pull/1408) — targeted session lookup | Independent. Both orders merge cleanly onto the checked main and produce the same tree. | | [#1422](https://github.com/agentclientprotocol/claude-agent-acp/pull/1422) — resumed subagents | Complementary, with no dependency on this PR. It now conflicts with upstream main in `src/acp-agent.ts`; its author needs to resolve that conflict, integrate the [separately shared AIR routing patch](https://github.com/agentclientprotocol/claude-agent-acp/pull/1422#issuecomment-6401008862) and complete its validation. | <details> <summary>Additional local integration validation — 25 October</summary> A local combination of the recorded main, #1408, #1431, #1422 and the already-reviewed routing patch passed 199 focused foreground/resume/native-subagent checks (647 other cases filtered or skipped), TypeScript build, and two replays of previously captured SDK frames for AIR and standard subagents. The two captured-frame replays were independently repeated. No new model calls were made. The combination is a private test tree, not a published change. It does not replace full CI for #1422 or live Air acceptance. The routing patch needed three-way application against that recorded main because its surrounding source had moved; it applied cleanly that way. The current-main conflict in #1422 means this historical result does not establish today’s combined compatibility. Checked main `739dde3`, #1408 `e3b3aa4`, #1431 `8f96f46`, #1422 `dd3bf2c`. The two orders of #1408 and #1431 produce tree `1716d7e`; the full local test tree is `61c0447`. Refresh this evidence if these inputs change. </details> Co-authored-by: Codex <codex@openai.com>v0.96.1-preview.2 |
||
|
|
c26e640915 |
fix: bump body-parser from 2.3.0 to 2.4.0 (#1436)
Bumps [body-parser](https://github.com/expressjs/body-parser) from 2.3.0 to 2.4.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/expressjs/body-parser/releases">body-parser's releases</a>.</em></p> <blockquote> <h2>v2.4.0</h2> <h2>Important: Security</h2> <ul> <li>Security fix for <a href="https://www.cve.org/CVERecord?id=CVE-2026-111181">CVE-2026-111181</a> (<a href="https://github.com/expressjs/body-parser/security/advisories/GHSA-27r3-jxmh-p828">GHSA-27r3-jxmh-p828</a>)</li> </ul> <h2>What's Changed</h2> <ul> <li>build(deps): bump actions/checkout from 6.0.3 to 7.0.0 by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/expressjs/body-parser/pull/737">expressjs/body-parser#737</a></li> <li>chore: group github actions updates by <a href="https://github.com/Phillip9587"><code>@Phillip9587</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/743">expressjs/body-parser#743</a></li> <li>build(deps): bump the github-actions group with 3 updates by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/expressjs/body-parser/pull/745">expressjs/body-parser#745</a></li> <li>test: fix 'presist' typo in test descriptions by <a href="https://github.com/maxtaran2010"><code>@maxtaran2010</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/749">expressjs/body-parser#749</a></li> <li>docs: include security fix in 2.3.0 changes by <a href="https://github.com/UlisesGascon"><code>@UlisesGascon</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/748">expressjs/body-parser#748</a></li> <li>fix: avoid mutating read options when reading body by <a href="https://github.com/Phillip9587"><code>@Phillip9587</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/742">expressjs/body-parser#742</a></li> <li>refactor: move getCharset helper to only usage by <a href="https://github.com/Phillip9587"><code>@Phillip9587</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/707">expressjs/body-parser#707</a></li> <li>build(deps): bump the github-actions group with 7 updates by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/expressjs/body-parser/pull/753">expressjs/body-parser#753</a></li> <li>refactor: switch to neostandard by <a href="https://github.com/Phillip9587"><code>@Phillip9587</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/751">expressjs/body-parser#751</a></li> <li>perf(json): avoid first-char regex for direct JSON bodies by <a href="https://github.com/Phillip9587"><code>@Phillip9587</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/744">expressjs/body-parser#744</a></li> <li>docs: fix entity verify error description by <a href="https://github.com/Rawal27"><code>@Rawal27</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/755">expressjs/body-parser#755</a></li> <li>feat: zstandard support by <a href="https://github.com/Phillip9587"><code>@Phillip9587</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/586">expressjs/body-parser#586</a></li> <li>test: remove unused experimentalZstd option by <a href="https://github.com/Phillip9587"><code>@Phillip9587</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/757">expressjs/body-parser#757</a></li> <li>ci: run tests on windows and macos matrix by <a href="https://github.com/kilisamemarisaaa"><code>@kilisamemarisaaa</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/759">expressjs/body-parser#759</a></li> <li>deps: qs@^6.16.0 by <a href="https://github.com/krzysdz"><code>@krzysdz</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/762">expressjs/body-parser#762</a></li> <li>build(deps): bump the github-actions group with 3 updates by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/expressjs/body-parser/pull/763">expressjs/body-parser#763</a></li> <li>ci: trigger npm publish on release published and set dist-tag by <a href="https://github.com/UlisesGascon"><code>@UlisesGascon</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/768">expressjs/body-parser#768</a></li> <li>build(deps): bump the github-actions group with 3 updates by <a href="https://github.com/dependabot"><code>@dependabot</code></a>[bot] in <a href="https://redirect.github.com/expressjs/body-parser/pull/771">expressjs/body-parser#771</a></li> <li>fix(test): pin supertest to 7.3.0 to avoid 7.3.1 regression by <a href="https://github.com/saadkhantareen"><code>@saadkhantareen</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/773">expressjs/body-parser#773</a></li> <li>perf: inline content stream setup by <a href="https://github.com/Phillip9587"><code>@Phillip9587</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/750">expressjs/body-parser#750</a></li> <li>docs: note that req.body may be undefined in v2 by <a href="https://github.com/Hashim1999164"><code>@Hashim1999164</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/752">expressjs/body-parser#752</a></li> <li>docs: fix strict option description by <a href="https://github.com/Rawal27"><code>@Rawal27</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/756">expressjs/body-parser#756</a></li> <li>docs: fix depth error description by <a href="https://github.com/johnnyhuirilef"><code>@johnnyhuirilef</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/776">expressjs/body-parser#776</a></li> <li>chore: update dependencies by <a href="https://github.com/Phillip9587"><code>@Phillip9587</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/778">expressjs/body-parser#778</a></li> <li>Release: 2.4.0 by <a href="https://github.com/UlisesGascon"><code>@UlisesGascon</code></a> in <a href="https://redirect.github.com/expressjs/body-parser/pull/777">expressjs/body-parser#777</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/maxtaran2010"><code>@maxtaran2010</code></a> made their first contribution in <a href="https://redirect.github.com/expressjs/body-parser/pull/749">expressjs/body-parser#749</a></li> <li><a href="https://github.com/Rawal27"><code>@Rawal27</code></a> made their first contribution in <a href="https://redirect.github.com/expressjs/body-parser/pull/755">expressjs/body-parser#755</a></li> <li><a href="https://github.com/kilisamemarisaaa"><code>@kilisamemarisaaa</code></a> made their first contribution in <a href="https://redirect.github.com/expressjs/body-parser/pull/759">expressjs/body-parser#759</a></li> <li><a href="https://github.com/saadkhantareen"><code>@saadkhantareen</code></a> made their first contribution in <a href="https://redirect.github.com/expressjs/body-parser/pull/773">expressjs/body-parser#773</a></li> <li><a href="https://github.com/Hashim1999164"><code>@Hashim1999164</code></a> made their first contribution in <a href="https://redirect.github.com/expressjs/body-parser/pull/752">expressjs/body-parser#752</a></li> <li><a href="https://github.com/johnnyhuirilef"><code>@johnnyhuirilef</code></a> made their first contribution in <a href="https://redirect.github.com/expressjs/body-parser/pull/776">expressjs/body-parser#776</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/expressjs/body-parser/compare/v2.3.0...v2.4.0">https://github.com/expressjs/body-parser/compare/v2.3.0...v2.4.0</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/expressjs/body-parser/blob/master/HISTORY.md">body-parser's changelog</a>.</em></p> <blockquote> <h1>2.4.0</h1> <ul> <li>Security fix for <a href="https://github.com/expressjs/body-parser/security/advisories/GHSA-27r3-jxmh-p828">GHSA-27r3-jxmh-p828</a> (CVE-2026-111181)</li> <li>feat: add <code>zstd</code> content-encoding support (<a href="https://redirect.github.com/expressjs/body-parser/issues/586">#586</a>) <ul> <li>Requires Node.js <code>^22.15.0</code> or <code>>=23.8.0</code>; older versions keep returning <code>415</code> for <code>zstd</code> encoded bodies</li> </ul> </li> <li>fix: avoid mutating the parser options and the request object while reading the body (<a href="https://redirect.github.com/expressjs/body-parser/issues/742">#742</a>, <a href="https://redirect.github.com/expressjs/body-parser/issues/750">#750</a>)</li> <li>perf(json): avoid first-char regex for direct JSON bodies (<a href="https://redirect.github.com/expressjs/body-parser/issues/744">#744</a>)</li> <li>deps: <ul> <li>content-type@^2.1.0</li> <li>iconv-lite^0.7.3</li> <li>qs@^6.16.1</li> </ul> </li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="v0.96.1-preview.1 |
||
|
|
f6958db1ee |
chore(main): release 0.96.0 (#1425)
🤖 I have created a release *beep* *boop* --- ## [0.96.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.95.0...v0.96.0) (2026-10-26) ### Features * report SendMessage delegations as linked session messages ([#1424](https://github.com/agentclientprotocol/claude-agent-acp/issues/1424)) ([v0.96.0 |
||
|
|
2f3c6bb7b3 |
fix: update to Claude Code 2.1.310 (#1435)
Updates `@anthropic-ai/claude-agent-sdk` from 0.3.309 to **0.3.310** (Claude Code **2.1.310**), `@agentclientprotocol/sdk` 2.0.1 → 2.0.2 and `@anthropic-ai/sdk` 1.1.0 → 1.3.0. TypeScript stays on 6.0.3, because typescript-eslint 8.72 still requires `typescript <6.1.0`. ## Behaviour changes ACP users may notice - **2.1.310:** the Monitor tool and plugin monitors now run on Bedrock, Vertex and Foundry, and with telemetry or nonessential traffic disabled. On those setups, long foreground sleeps are now blocked. We already hide Monitor tasks from the client (`local_monitor` / `HIDDEN_TASK_TOOLS`), so the only visible change is that a blocked sleep shows up as a failed Bash call. - **2.1.310:** when an MCP tool call times out because its elicitation went unanswered, the error now tells Claude not to repeat the call. ## Upstream fixes this picks up - Requests behind gateways that reject the `effort-2025-11-24` beta or mid-conversation system messages are retried without them. This affects our `providers/set` gateway sessions. - After a "Prompt is too long" error, compaction now trims dense content (base64, SVG) properly, so the next request no longer fails again. Compaction in SDK sessions with very large transcripts also uses less memory. - File read permission prompts now show where a symbolic link leads. - Windows: PreToolUse and PermissionRequest hooks no longer let a tool call through when Git Bash is missing and the hook's command is only quoted strings. ## Checked, no change needed - **Agent SDK 0.3.310:** the `sdk.d.ts` diff is doc text only (`connectorId` in the `sdkMcpServerConfigs` comment, and the provider list for `'highlights'` thinking display). Every `CLAUDE_*` env var the adapter reads is still in the 2.1.310 binary. - **ACP SDK 2.0.2:** only fixes the HTTP transport (CR line endings in SSE, request-scoped POST failures), which we don't use. - **`@anthropic-ai/sdk` 1.2/1.3:** adds API endpoints (message threads, usage/cost reports, Claude Tag); we only use its types. Verified: `npm run build`, `npm run check`, `npm run test:run` (3323 passed, 30 skipped), and a typecheck of `examples/`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)v0.95.1-preview.6 |
||
|
|
9a8bf71d45 |
fix: refine RFD child models after a load, and retry a failed model update (#1434)
## Summary Follow-up to #1433, which was merged before these review fixes landed. - **RFD child models after a load.** On a real `session/load` (session not live in this process), #1433 also gave `RfdSubagentReplay` no model list, so after the load response `currentStates` could not map a child's model to the root session's `model` entry. RFD children kept the raw model ID. The replay now reads the session's models when needed; only the in-replay mapping is off while the load replays. - **Retry after a failed publish.** `reportModel` skipped a model that matched the stored options, which are written before the publish. A failed publish then blocked every later report of the same model. It now compares with the last model the client actually received. - **Failed load replay.** The replayed child models are also dropped when the replay itself fails. - The buffer of an unannounced child collapses only model reports from `reportModel`; other config updates stay as they are. ## Tests - `replayRfd` gained a `load` option that replays like a real load; "sends the model of each child's responses, and after the load response only a changed entry" uses it (fails without the fix). - A retry after a failed publish, for the RFD and AIR forms. - "refines an ended AIR child's model" now goes through the load path. - `npm run build`, `npm run check`, `npm run test:run`: 3323 passed, 30 skipped. ## Related - Follow-up to #1433 and #1432 - RFD change: https://github.com/agentclientprotocol/agent-client-protocol/pull/2482 - RFD section: [Child configuration](https://github.com/agentclientprotocol/agent-client-protocol/blob/main/docs/rfds/subagents.mdx#child-configuration) - JetBrains issue: [IJAI-4754](https://youtrack.jetbrains.com/issue/IJAI-4754)v0.95.1-preview.5 |
||
|
|
eb9d63e5fd |
fix: do not hold an AIR load replay until the CLI starts (#1433)
## Summary #1432 made an AIR `session/load` replay wait for the CLI start before it sent the children's models. So the end of every such replay (`loadReplayEnd` and the children's `subagent_state_update`) came only after the CLI started, also for a history without subagents. - The replay no longer waits. It sends each child's model as the replay reaches it. During a load the session's model list is not known yet, so the model goes as its id. - After the load response, each replayed child whose model the list maps to another entry gets that entry. This also applies to a child that the replay already ended. It is a more exact snapshot of the same configuration. - `modelEntryFor` and `modelDisplayName` keep their results per model list. `reportModel` skips a model that the child already has. - The buffer of a child that is not announced yet keeps only its latest configuration update, so model reports do not crowd out the child's output. - AIR: the runtime forgets the configuration of an ended child. ## Validation - `npm run build`, `npm run check` - `npm run test:run`, two runs: 3321 passed, 30 skipped. - `src/tests/acp-scenarios.test.ts`, 30 runs in 6 parallel workers: no failure. - New tests: the load end event before the CLI start, with and without subagents (both fail on `main`); the post-load refinement of an ended child; the buffer; the cleanup; the memo after a list change. - Microbenchmark of 10,000 child responses over 200 children, with 51 models: | | before | after | |---|---|---| | `modelEntryFor`, last entry | 12.16 µs | 0.23 µs | | `modelEntryFor`, no match | 64.60 µs | 0.08 µs | | `reportModel`, AIR | 13.66 µs | 4.03 µs | | `reportModel`, RFD | 12.80 µs | 3.23 µs | ## Related - Follow-up to https://github.com/agentclientprotocol/claude-agent-acp/pull/1432 - RFD change: https://github.com/agentclientprotocol/agent-client-protocol/pull/2482 - JetBrains issue: [IJAI-4754](https://youtrack.jetbrains.com/issue/IJAI-4754)v0.95.1-preview.4 |
||
|
|
c319e5e542 |
feat: report the model of each native subagent (#1432)
## Summary A native subagent child session gets its model only from what the child reports. The update is a `config_option_update` with the child's session id and a single `model` select option. This follows the subagents RFD, [Child configuration](https://github.com/agentclientprotocol/agent-client-protocol/blob/main/docs/rfds/subagents.mdx#child-configuration) (see also agentclientprotocol/agent-client-protocol#2482). ## Relation to #1417 #1417 reports a child's model from its responses, in the `rfd` form only, with the raw model id as the name. This PR keeps that source and extends it: - The `air` form gets the same update. - History replay sends each child's model from its transcript. - The value maps to an entry of the root session's `model` option, so a client can compare the child's model with the session's. There is no model at spawn. The adapter cannot tell the model that Claude Code picks for a new child, for example with `CLAUDE_CODE_SUBAGENT_MODEL_FORCE`, or when an alias runs on the parent's exact model. So the first update comes with the child's first real response (`message.model`, not `<synthetic>`). A new update goes only when the entry changes. The configuration hooks of #1417 (`PostModelSwitch` and the others) now also run for `air` clients. A hook names the SDK agent id, so in the `air` form its options go to the agent's current generation session (`<agent id>:generation:<n>`). In the `air` form, no configuration goes after a child's end. ## Notification ```json { "sessionId": "<child session id>", "update": { "sessionUpdate": "config_option_update", "configOptions": [{ "id": "model", "name": "Model", "category": "model", "type": "select", "currentValue": "opus[1m]", "options": [{ "value": "opus[1m]", "name": "Opus 4.6 (1M context)" }] }] } } ``` - The client cannot change a child's configuration, so the select offers only the current value. - No field is added to `subagent_spawned` or `subagent_update`. ## Matching a model id to an entry Best first: 1. the root session's current entry, when it runs the same model up to a context hint, such as `opus[1m]` or `default` for `claude-opus-4-6`; 2. the listed entry whose value or resolved model is the id; 3. a listed entry that runs the same model up to a context hint. When several entries run the model, a concrete entry comes before `default`, unless `default` is the current entry. A model id is compared as it is, so a dated or provider id (`claude-haiku-4-5-20251001`, `eu.anthropic.claude-sonnet-5`) matches only the same id: `ModelInfo.resolvedModel` is the wire id that a response reports. A model that matches no entry goes as its full id, with its display name when the session's model list has one. A `PostModelSwitch` hook of a child uses the same matching. ## Replay - A child without responses in its transcript gets no model. - `rfd` form: the replay sends a child's model right after its announcement, from its first response, and again when a later response changes it. During a load, the session's model list can be unknown, so the replay can send the full id. After the load response, a child's model goes again only when the list maps it to another entry. - `air` form: the replay ends every child, and nothing may follow the end. So each child's latest response model goes once the session creation ended, just before the child's end, as the entry of the session's model list. ## Validation - `npm run build` - `npm run check` - `npm run test:run`, three runs: 3315 passed, 30 skipped. - `src/tests/acp-scenarios.test.ts`, 30 runs in 6 parallel workers: no failure. New tests cover: - no model before the child's first response, in both forms; - an update only when the entry changes; - no update to an ended `air` child, also with an update in flight at the end; - a hook's options under the current `air` generation; - matching for `opus[1m]` and `default`, concrete entries before `default`, listed entries, dated and provider ids, and unlisted ids; - the `PostModelSwitch` entry, in both forms; - an `air` load replay that maps a child's model only once the session exists; - `rfd` replay with an unlisted full id, and no duplicate update after the load response. The scenario snapshots for both forms and v2 are updated.v0.95.1-preview.3 |
||
|
|
739dde3ae5 |
feat: report SendMessage delegations as linked session messages (#1424)
In the subagents RFD form, a `SendMessage` call to a child now becomes a message between the two sessions, as a launch's prompt already does (#1405). Before, it was a tool call of its sender plus an unlinked message in the child. Every delegation now has a parent-side message, which a client can anchor a per-delegation card on, and both views name each other with `senderMessageId`/`recipientMessageId`. ## Live - The call is held until its final update. The SDK reports that the message resumed a child before it reports the call's result. - **Message reached an announced child:** the sender gets the outgoing view and the child the incoming one (`linkedSessionMessages`). The call's result isn't shown. - **Message reached no announced child**, for example one sent to the parent: the call is shown after all, with its final status (`unexposedControlFallback`). - **Call a permission request already showed:** it keeps its updates, and its message goes only to the child. ## Replay - A child's history replays right after its launch, so a call from a parent to its child is always matched to its delivery first. - The child's view then names the call, and the sender's view goes out where the call sits. - A call the replay reaches before its delivery stays a tool call, unlinked. That can happen with a child's message to a sibling whose history replays later. `publishPrompt`'s `replacesLaunch` option is now `replacesCall`. ## Testing - **Live:** the existing `SendMessage` tests in `native-subagents.test.ts` and `acp-agent.test.ts` now expect both views and check that the call and its completed result are hidden. A new test checks that a call reaching no announced child is shown with its final status. - **Replay:** the existing test expects the linked views in place of `root tool_call toolu_send`. A new test covers a call reached before its delivery, and fails if delivery ignores that the call was already shown. - `npm run check`, `npm run build` and `npm run test:run` (3301 tests) pass locally. Not tried against a real Claude Code run yet.v0.95.1-preview.2 |
||
|
|
17a967b4da |
fix: send subagents' current state after a load response (#1423)
The subagents RFD makes the response to a load (v1 `session/load`, v2 `session/resume` with replay) the freshness boundary. Work states and `cancel` grants sent before it are history, and "current snapshots are sent after the response". The adapter sent each replayed child's end only during the replay, so a client that follows the RFD strictly showed every child as unknown after a reload. This replaces the RFD carve-out proposed in agentclientprotocol/agent-client-protocol#2475. After the response, each replayed child now gets one current `subagent_update`: - **A child still running in this process**, as when a live session is loaded again, reports its live state and `capabilities.cancel`, as it did live. - **Any other child** can't be running, because the process that ran it is gone. Its replayed end becomes its current state, with no grant. When it's sent: - **v1:** with the commands, in the timer that follows the setup response (`afterSetupResponse`). - **v2:** the surface sends it only once its own resume response is out, after `setupCommands`. A timer set inside `loadSession` could fire before that response. `RfdSubagentReplay.finish` and the new `currentStates` share one `endState`. `NativeSubagentRuntime.liveWorkState` exposes the live state. ## Testing - `sends each child's current state after the load response`: a live child and a finished one, after the replay and its response. - `replays a subagent's history to its own session…` (v2) now records when the client receives the response. It checks that the child's current `state_update` arrives after it, and that the parent's copy grants nothing. It fails without the v2 change. - `npm run check`, `npm run build` and `npm run test:run` (3300 tests) pass locally. Not tested end to end: the v1 timer path. It reuses the timer that already sends v1 commands after the setup response.v0.95.1-preview.1 |
||
|
|
ebfbfbdaa9 |
chore(main): release 0.95.0 (#1391)
🤖 I have created a release *beep* *boop* --- ## [0.95.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.94.0...v0.95.0) (2026-10-23) ### Features * end a turn at its result for AIR clients with backgroundSubagents ([#1262](https://github.com/agentclientprotocol/claude-agent-acp/issues/1262)) ([v0.95.0 |
||
|
|
6ab670baae |
feat: report read-only subagent configuration (#1417)
## Summary Expose the observed configuration of RFD subagent sessions using the same config-option IDs as ordinary sessions, without granting client-initiated configuration changes. - Report model from child responses and model-switch hooks, and mode, applied reasoning effort, and agent type from child-attributed SDK hooks. - Merge partial observations into complete, ordered config snapshots; buffer early observations until truthful child announcement and serialize concurrent publications. - Advertise only each observed current value. Do not inherit parent settings or invent child Fast-mode state. - Keep child plan-mode and model-switch hooks from changing the parent's configuration. - Cover initial/changed settings, announcement ordering, publication failures, root isolation, and hook registration in both protocol versions; update v2 scenario snapshots. ## Related Protocol clarification: https://github.com/agentclientprotocol/agent-client-protocol/pull/2468 Zed client implementation: https://github.com/zed-industries/zed/pull/66058 ## Validation Passed after rebasing onto current `main`: - `npm run build` - `npm run check` - `npm run test:run -- --silent`: 3,294 passed, 30 skipped. No live Claude-to-Zed smoke test was run. Settings are reported only when observed from the SDK; availability depends on runtime support and events received.v0.94.1-preview.13 |
||
|
|
f7d6030c04 |
fix: bump the minor group across 1 directory with 2 updates (#1416)
Bumps the minor group with 2 updates in the / directory: [@opentelemetry/api](https://github.com/open-telemetry/opentelemetry-js) and [jose](https://github.com/panva/jose). Updates `@opentelemetry/api` from 1.9.1 to 1.10.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/open-telemetry/opentelemetry-js/releases">@opentelemetry/api's releases</a>.</em></p> <blockquote> <h2>api/v1.10.0</h2> <h2>1.10.0</h2> <h3>🚀 Features</h3> <ul> <li>feat(api): integrate the Logs API into <code>@opentelemetry/api</code> <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/4862">#4862</a> <a href="https://github.com/hectorhdzg"><code>@hectorhdzg</code></a></li> <li>feat(api): add imperative <code>context.attach()</code> for setting context across callback boundaries that <code>with()</code> cannot wrap. <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6845">#6845</a> <a href="https://github.com/pichlermarc"><code>@pichlermarc</code></a> <ul> <li><code>attach()</code> returns a <code>Token</code> whose <code>dispose()</code> method restores the previous context. Use <code>token.dispose()</code> to detach.</li> <li><code>attach</code> is an optional method on the <code>ContextManager</code> interface; when the active context manager does not implement it, <code>context.attach()</code> logs a warning and returns a no-op token.</li> </ul> </li> <li>feat(api): add <code>AnyValue</code> type (of type <code>unknown</code>) and extend <code>Attributes</code> type values to use <code>AnyValue</code> <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6780">#6780</a> <a href="https://github.com/trentm"><code>@trentm</code></a> <ul> <li>This is part of supporting <a href="https://github.com/open-telemetry/opentelemetry-specification/blob/main/oteps/4485-extending-attributes-to-support-complex-values.md#how">OTEP 4485</a>.</li> <li>This is a <strong>breaking change for SDK implementations</strong>, in that they may need to support more attribute types for any APIs that accept <code>Attributes</code> or <code>AnyValue</code>. Implementors should refer to the OTEP 4485 link above for "MUST / SHOULD" requirements for complex attributes handling. See also the <a href="https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-core/src/common/attributes.ts">attributes-handling utilities provided by <code>@opentelemetry/core</code> to help</a>. For example, <code>cleanSimpleAttributes()</code> can be used to limit user-provided attributes to the set of value types supported in earlier <code>@opentelemetry/api</code> versions.</li> <li>This change is <strong>typically not a breaking change for users</strong> of <code>@opentelemetry/api</code>. There is one possible breaking case: If a TypeScript user was using the <code>Attributes</code> type in their own code and using <a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html">TypeScript Narrowing</a> to reduce an attribute value to an expected type (<a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6579#issuecomment-4345316200">example here</a>). It is expected that this usage should be rare and, likely, limited to SDK implementations, if at all. (If this impacted your code, <a href="https://github.com/open-telemetry/opentelemetry-js/issues/new">please let us know</a>.)</li> <li><strong>Note for users of attributes:</strong> Simple attributes SHOULD be used whenever possible. Instrumentations SHOULD assume that backends do not index individual properties of complex attributes, that querying or aggregating on such properties is inefficient and complicated, and that reporting complex attributes carries higher performance overhead.</li> </ul> </li> </ul> <h3>🐛 Bug Fixes</h3> <ul> <li>fix(api): cap tracestate list-members and total length in the deprecated <code>TraceState.set()</code> so it stays in step with <code>TraceState</code> from <code>@opentelemetry/core</code> <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6964">#6964</a> <a href="https://github.com/Zuhef"><code>@Zuhef</code></a></li> <li>fix: resolve the ESM build through the <code>default</code> export condition instead of <code>import</code>, so a resolver that activates neither <code>import</code> nor <code>require</code> still finds an entry point <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/7132">#7132</a> <a href="https://github.com/overbalance"><code>@overbalance</code></a></li> </ul> <h3>📚 Documentation</h3> <ul> <li>docs(api): complete <code>@since</code> annotations for the public API <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/7023">#7023</a> <a href="https://github.com/nabeelamjadsheikh"><code>@nabeelamjadsheikh</code></a> <ul> <li>Adds the three missing exported-type annotations and the member-level annotations for methods and properties introduced after their enclosing type.</li> <li>Corrects <code>Attributes</code>, <code>AttributeValue</code> and <code>TracerOptions</code> from <code>1.3.0</code> to <code>1.1.0</code>; all three were already importable in 1.1.0 via wildcard re-export.</li> </ul> </li> </ul> <h3>🏠 Internal</h3> <ul> <li>build: migrate the package build from <code>tsc</code> to <code>tsdown</code>, emitting dual CJS/ESM output from a single <code>dist/</code> directory <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6293">#6293</a> <a href="https://github.com/overbalance"><code>@overbalance</code></a> <ul> <li>The public entry points are unchanged: <code>@opentelemetry/api</code> and <code>@opentelemetry/api/experimental</code>. This package already declared an <code>exports</code> map, so deep imports such as <code>@opentelemetry/api/build/src/...</code> were rejected before this change and continue to be.</li> <li>The emitted files moved out of <code>build/src</code> (CJS), <code>build/esm</code> and <code>build/esnext</code> (ESM) into <code>dist/</code>, using <code>.cjs</code>/<code>.mjs</code> extensions with matching <code>.d.cts</code>/<code>.d.mts</code> declarations. The non-standard <code>esnext</code> condition has been dropped in favour of the standard <code>import</code>/<code>require</code> conditions.</li> </ul> </li> <li>perf(api): add getGlobal fast-path <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/6956">#6956</a> <a href="https://github.com/legendecas"><code>@legendecas</code></a></li> <li>chore: remove the redundant <code>module</code> field from <code>package.json</code>; bundlers resolve the ESM build through the <code>exports</code> map <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/7130">#7130</a> <a href="https://github.com/overbalance"><code>@overbalance</code></a></li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/open-telemetry/opentelemetry-js/blob/main/CHANGELOG.md">@opentelemetry/api's changelog</a>.</em></p> <blockquote> <h2>1.10.0</h2> <h3>🚀 (Enhancement)</h3> <ul> <li>feat(resource): create sync resource with some attributes that resolve asynchronously <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3460">#3460</a> <a href="https://github.com/samimusallam"><code>@samimusallam</code></a></li> <li>feat: collect host id for non-cloud environments <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3575">#3575</a> <a href="https://github.com/mwear"><code>@mwear</code></a></li> <li>feat (api-logs): separate Events API into its own package <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3550">3550</a> <a href="https://github.com/martinkuba"><code>@martinkuba</code></a></li> <li>feat(sdk-metrics): apply binary search in histogram recording <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3539">#3539</a> <a href="https://github.com/legendecas"><code>@legendecas</code></a></li> <li>perf(propagator-jaeger): improve deserializeSpanContext performance <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3541">#3541</a> <a href="https://github.com/doochik"><code>@doochik</code></a></li> <li>feat: support TraceState in SamplingResult <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3530">#3530</a> <a href="https://github.com/raphael-theriault-swi"><code>@raphael-theriault-swi</code></a></li> <li>feat(sdk-trace-base): add diagnostic logging when spans are dropped <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3610">#3610</a> <a href="https://github.com/neoeinstein"><code>@neoeinstein</code></a></li> <li>feat: add unit to view instrument selection criteria <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3647">#3647</a> <a href="https://github.com/jlabatut"><code>@jlabatut</code></a></li> <li>feat(tracing): expose dropped counts for attributes, events and links on span <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3576">#3576</a> <a href="https://github.com/mohitk05"><code>@mohitk05</code></a></li> </ul> <h3>🐛 (Bug Fix)</h3> <ul> <li>fix(core): added falsy check to make otel core work with browser where webpack config had process as false or null <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/issues/3613">#3613</a> <a href="https://github.com/ravindra-dyte"><code>@ravindra-dyte</code></a></li> <li>fix(instrumentation-http): include query params in http.target <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3646">#3646</a> <a href="https://github.com/kobi-co"><code>@kobi-co</code></a></li> </ul> <h3>📚 (Refine Doc)</h3> <ul> <li>chore: update http example <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3651">#3651</a> <a href="https://github.com/JamieDanielson"><code>@JamieDanielson</code></a></li> </ul> <h3>🏠 (Internal)</h3> <ul> <li>chore(exporter-jaeger): deprecate jaeger exporter <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3585">#3585</a> <a href="https://github.com/pichlermarc"><code>@pichlermarc</code></a></li> <li>fix(sdk-metrics): fix flaky LastValueAggregator test by using fake timer <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3587">#3587</a> <a href="https://github.com/pichlermarc"><code>@pichlermarc</code></a></li> <li>fix(test): fix failing tests by preventing source-map generation <a href="https://redirect.github.com/open-telemetry/opentelemetry-js/pull/3642">#3642</a> <a href="https://github.com/pichlermarc"><code>@pichlermarc</code></a></li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="v0.94.1-preview.12 |
||
|
|
28a09b1008 |
chore: remove the unused ts-node devDependency (#1414)
Removes `ts-node` 10.9.2 from devDependencies. Nothing in the repo uses it: no script, config or test references it. `npm run build` uses `tsc`, tests run through vitest, and `npm run example:simple-client` uses `node --experimental-strip-types`. Verified: `npm run build`, `npm run check`, `npm run test:run`. |
||
|
|
a1521b6196 |
feat: update to Claude Code 2.1.309 (#1413)
Updates `@anthropic-ai/claude-agent-sdk` from 0.3.303 to **0.3.309** (Claude Code **2.1.309**), `@agentclientprotocol/sdk` 2.0.0 → 2.0.1, `@anthropic-ai/sdk` 0.135.0 → 1.1.0 and typescript-eslint 8.71.2 → 8.72.0. TypeScript stays on 6.0.3. typescript-eslint requires `typescript <6.1.0` and has no TS 7 support yet (typescript-eslint/typescript-eslint#10940), so we wait for that rather than running two TypeScript versions side by side. ## Uses new SDK features - **`/usage` recommendations (0.3.305):** our structured `/usage` Markdown now lists Claude Code's per-window suggestions (`- **41%** Disable my_server · /mcp`) above the MCP server table, in the order Claude Code sends them. `fix` is not rendered: its messages must be queued at priority `later` with `client_composed` set, which an ACP prompt cannot express. A malformed recommendation makes the response fail validation, so we fall back to Claude Code's own `/usage` text. - **`wakeup_source` on `command_lifecycle` "started" (0.3.307):** when a ScheduleWakeup or another scheduled task starts a turn with no prompt open, the async-task (AIR) "Claude is working" task now says `A scheduled wakeup fired (set for <UTC time>).` or `A scheduled task fired.` instead of `Claude Code started a turn without a prompt.` It works whether the frame arrives before or after `session_state_changed: running`; older CLIs and unknown values behave as before. ## Fixes for changes in the new CLI - **Fork transcripts (2.1.307):** the placeholder `tool_result` text in a fork's copied prefix changed (`Fork started — that fork is you.` / `This is the parent's call, not yours. …`). `stripForkPrefix` matches only the directive text, so behaviour is unchanged; its doc comment and the replay fixture now describe both formats. ## Behaviour changes ACP users may notice - **2.1.304:** tool search is on by default behind a custom `ANTHROPIC_BASE_URL` (our `providers/set` gateway sessions), and a gateway that rejects it is retried without it (2.1.305). - **2.1.304:** `rm -r` of a mounted drive or a top-level folder on it (`/Volumes/…`, `/media/…`, `/mnt/c/…`) now asks for permission, even in bypass mode, without an always-allow option. `CLAUDE_CODE_DISABLE_MOUNTED_DRIVE_RM_PROMPT` turns it off. - **2.1.309:** with `sandbox.enabled` but no runnable sandbox, commands in `sandbox.excludedCommands` now ask before writing to the sandbox's write-list paths, and the unsandboxed fallback is refused. - **2.1.304:** `allowedMcpServers` no longer filters `managed-mcp.json` stdio servers that use `${VAR}` only in `env`. ## Upstream fixes this picks up - Model switches, prompts and interrupts no longer wait behind our background `getContextUsage` call (2.1.304); `setModel()` waits up to 15 s for the API to confirm a model (2.1.307). - A PreToolUse hook's deny reason is no longer replaced by a timeout of our `Edit|Write` preview callback hook (2.1.304). - Host-supplied `managedSettings` no longer drop `disableAllHooks`, `disableSkillShellExecution` and empty HTTP hook lists (0.3.309). - Gateway fixes: `context_management` rejections are retried without the field (2.1.304); no `prompt-caching-scope` header behind custom gateways (2.1.307). - A disabled MCP server is no longer reconnected by a later permission prompt in SDK sessions; HTTP MCP tool calls are no longer sent twice when the connection drops (2.1.307/2.1.309). - Bash permission and sandbox hardening (2.1.309), fewer "prompt is too long" and autocompact-thrashing errors, and faster resume of large compacted sessions. ## Checked, no change needed - **ACP SDK 2.0.1** only changes the client-side `createHttpStream` transport, which we don't use. - **`@anthropic-ai/sdk` 1.x** (API version 2026-10-21, Bearer auth, sampling params removed): we only use its types, none of which changed in a way that affects us. Neither our `dist/` nor the Agent SDK runtime imports it, and the bundled CLI carries its own client. It is Apache-2.0 from 1.0.0 (previously MIT). - **`sed -i` (2.1.309)** runs as plain Bash; SDK sessions already did, since `_simulatedSedEdit` only exists in the TUI preview. - The remaining type changes (`liveReply`, context-usage row `id`s, `pluginId`/`path` on agents and skills, new settings keys) are additive and unused. Verified: `npm run build`, `npm run check`, `npm run test:run` (3277 passed, 30 skipped), and a typecheck of `examples/`.v0.94.1-preview.11 |
||
|
|
0fe22ae5a1 |
fix: bump fast-uri from 3.1.8 to 3.1.9 (#1410)
Bumps [fast-uri](https://github.com/fastify/fast-uri) from 3.1.8 to 3.1.9. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/fastify/fast-uri/releases">fast-uri's releases</a>.</em></p> <blockquote> <h2>v3.1.9</h2> <h2>Security</h2> <p>This security release fixes four URI parsing and normalization vulnerabilities in fast-uri 3.x. Applications that process untrusted URI input should upgrade to v3.1.9.</p> <ul> <li><strong>Medium — URI scheme spoofing through percent-encoded schemes</strong> (<a href="https://github.com/fastify/fast-uri/security/advisories/GHSA-w74x-v6f9-j3xg">GHSA-w74x-v6f9-j3xg</a>, CVE-2026-110306): percent-encoded scheme input is now rejected instead of being decoded into a live scheme.</li> <li><strong>Medium — Host confusion during domain-host canonicalization</strong> (<a href="https://github.com/fastify/fast-uri/security/advisories/GHSA-wjr9-j795-jxcr">GHSA-wjr9-j795-jxcr</a>, CVE-2026-110180): malformed domain hosts containing ambiguous delimiters or stripped control characters are now rejected instead of being silently rewritten.</li> <li><strong>Low — Incorrect relative-reference normalization</strong> (<a href="https://github.com/fastify/fast-uri/security/advisories/GHSA-xhq7-xmqj-769h">GHSA-xhq7-xmqj-769h</a>, CVE-2026-110095): dot-segment removal now preserves the resolution semantics of relative references.</li> <li><strong>Low — Scheme injection in suffix references</strong> (<a href="https://github.com/fastify/fast-uri/security/advisories/GHSA-333x-w4r6-6crp">GHSA-333x-w4r6-6crp</a>, CVE-2026-110725): first-segment colons in path-only suffix references are now escaped so the output is not reparsed as a scheme.</li> </ul> <p>Upgrade with:</p> <pre lang="sh"><code>npm install fast-uri@3.1.9 </code></pre> <p>Thanks to <a href="https://github.com/zekth"><code>@zekth</code></a> for reporting the scheme, host, and relative-reference issues, and to <a href="https://github.com/UlisesGascon"><code>@UlisesGascon</code></a> for finding the suffix-reference issue and reviewing the remediations.</p> <h2>What's Changed</h2> <ul> <li>ci: enable trusted publishing releases (v3.x) by <a href="https://github.com/mcollina"><code>@mcollina</code></a> in <a href="https://redirect.github.com/fastify/fast-uri/pull/229">fastify/fast-uri#229</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/fastify/fast-uri/compare/v3.1.8...v3.1.9">https://github.com/fastify/fast-uri/compare/v3.1.8...v3.1.9</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="v0.94.1-preview.10 |
||
|
|
59e292e29f |
feat: report RFD delegations as linked session messages (#1405)
## Summary For a client on the subagents RFD (every ACP v2 client, and v1 clients that declare `subagents`), session messages now replace the Agent/Task call that launches a child. The parent no longer sees that tool call. AIR's form is unchanged. - **Prompt.** The launch's prompt is a `session_message` in both transcripts: the parent's outgoing view and the child's incoming one. Both use the launch's tool use id, and each names the other with `recipientMessageId` / `senderMessageId` from agentclientprotocol/agent-client-protocol#2465. - **Answer.** A foreground child's answer, from the launch's result, is the child's `session_message` to the parent (`<launch id>:reply`). It uses the result as `AgentReporter` renders it, so the model-facing `agentId: …` line and `<usage>` block are gone. A failure or cancellation comes from the child's `idle` stop reason, which it already reported. A background launch's result gets no reply. - **Hand-back mode.** Claude Code (seen with 2.1.303) can have the child hand its report back with a `SubagentHandback` call; the Agent result then only says that the report "was delivered to you as a message". That call is reported as the child's message to the parent, in both transcripts and linked the same way, and the launch's reply is skipped for that run. A failed hand-back delivered nothing, so it stays a tool call of the child. - **Unexposed work.** A launch whose child is never exposed is shown as a tool call after all, with its final status (`unexposedControlFallback`, the former `failedControlFallback`). - **Hidden launches by id.** The adapter's own report that closes an unfinished call (for example at a forced cancel) carries no `toolName`, so the runtime tracks hidden launches by id to keep that report from reaching the client for a call it never saw. - **Replay** sends the same messages from the child's transcript: the launch's prompt, the reply, and hand-backs. A launch without Claude Code's metadata file keeps its tool call and the missing-history notice. Replay can't tell a child's runs apart, so any hand-back in its transcript suppresses its launch's reply. - **SendMessage** calls stay tool calls of their sender, and the child gets the incoming view without references, as before. - README's subagent section describes the new behavior. Do not merge before agentclientprotocol/agent-client-protocol#2465 settles the field names: a merge to `main` publishes a preview right away. Clients on the published schema ignore the two fields (no `deny_unknown_fields` in the Rust schema; the scenario validation with the SDK's zod schema passes). ## Testing - `npm run build`, `npm run check` and `npm run test:run` pass (57 files, 4 skipped as before). - The six v2 `subagent-*.jsonl` scenario snapshots changed: the launch's tool-call updates are gone, the parent gets the outgoing view, the child's view carries `senderMessageId`, and foreground results became `:reply` messages. AIR snapshots are unchanged. - New unit tests cover hidden launches, nested launches, replies, failed and background launches, unexposed launches with both final statuses, the close report without a tool name, and hand-back success and failure, live and on replay. - A real run: the built adapter driven over v2 stdio with Claude Code, one foreground subagent asked to answer PONG, then `session/resume` with replay in a fresh process. Live and replay both showed the linked prompt (parent → child), the linked hand-back "PONG" (child → parent), and no Agent tool call.v0.94.1-preview.9 |
||
|
|
50cd76e78d |
fix: publish the session title as soon as the CLI has it (#1406)
## Summary Session titles showed up only after the first turn ended. With background subagents, that could be minutes or hours later. Now the adapter asks for the title when the prompt is sent to the CLI. In a live run the title arrived **0.8s** after the prompt, compared with **17.9s** (at turn end) on `main`. ## Why - **The CLI already titles SDK sessions.** The bundled CLI (2.1.303) titles a new session from its first prompt within seconds and stores it as an `ai-title` transcript entry. `getSessionInfo` returns it as `customTitle`. The header comment in `session-titles.ts` said the CLI never titles SDK sessions; that is out of date. The CLI's off switch only applies to the `sdk-cli` entrypoint without `CLAUDE_AGENT_SDK_VERSION`, and the TS SDK sets `sdk-ts` and that variable. - **No message carries an AI title.** The CLI's internal `system/session_title_changed` covers only `/rename`-style names, and its schema says so. - **The adapter only checked at `idle`.** `SessionTitles.onTurnEnd` ran at `session_state_changed: idle`, which comes after the whole turn. Since CLI 2.1.270 it also waits for background subagents to finish. In the common case, `onTurnEnd` just picked up the title that had been on disk for the whole turn. ## Change - **New `SessionTitles.onPromptQueued`**, called right after the prompt is pushed to the SDK. Until the session has a title, it: 1. reads the session file, and publishes a stored title if there is one (a resumed session, or a `/rename`); 2. otherwise sends `generate_session_title` with the prompt text only, in the background, and publishes the result. - **No second model call.** The CLI runs this request alongside the turn instead of queuing it behind it. Its handler returns the stored custom title, then the AI title, and otherwise waits for the CLI's own title call already in flight. - **One try per prompt, like the CLI.** After a prompt-time request, the turn end does not ask again. If nothing came back, it publishes the stored summary as before, and the next prompt tries again. - **Unchanged:** - the turn end still titles a prompt too short to title from (under 10 characters, like "hi") from the prompt plus the reply; - the turn end still picks up a later `/rename`; - a title the client set still wins. ## Verification - `npm run check` and `npm run test:run` pass (3275 passed, 30 skipped). - New tests: - the title is published while the first turn is still running; - the raw prompt is not published at turn end while a title is still pending; - a short "hi" prompt is titled at turn end from the prompt and the reply. - The latch-release test now pins one request per prompt. Removing the new call site makes two of the tests fail. - Live check: one real text-only turn against this branch and against `main`, both on the bundled CLI 2.1.303, timing `session_info_update` against the prompt response: | build | title published | prompt response | | --- | --- | --- | | this branch | 0.8s | 17.1s | | `main` | 17.9s | 17.9s | Both runs got the same title, and both transcripts contain the same two `ai-title` entries. So the change adds no title generation; the CLI itself writes the entry twice. ## Risks - **Undocumented CLI behaviour.** This depends on the CLI answering `generate_session_title` mid-turn and returning the title it is already generating, which `sdk.d.ts` does not document. If a future CLI changes that, the worst case is one extra small-model call per session. The latch still limits it to one success. - **Titles now arrive mid-turn.** Clients that expected `session_info_update` only between turns should be checked. - **Steering is not covered.** Messages injected with `_session/steering` don't trigger a title request.v0.94.1-preview.8 |
||
|
|
aa62f44886 |
ci: resolve latest Node LTS patches before using runner cache (#1404)
## Summary - Enable `check-latest: true` for all three Node setup steps: CI, stable publishing and preview publishing. - Preserve the existing `lts/*` policy, action pins, npm settings, package version and `engines.node` requirement. ## Why The latest sampled [CI](https://github.com/agentclientprotocol/claude-agent-acp/actions/runs/39865544394) and [preview publishing](https://github.com/agentclientprotocol/claude-agent-acp/actions/runs/39865544489) runs both selected cached Node **24.21.0**. That predates **24.22.1**, the fixed Node 24 release for the [October 21 security updates](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases), including CVE-2026-111497. ## Validation The same checks passed before and after: - Baseline on local Node **24.22.0**: `npm ci && npm run check && npm run build && npm run test:run`. - After on official Node **24.22.1** (archive SHA-256 verified): `npm ci && npm run check && npm run build && npm run test:run`. - Both runs: **3,272 passed, 30 skipped**; the skipped/integration coverage remains unverified. - Parsed workflow configuration to verify all three setup steps keep `lts/*` and enable `check-latest`. - Tests ran natively on macOS; GitHub runner selection remains to be confirmed by PR CI. No publish or release commands were run. ## Risk / rollout Low-risk CI-only runtime freshness change. Verify the next CI/stable/preview job's setup-node log resolves at least **24.22.1** for Node 24. Reverting restores cache-first selection, which can restore an unpatched runtime; it is not a mitigation. This patches the build/publishing environment, not end users' separately installed Node runtimes. No application-code or release-version changes are included.v0.94.1-preview.7 |
||
|
|
9b3a5c891c |
feat: end a turn at its result for AIR clients with backgroundSubagents (#1262)
## What This PR adds the AIR client capability `backgroundSubagents`. A client declares it in `initialize.clientCapabilities._meta.jetbrains.air.capabilities`. With the capability, an ACP v1 prompt turn ends at its result. This is also true while background subagents of the turn still run, including a subagent that SendMessage resumed. Subagent updates, permission requests and elicitations then go out after the prompt response. Their routing does not change. The agent advertises the capability only to ACP v1 AIR clients. ## Why The hold of #864/#866 keeps `session/prompt` open until the subagents finish. The Claude CLI ends the model turn at `result`, and only `idle` waits for the background agents. In AIR the hold hides the end of the answer, and the next user message steers into an old turn. One SendMessage-resumed subagent kept a turn open for about two hours. ## Unchanged - A client without the capability keeps the hold exactly. So #866 stays fixed for clients that stop listening at the prompt response. - ACP v2 keeps the hold too. ## Related changes - Out of a turn, the ExitPlanMode request of such a client does not offer the clear-context option. The fresh query must continue an ACP turn, and there is none. - An ExitPlanMode interruption of an autonomous cycle with no held turn now clears its markers. ## Docs `docs/air-extensions.md` has a new "Background subagents" section. ## Tests New capability cases: - a fresh subagent; - a SendMessage-resumed subagent; - a permission request after the prompt response, with the `parentToolUseId` attribution; - an autonomous followup that does not end the queued next prompt; - ExitPlanMode out of a turn, with and without a reset; - the exclusion of a running subagent from the incomplete-tool check. The existing tests cover the path without the capability. When the gate is disabled, 7 of the 8 new cases fail. The eighth is the in-turn control case and passes in both configurations. `npm run build`, `npm run check` and `npm run test:run` pass. The exception is 4 `providers.test.ts` cases. They depend on the environment (a local proxy `baseUrl`) and fail on `main` too.v0.94.1-preview.6 |
||
|
|
ecaa2c935b |
fix: bump postcss from 8.5.30 to 8.5.31 in the minor group (#1403)
Bumps the minor group with 1 update: [postcss](https://github.com/postcss/postcss). Updates `postcss` from 8.5.30 to 8.5.31 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/postcss/postcss/releases">postcss's releases</a>.</em></p> <blockquote> <h2>8.5.31</h2> <ul> <li>Fix better source map on <code></style></code> escaping (by <a href="https://github.com/firefoxic"><code>@firefoxic</code></a>).</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/postcss/postcss/blob/main/CHANGELOG.md">postcss's changelog</a>.</em></p> <blockquote> <h2>8.5.31</h2> <ul> <li>Fix better source map on <code></style></code> escaping (by <a href="https://github.com/firefoxic"><code>@firefoxic</code></a>).</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="v0.94.1-preview.5 |
||
|
|
5b11f470b1 |
feat: show messages typed in other Remote Control clients (#1371)
A message typed in claude.ai or the Claude mobile app while Remote
Control is on never appeared in the client that hosts the session, even
though Claude's reply to it did. This makes both sides of that
conversation show up.
Two causes, one commit each:
- **Messages from other clients were dropped.** Claude Code echoes them
to the adapter as a replayed user message with `origin: { kind: "human"
}` and a uuid the adapter never created. That matched no turn, so it
fell into the "unrelated replay" branch and was ignored. Human-origin,
top-level, non-synthetic messages that match no turn are now forwarded
as `user_message_chunk` (mapped to `user_message` on ACP v2). The echoes
of the adapter's own prompts still match their turn first and stay out
of the feed.
- **The stream reader was not running after `/remote-control`.** The
reader that forwards Claude Code's output starts with the first prompt,
and `/remote-control` answers without a turn. In a thread where it was
the first thing run, nothing read the stream, so neither the phone's
message nor Claude's reply reached the client. The command now starts
the reader. This also fixes the reply side for #1197.
## Testing
- `npm run check`, `npm run build` and `npm run test:run` pass, with new
tests in `remote-user-messages.test.ts` and `remote-control.test.ts`.
The tests for both fixes fail without them.
- Ran the built adapter as a custom agent in Zed: after
`/remote-control`, a message sent from the Claude iOS app showed up in
the Zed thread along with Claude's reply.
- Not tested: messages with images or attachments, and whether resuming
a session can replay old human messages through the same path.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
v0.94.1-preview.4
|
||
|
|
e9f986b8a9 |
fix: IJAI-3744 keep a session running while its background tasks are open (#1399)
## Summary A Claude Code session can start a background shell command or a background sub-agent, and then end its turn. When a task ends, Claude Code wakes the session for a short turn. The session index reported `idle` at each turn end, so a client saw one completion for each task. Now the index finds the open background tasks in the transcript. A turn end with an open task stays `running`, also after 10 minutes. The session gets one `idle`, when the last task ends. The rules are the same as in the native Claude provider of AIR (IJAI-3744). ## Rules - A task opens with a tool result that has `backgroundTaskId`, or `isAsync` with an `agentId`. - A task closes with its `<task-notification>` (a user record or a queue `remove`), or with a `TaskStop` result. - The wait ends when no live process holds the session, or when the registry status is `idle`. - A task can start before the tail window. A later scan applies the tail on top of the earlier task set. When it cannot, the index reads the whole transcript, but only for a finished turn of a live session. ## Not in this PR - A background task that a sub-agent starts. Its start record is only in the transcript of the sub-agent. - A session that this connection runs. Its state comes from the SDK. ## Tests - `background-tasks.test.ts`: the record orders of the native provider tests, in a small transcript and in one longer than the tail window. The tests also cover a task before the tail window, the end of the wait, and the count of whole-file reads. - A real check with Claude Code 2.1.306 in a terminal. With two background shells or two background sub-agents, `main` gave three `idle` and this change gave one. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>v0.94.1-preview.3 |
||
|
|
4d378f93f3 |
feat: serve experimental ACP v2 (#1400)
## Summary The draft ACP v2 is no longer opt-in. The adapter always connects through the SDK's protocol router (as codex-acp does), so a client that asks for protocol version 2 or later in `initialize` gets v2, and every other client gets v1 as before. v2 is still experimental and follows the draft as it changes. - Removes `CLAUDE_AGENT_ACP_EXPERIMENTAL_V2`, which only turned on what is now the default. - Adds `CLAUDE_AGENT_ACP_PROTOCOL` to limit the adapter to one version: - unset, empty, or `auto`: both, picked by the client's `initialize`. - `v1`: a client that asks for v2 is negotiated down to v1. This is the escape hatch if a client's v2 handling breaks. - `v2`: a v1 client's `initialize` is rejected with `-32022 Unsupported protocol version`. - Any other value fails at startup, so a typo like `CLAUDE_AGENT_ACP_PROTOCOL=1` doesn't silently serve both. - Fixes the comment in `src/acp-subagents.ts` that said v2 clients don't get subagents. Note: a client that already sends `protocolVersion >= 2` switches to the v2 surface as soon as this lands on `main`, which publishes a preview. ## Testing - New routing tests: down-negotiation to v1, rejecting v1 when limited to v2, env parsing. - `npm run check`, `npm run build`, `npm run test:run` pass. - Ran the built binary over stdio with each setting: default → v2 for a v2 client, `v1` → protocol version 1, `v2` → `-32022` for a v1 client, invalid value → exits with an error at startup. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>v0.94.1-preview.2 |
||
|
|
a1d0eeeaad |
fix: publish turns that Claude Code starts after end_turn as an async task in v1 (#1390)
## Motivation
Claude Code can start a turn of its own after a prompt has ended, for
example to answer the notification of a finished background task. ACP v1
has no session state, and the client already got `end_turn` for its last
prompt. The output of that turn just keeps arriving as session updates,
and the client has no signal that the agent is working again, or when it
stops.
## Change
The adapter now publishes such a turn as an async task (AIR async tasks
extension) with the id `autonomous-turn-<uuid>`, the name `Claude is
working`, `taskType: "turn"` and `showInTranscript: false`. Its
description is the summary of the last task notification, when there is
one.
- **Start:** the SDK moves to `running` while no prompt is active or
queued. From CLI 2.1.270 the state stays `running` while background
agents run, so the task also starts at the first root output with no
prompt open.
- **End:** the task ends `completed` at the turn's result or at `idle`,
and `failed` at an error result. A coalesced placeholder result
(`num_turns: 0`) does not end it.
- **Folded prompt:** a prompt that the turn takes in ends the task,
because that prompt owns the turn now.
- **Stop:** `_session/async_task/stop` on this task interrupts the turn,
since the SDK has no task to stop. It returns `{ "stopped": false }`
while a prompt waits for its turn, because the interrupt would drop that
prompt.
- **Lifecycle:** the SDK task list does not end the task, because the
SDK does not know about it. Shutdown fails it like other open tasks.
Clients without the async tasks capability get nothing new. The behavior
is documented in `docs/air-extensions.md` under "Autonomous turn".
## Tests
`acp-agent.test.ts` covers the start at `running` and at the first
output, the end at the result, the folded prompt, stop as an interrupt,
and a client without async tasks. `async-tasks.test.ts` covers the SDK
task list reconciliation and shutdown.
v0.94.1-preview.1
|
||
|
|
7bcbfc7a5c |
chore(main): release 0.94.0 (#1381)
🤖 I have created a release *beep* *boop* --- ## [0.94.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.93.0...v0.94.0) (2026-10-19) ### Features * send one end event after the session/load history replay for AIR ([#1361](https://github.com/agentclientprotocol/claude-agent-acp/issues/1361)) ([v0.94.0 |
||
|
|
2dab922644 |
fix: update to Claude Code 2.1.303 (#1384)
Updates `@anthropic-ai/claude-agent-sdk` from 0.3.300 to **0.3.303**
(Claude Code **2.1.303**), along with dependabot's minor-group bumps
(`@anthropic-ai/sdk`, eslint, vitest and transitive packages). 0.3.304
is only on the `next` dist-tag, so it is not included.
## Fixes for changes in the new SDK
The Agent SDK turns on fork subagents (`subagent_type: "fork"`) by
default in SDK sessions (0.3.302). Before this, ACP sessions never got
them. Live streaming already handles forks. History replay did not:
- **Replay showed the parent's launching message inside the fork.** A
fork's transcript starts with a copy of the parent's launching assistant
message (with the same API message id and every `tool_use`), then a user
message with a `"Fork started — processing in background"` result per
`tool_use` and a `<fork-boilerplate>…Your directive: <prompt>` text. On
`session/load`, the parent's text, tool calls and those results appeared
in the fork, and the fork's prompt showed the full boilerplate.
Replaying the copy also consumed the parent's tool-use cache entries, so
the parent's real Agent/parallel tool results were dropped. In the AIR
form, sibling forks were re-registered under the fork.
`readSubagentMessages` now drops everything before the directive message
and reduces it to the prompt (`stripForkPrefix`).
- **Lineage scan** (`subagentLineage`) ignores launch calls in a fork's
copied prefix, so it no longer attributes the parent's launches to the
fork.
- **Agent title** no longer shows `(high effort)` for a fork: a fork
ignores `effort` and runs at the parent's effort.
## Changelog review: nothing else to change
- **0.3.302: an omitted `permissionMode` now starts in `default` on
third-party providers.** The agent always passes `permissionMode`
explicitly, so this does not apply.
- **0.3.301: a full-disk login refresh now reports `invalid_request`
instead of `authentication_failed`/401.** This now maps to `bad_request`
rather than `auth_required`. That's the right outcome, since `/login`
cannot fix a full disk. Its text has no "Please run /login", so the
synthetic-login check does not catch it.
- **0.3.301: `setModel()` no longer fails at the usage limit.** This is
a free fix for model switches.
- **0.3.302: structured output refusals are now error results.** These
are covered by the existing result handling.
- **New APIs not adopted:**
- Per-tool `permission_policy` on sdk MCP servers: we register none.
- `reloadPlugins({ addPlugins })`: there's no plugin reload surface.
- `BUILTIN_TOOL_NAMES`/`LEGACY_TOOL_NAME_ALIASES`: `@alpha`, and nothing
here needs them.
- MCP `_meta.ui`: unused.
Verified: `npm run build`, `npm run check`, `npm run test:run` (3205
passed). New tests cover the fork replay trace (RFD form),
`stripForkPrefix`, the lineage scan with a fork transcript (it fails
without the fix), and the fork title.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
v0.93.1-preview.6
|
||
|
|
ff01e06579 |
fix: update to ACP SDK 2.0.0 (#1386)
Updates `@agentclientprotocol/sdk` from 1.9.0 to 2.0.0. SDK 2.0.0 makes the default entrypoints stable-only and removes the legacy connection classes ([migration guide](https://github.com/agentclientprotocol/typescript-sdk/blob/main/MIGRATION_STABLE_UNSTABLE.md)). - Protocol imports move to `@agentclientprotocol/sdk/unstable` and `@agentclientprotocol/sdk/experimental/v2/unstable`. The agent uses unstable features (session forking, `systemPrompt`, turn usage, subagents, v2 draft extras), so this keeps the same protocol surface as 1.9.0. No wire changes. - The scenario schema validator loads `schema/v1/schema.unstable.json`, because the unversioned `schema/schema.json` export was removed. - `remote-control.test.ts` uses the repo's own `AcpClient` type instead of the removed `AgentSideConnection`. - Runtime code already used the `agent()` app API, so it needed no migration. Verified: `npm run build`, `npm run test:run` (3199 passed), `npm run check`, and a separate typecheck of `examples/`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>v0.93.1-preview.5 |
||
|
|
e155ecb419 |
test: expect the v2 state snapshot after the replay end event (#1385)
`main` has failed CI since #1361, on one test: `ACP v2 prompts > ends a resume with replay with one end event for a client with loadReplayEnd`. Two PRs that merged separately collided: - #1366 made a v2 resume send a `state_update` snapshot after the replay and before the response ("v2 requires a snapshot of the foreground state after the replay", in `src/v2/agent.ts`). - #1361 added the `loadReplayEnd` end event and this test, which expected the end event to be the last update of the response. The test predates the snapshot, so each PR passed CI on its own. The snapshot is required by the v2 spec, so the code is right and the test is stale. The test now expects the end event followed by the snapshot, and still checks that the end event is sent once. Only `src/tests/acp-v2.test.ts` changes. ## Testing - `npm run check`, `npm run build` and `npm run test:run` pass (3199 passed, 30 skipped). - The same test fails on `main` at `bcf74c2` without this change. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>v0.93.1-preview.4 |
||
|
|
bcf74c2fe8 |
fix: match OpenRouter model ids in the gateway model listing (#1365)
The model picker was empty behind OpenRouter: `normalizeModelId` did not match `anthropic/claude-opus-5.5:batch[1m]` to `claude-opus-5-5`. It now strips a leading `anthropic/` and a `:variant` suffix, and maps `5.5` to `5-5`.v0.93.1-preview.3 |
||
|
|
1420994ced |
feat: send one end event after the session/load history replay for AIR (#1361)
## What
A client that declares the AIR capability `loadReplayEnd` gets one extra
`session/update` after the history replay of `session/load`:
```json
{
"sessionId": "<loaded session>",
"update": {
"sessionUpdate": "session_info_update",
"_meta": { "jetbrains": { "air": { "version": 1, "loadReplayEnd": true } } }
}
}
```
The client declares the capability in
`clientCapabilities._meta.jetbrains.air.capabilities`, as it declares
the other AIR extensions. The agent does not advertise it.
## Why
ACP has no signal that the history replay of `session/load` is over,
other than the response. This adapter replays the transcript while the
Claude Code CLI starts, and the CLI start takes most of the load time.
So the history is whole long before the response. With this event, the
client can show the history at once.
The protocol side is the RFD
https://github.com/agentclientprotocol/agent-client-protocol/pull/2407.
## Design change
The first version of this PR marked each replayed notification with an
index (`loadSessionReplayIndex`) and the last one with
`loadSessionEndOfRecordedHistory`. To know the last one, it held the
latest update and queued every other outbound message of the session
behind it. That design is replaced with a capability-gated single end
event. The replay sends as before. Only one event is added at its end.
There are no indexes, no held update and no queue.
## When the event is sent
- After every replayed update, the subagent history that the parent
replay sends to the child sessions included, and before the
`session/load` response.
- Also for an empty history.
- For `session/load` of a session that starts while the replay runs, for
`session/load` of a session that is already live, and for the ACP v2
`session/resume` with `replayFrom: {type: "start"}`.
It is not sent:
- When the replay stops (the CLI start failed during the replay) or
fails.
- For a live update.
- To a client without the capability.
The update has no `title` and no `updatedAt`. A `null` there would clear
the value. The load can still fail after the event, for example when the
CLI start fails after the replay. The event means that the recorded
history arrived whole.
## Client status
JetBrains Air shows the history before the load answer only after the
Kotlin SDK delivers the updates of a loading session before the answer.
An SDK PR for this is in progress.
## Tests
- `create-session-options.test.ts`: the event comes once after the
replay and before the response; before the CLI start finishes; for an
empty history; for an already live session; not when the CLI start fails
part way; not when the replay fails; not without the capability. The
event has no `title` and no `updatedAt` key.
- `acp-agent.test.ts`: the subagent history from its own transcript file
comes before the event.
- `acp-v2.test.ts`: v2 `session/resume` with a replay ends with the
event before the response; a resume without a replay sends none.
- `docs/air-extensions.md`: a new "Load replay end" section, and the
capability and key rows.
v0.93.1-preview.2
|
||
|
|
424db87535 |
fix: resolve a skill's SKILL.md by its declared name, not by its directory name (#1372)
## Problem Claude Code advertises a skill by the `name:` of its `SKILL.md` frontmatter, which does not have to match the name of the directory — or of the symlink — that holds the file. `resolveSkillPath` joined the advertised name into each container path and only checked whether the result exists, so every such skill resolved to nothing. For an AIR client the consequence is visible: `getAvailableSlashCommands` attaches `_meta.jetbrains.air.kind = "skill"` and the `SKILL.md` path only when the path resolves, so the skill reached the client as a plain command and disappeared from the skill completion, while `/name` kept working. Symlinked skills hit this most often, because the link name is usually chosen independently of the skill's declared name. Reproduced with a project whose `.claude/skills/mismatch/SKILL.md` declares `name: frontname`, and with `.claude/skills/aliased2 -> …/target2` declaring `name: front2`: both were advertised without any `_meta`. The same happens in a large repo where `.claude/skills/rubymine` declares `name: rubymine-workflows`. ## Fix The existing join-by-name probe stays the first attempt, so nothing changes for the common layout. When it misses, the same containers are scanned, in the same order, for a `SKILL.md` whose frontmatter declares the requested name: - `statSync`/`existsSync` follow links, so a skill behind a symlinked directory is scanned like any other; - each container is listed per lookup, and a `SKILL.md` whose modification time has not changed keeps the name of the previous scan, so an unchanged file is parsed once; - only the frontmatter block of at most 8 KB is parsed, so a `name:` in the body is not a name; - a directory that is itself named like the skill still wins over another skill that merely declares the name. ## Tests Eight cases in `src/tests/tools.test.ts` cover a directory/declared-name mismatch, a symlink with a differing link name in both `.claude/skills` and `.agents/skills`, the precedence of the directory that carries the name, scoped and plugin spellings resolved by declared name, a file without frontmatter, and a declared name that changes after the first resolution. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Happy <yesreply@happy.engineering>v0.93.1-preview.1 |
||
|
|
dbf386d8d3 |
chore(main): release 0.93.0 (#1369)
🤖 I have created a release *beep* *boop* --- ## [0.93.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.92.0...v0.93.0) (2026-10-16) ### Features * add /remote-control command to start Remote Control for a session ([#1197](https://github.com/agentclientprotocol/claude-agent-acp/issues/1197)) ([v0.93.0 |
||
|
|
db9f50f021 |
feat: add /remote-control command to start Remote Control for a session (#1197)
Adds a `/remote-control [name]` command (alias `/rc`) so a session hosted over ACP can be continued from claude.ai/code or the Claude mobile app. Addresses #459. The CLI's own `/remote-control` is terminal-bound and isn't advertised to SDK hosts, and `remoteControlAtStartup` only applies to interactive sessions. The SDK does expose a runtime `enableRemoteControl(enabled, name?)` on the query object, which returns the session URL. See anthropics/claude-agent-sdk-typescript#460. - The adapter handles the command itself in `prompt()`, calls `enableRemoteControl(true, name)`, and replies with the session URL as an agent message. The turn ends without going to the model. - Failures (for example Remote Control disabled by policy) are reported to the user in the same way. - The command is added to `available_commands_update` only when the query exposes the method. - `enableRemoteControl` is not in the published `Query` types yet, so it is typed locally the same way as `mcpAuthenticate`. ## Testing - `npm run check`, `npm run build` and `npm run test:run` pass, including new tests in `src/tests/remote-control.test.ts`. - Ran the built agent through `examples/simple-client.ts` against a real Claude Max session: the command was advertised, `/remote-control` returned a working `claude.ai/code` URL, and prompts sent from the Claude iOS app ran in the session and were answered. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Noah Eisenbruch <noaheisenbruch@gmail.com> Co-authored-by: Andrey Bragin <andrey.bragin@jetbrains.com>v0.92.1-preview.2 |
||
|
|
f5967fd6b4 |
fix: hold a fork back from the session list until its session/fork response is out (#1368)
## Problem `session/fork` copies the transcript and then starts the forked session, which takes several seconds. Meanwhile the list subscription sees the new transcript and sends `_session/list/changes` with the fork row before the fork response. The client meets an unknown session and lists it as a session of its own. JetBrains Air then refuses the fork (IJAI-4105). ## Fix - `ForkHolds` (in `session-index/list-subscriptions.ts`, owned by the session index service) holds the row of a fork until the `session/fork` response is out: - by `forkedFrom`, for an unsent row, while the transcript is copied; - by the fork id after the copy. This covers a fork whose first record is over 64 KB, because the scan reads `forkedFrom` from the head only. - `session/list` leaves a held fork out too. - The v1 and v2 fork handlers run in `forking(...)`. A `setTimeout(0)` releases the rows after the SDK has written the response. - The holds live in the service, so a subscription that starts during a fork holds that fork too. ## Tests `holds a fork back until the response of its session/fork is out` (session-index.test.ts). It fails without the fix.v0.92.1-preview.1 |
||
|
|
af3d7f9335 |
chore(main): release 0.92.0 (#1358)
🤖 I have created a release *beep* *boop* --- ## [0.92.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.91.0...v0.92.0) (2026-10-16) ### Features * add the MCP server and tool to AIR tool calls ([#1359](https://github.com/agentclientprotocol/claude-agent-acp/issues/1359)) ([v0.92.0 |
||
|
|
68bf74f58e |
feat: update ACP SDK to 1.9.0 and adopt the v2 spec clarifications (#1366)
Updates `@agentclientprotocol/sdk` to 1.9.0 (schema v1.26.0, v2.0.0-alpha.9) and adapts the agent to the v2 spec clarifications in that release. ## Changes **Client-provided system prompt (unstable)** - Advertises `sessionCapabilities.systemPrompt` with `mode.override` on v1 and `session.systemPrompt` on v2. - Accepted on `session/new`, `load`, `resume`, and `fork`: - `append` adds the text after the Claude Code preset. - `override` replaces the preset with the text. Tools, MCP servers, permissions, and settings (including CLAUDE.md through `settingSources`) are unchanged. - An unsupported mode or non-text content fails with `invalid_params` before any session is created, reused, or forked. - Takes precedence over the `_meta.systemPrompt` extension. AIR custom instructions still follow the client text. - A different prompt on resume recreates a live session. Claude Code reuses its saved system prompt until the next compaction, which the RFD allows. **v2 session/resume state snapshot** - Sends the current foreground state (`idle`, `running`, or `requires_action`) after any replay and before the response, as the clarified spec requires. This applies even without a replay. **v2 replay of subagents** - No longer replays a child's past `running`/`idle` as current activity. Each replayed child gets one `state_update` with its last state after the replay. **v2 tool call `_meta` patches** - Reports carry only the top-level keys that changed. `claudeCode` is still sent whole, since clients don't merge nested objects. - A removed key is sent as `null`. - A tool call id that starts again removes the old keys. - A replayed tool call this connection has not reported sends `_meta: null` first, then the current keys. **Cancellation and close** - A `session/close` whose turns don't end within the teardown timeout settles them as cancelled. The client gets `idle` with `cancelled`, or `-32800` for a prompt never inserted, before the close response. - A prompt racing `session/close` ends as cancelled (`-32800` on v2) instead of `-32603`. On v1 it now returns `stopReason: cancelled`, matching a prompt queued just before the close. - A stream error after a cancel ends the work as `cancelled` instead of `error`. ## Not in this PR - After a URL-mode MCP elicitation is accepted, the session reports `running` right away. The spec asks for `requires_action` until the external interaction finishes, but a server may never send `elicitation_complete`, so this needs its own design. - `requires_action` is reported while one foreground subagent waits, even if other foreground work can continue. This is SHOULD-level in the spec. ## Testing - `npm run build`, `npm run check`, and `npm run test:run` pass. - Golden files changed because of the new capability and the resume snapshot. `compare.ts` allows the new capability against origin/main. - `session index cost > reads only the changed transcript for a subscription` failed intermittently locally (about 3 in 15 runs) on a loaded machine. This PR doesn't touch the session index, but watch it in CI. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>v0.91.1-preview.5 |
||
|
|
26f144a2a5 |
fix: restore resumed subagents after an adapter restart (#1364)
After a restart the AIR subagent map is empty, so a SendMessage resume opened no generation and the child's messages stayed buffered under the old launch id. Restore the agent from the session history on a resume signal or on a message with an unseen parent_tool_use_id, with a generation id that can't collide with ids the client stored before.v0.91.1-preview.4 |
||
|
|
872e93f11f |
feat: add the MCP server and tool to AIR tool calls (#1359)
AIR gets `_meta.jetbrains.air.mcp = {server, tool}` on MCP tool calls,
so the MCP card does not depend on the title format.
The adapter splits the `mcp__<server>__<tool>` tool name the way Claude
Code does. `server` is the normalized name. Clients other than AIR get
nothing new.
Split from IJAI-872. The SDK does not expose MCP progress yet, so this
PR does not forward it.
v0.91.1-preview.3
|
||
|
|
78a29f58ba |
feat: publish the predicted follow-up prompt as _meta.promptSuggestions (#1356)
## What
The Claude Code CLI can predict the prompt the user is likely to send
next. This adapter asked for nothing and dropped the `prompt_suggestion`
message. It now asks for the prediction (`promptSuggestions: true`) and
forwards the one prediction of a turn.
ACP has no field for a composer prefill, so the value travels as
```json
{
"sessionUpdate": "session_info_update",
"_meta": { "promptSuggestions": { "suggestions": [{ "text": "Run the tests" }] } }
}
```
The key names no vendor, so another client can read it. AIR already
renders the first non-blank text as gray text in an empty composer,
where Tab fills the composer and sends nothing.
## Behavior
- `suggestions: []` clears the prediction the client holds: at the next
`session/prompt`, because that turn's prediction is spent, and on a
`conversation_reset`, because the transcript it was drawn from is gone.
- A prediction the next prompt outran — the user sent the next prompt
before the adapter read the prediction off the SDK stream — is dropped
instead of published mid-turn.
- A blank prediction never goes on the wire.
- The update is sent only to an AIR client, like the other extension
keys, so non-AIR traffic is unchanged (the key is added to
`AIR_ONLY_META_KEYS`; the `origin/main` scenario baselines stay
byte-identical).
- The CLI predicts nothing on the first turn, after an API error, in
plan mode, and at the usage limit, so a turn without a prediction is
normal. A caller can opt out with
`_meta.claudeCode.options.promptSuggestions: false`.
Documented in `docs/air-extensions.md`.
## Tests
`src/tests/prompt-suggestions.test.ts` covers the wire shape, the
publish after the turn's result, the clear at the next prompt, the
dropped stale prediction, the blank prediction, and a non-AIR client.
`src/tests/create-session-options.test.ts` covers the SDK option and the
caller opt-out.
`npm run check`, `npm run build` and the touched suites are green; the
full `test:run` has pre-existing flakiness on this machine
(session-index watchers, providers) unrelated to this change.
Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Happy <yesreply@happy.engineering>
v0.91.1-preview.2
|
||
|
|
910d83ceea |
fix: include subagent file edits in the file-change report (#1357)
## Summary `agentFileChangeReport` took its path list only from Claude's file checkpoints (`rewindFiles` dry run). A checkpoint tracks only the files that the root agent edits with its own file tool. So a file that only a subagent edited never appeared in the report. Air then showed no "Since last turn" row for it, and Last Turn review could not include it. - Collect the `file_path` / `notebook_path` of successful `Edit`/`Write`/`MultiEdit`/`NotebookEdit` results from subagent messages in the stream. Store them on the active turn. This also covers background subagents, because the turn stays open until they finish. - Merge these paths with the checkpoint list. When the checkpoint preview times out or is unavailable, report the subagent paths instead of `unavailable`.v0.91.1-preview.1 |
||
|
|
c0af592d25 |
chore(main): release 0.91.0 (#1333)
🤖 I have created a release *beep* *boop* --- ## [0.91.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.90.0...v0.91.0) (2026-10-15) ### Features * keep background subagents running after a parent cancel, for clients that can cancel them ([#1348](https://github.com/agentclientprotocol/claude-agent-acp/issues/1348)) ([v0.91.0 |
||
|
|
761b4c8359 |
fix: update Claude Agent SDK to 0.3.300 (#1355)
Updates `@anthropic-ai/claude-agent-sdk` from 0.3.296 to 0.3.300 (parity
with Claude Code v2.1.300), and `@anthropic-ai/sdk` from 0.133.0 to
0.134.0.
No code changes needed. The new types are an optional `property_order`
on elicitation requests, `nextFireAt` on the CronCreate/CronList
outputs, and `owned` on Artifact outputs. We don't need any of them.
Fixes picked up that affect this agent:
- `importSessionToStore` (used for session forks) no longer skips
transcript rows containing U+2028/U+2029 on Node 24.
- Resuming an SDK session after a compaction no longer loses the recent
messages or the compaction summary in some cases.
- Background subagents in auto mode no longer send their final report
twice or merge it into another turn.
- Queued content-block prompts merged into one turn are now separated by
a line break.
- `ScheduleWakeup` now fires while a background task is running.
Behaviour change: `MAX_THINKING_TOKENS=0` (sent as `thinking: { type:
"disabled" }`) now runs adaptive thinking on models that can't turn
thinking off.
`npm run build`, `npm run check` and `npm run test:run` all pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
v0.90.1-preview.16
|