## Motivation
ACP clients currently have two gaps when rendering Claude Code activity:
1. Bash tool calls expose the shell command as the standard ACP title,
but the concise human-readable `description` produced by Claude Code is
lost.
2. ACP 1.2 has no standard subagent tool kind or nested-message
relationship, so subagent prose and child tools are either flattened
into the main conversation or filtered out entirely.
This PR adds namespaced metadata and an explicit client capability so
richer clients can render both cases without changing the standard ACP
schema or regressing legacy clients.
## What changed
### Bash descriptions
- Keeps the shell command in the standard ACP `title`, preserving
command-oriented clients.
- Exposes the optional Claude Code Bash `description` as
`_meta.claudeCode.title`.
- Applies the metadata consistently to eager permission tool calls,
normal tool calls, and streamed input refinements.
- Falls back to the command title when no description is available.
### Nested subagent transcripts
- Adds the opt-in client capability
`clientCapabilities._meta["subagent-transcript"] = true`.
- Enables the Claude Agent SDK `forwardSubagentText` option when the
client advertises support.
- Preserves the pre-existing caller-provided `forwardSubagentText: true`
option for compatibility.
- Marks Agent and legacy Task launches with `_meta.claudeCode.subagent =
true`.
- Relates nested text, thinking, and child tool calls to the launching
Agent/Task call through `_meta.claudeCode.parentToolUseId`.
- Preserves parent attribution during session-history replay, not only
during live streaming.
- Handles nested Agent-to-Agent launches without inferring subagents
from the generic ACP `think` kind.
## Compatibility
Clients that do not advertise `subagent-transcript` retain the previous
behavior: subagent text and thinking remain filtered from the top-level
feed.
The normal Agent/Task tool result is still emitted in every mode as the
protocol-compatible fallback. No existing result or standard ACP field
is removed or redefined.
## Validation
- `npm run build`
- `npm run check`
- `npm run test:run`
- 623 tests passed, 20 skipped
Coverage includes live and replayed nested text/thinking, child tool
attribution, Agent/Task launch markers, nested Agent launches, legacy
filtering, and SDK-option compatibility.
Bumps [@hono/node-server](https://github.com/honojs/node-server) from
1.19.14 to 1.19.15.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/honojs/node-server/commits">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the minor group with 2 updates:
[@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript)
and [hono](https://github.com/honojs/hono).
Updates `@anthropic-ai/sdk` from 0.113.0 to 0.114.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/anthropic-sdk-typescript/releases">@anthropic-ai/sdk's
releases</a>.</em></p>
<blockquote>
<h2>sdk: v0.114.0</h2>
<h2>0.114.0 (2026-07-23)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.113.0...sdk-v0.114.0">sdk-v0.113.0...sdk-v0.114.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> add new stop reason
'model_context_window_exceeded' (<a
href="1ec71c165d">1ec71c1</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/anthropic-sdk-typescript/blob/main/CHANGELOG.md">@anthropic-ai/sdk's
changelog</a>.</em></p>
<blockquote>
<h2>0.114.0 (2026-07-23)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.113.0...sdk-v0.114.0">sdk-v0.113.0...sdk-v0.114.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> add new stop reason
'model_context_window_exceeded' (<a
href="1ec71c165d">1ec71c1</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="2d314b4127"><code>2d314b4</code></a>
chore: release main</li>
<li><a
href="3d051dfe49"><code>3d051df</code></a>
feat(api): add new stop reason 'model_context_window_exceeded'</li>
<li>See full diff in <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.113.0...sdk-v0.114.0">compare
view</a></li>
</ul>
</details>
<br />
Updates `hono` from 4.12.31 to 4.12.32
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/honojs/hono/releases">hono's
releases</a>.</em></p>
<blockquote>
<h2>v4.12.32</h2>
<h2>What's Changed</h2>
<ul>
<li>ci: enable reports for type & bundle size check in <a
href="https://redirect.github.com/honojs/hono/pull/5148">honojs/hono#5148</a></li>
<li>fix(aws-lambda): add jwt and lambda authorizer types for API Gateway
v2 in <a
href="https://redirect.github.com/honojs/hono/pull/5142">honojs/hono#5142</a></li>
<li>fix(sse): emit empty id field to reset Last-Event-ID in <a
href="https://redirect.github.com/honojs/hono/pull/5138">honojs/hono#5138</a></li>
<li>test(cloudflare-workers): add coverage for onClose, onError, send,
and close in Cloudflare Workers websocket adapter in <a
href="https://redirect.github.com/honojs/hono/pull/5145">honojs/hono#5145</a></li>
<li>fix: use <code>Object.create(null)</code> when parsing query,
headers, and params in <a
href="https://redirect.github.com/honojs/hono/pull/5161">honojs/hono#5161</a></li>
<li>fix(secure-headers): keep CSP callbacks scoped to their header in <a
href="https://redirect.github.com/honojs/hono/pull/5147">honojs/hono#5147</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/honojs/hono/compare/v4.12.31...v4.12.32">https://github.com/honojs/hono/compare/v4.12.31...v4.12.32</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="26d8e42bff"><code>26d8e42</code></a>
4.12.32</li>
<li><a
href="402eb3abe5"><code>402eb3a</code></a>
fix(secure-headers): keep CSP callbacks scoped to their header (<a
href="https://redirect.github.com/honojs/hono/issues/5147">#5147</a>)</li>
<li><a
href="c85aead088"><code>c85aead</code></a>
fix: use <code>Object.create(null)</code> when parsing query, headers,
and params (<a
href="https://redirect.github.com/honojs/hono/issues/5161">#5161</a>)</li>
<li><a
href="a88c89dac6"><code>a88c89d</code></a>
test(cloudflare-workers): add coverage for onClose, onError, send, and
close ...</li>
<li><a
href="44f884321a"><code>44f8843</code></a>
fix(sse): emit empty id field to reset Last-Event-ID (<a
href="https://redirect.github.com/honojs/hono/issues/5138">#5138</a>)</li>
<li><a
href="e36f57dac0"><code>e36f57d</code></a>
fix(aws-lambda): add jwt and lambda authorizer types for API Gateway v2
(<a
href="https://redirect.github.com/honojs/hono/issues/5142">#5142</a>)</li>
<li><a
href="bf8608cb77"><code>bf8608c</code></a>
ci: enable reports for type & bundle size check (<a
href="https://redirect.github.com/honojs/hono/issues/5148">#5148</a>)</li>
<li>See full diff in <a
href="https://github.com/honojs/hono/compare/v4.12.31...v4.12.32">compare
view</a></li>
</ul>
</details>
<br />
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
## Summary
`session/new` and switching models via `configOptions` regressed to ~15s
each in v0.59.0. This removes the blocking call responsible and seeds
the context window synchronously instead, restoring sub-second behavior
on both paths.
## Root cause
v0.59.0 added an inline `await query.getContextUsage()` on the
session-creation and model-switch paths. That SDK control request is not
serviced by the CLI until the session's first prompt turn has run —
before then it stalls ~15s. And because SDK control requests are
serialized over a single stdin/stdout channel, an awaited `setModel`
queued behind the wedged `getContextUsage` inherited the full stall. So
both paths blocked ~15s before returning.
Verified with the real CLI (setModel alone pre-prompt: ~1ms;
getContextUsage alone pre-prompt: ~16s; getContextUsage-then-setModel:
both resolve together at ~16s, confirming the serialization).
## Fix
Drop `getContextUsage` from both hot paths. The context window is seeded
synchronously by `immediateContextWindow(...)`:
1. an authoritative value from a per-(provider, model) cache, if
learned; else
2. a synchronous text heuristic (`\b1m\b` → 1,000,000); else
3. `DEFAULT_CONTEXT_WINDOW` (200,000).
The authoritative window is learned the moment it's actually available —
from each turn's `result.modelUsage` — and written into the cache, so
later sessions/switches to the same model seed the correct window
immediately with no IPC. A model that has never run a turn shows the
heuristic/default window until its first response, matching pre-0.59.0
behavior.
### Cache design
- **Keyed on `(provider, resolved model id)`.** The resolved id
(`ModelInfo.resolvedModel`, e.g. `claude-sonnet-5[1m]`) matches the
`result.modelUsage` keys, so the write key and the read keys line up.
Keying on the resolved id (not the picker value) dedups aliases that
resolve to the same model; keying on the provider keeps two providers
that reuse an id string for different windows from crossing wires
(per-session provider config, #853). The provider is captured at session
creation, since the effective provider can change process-wide over the
adapter's lifetime.
- **Non-positive/NaN windows are ignored** — they neither overwrite the
session's learned window nor enter the cache.
## Impact (measured, real CLI)
| Path | Before | After |
| --- | --- | --- |
| `session/new` | ~17.4s | ~0.9s |
| model switch (before first prompt) | ~15s | ~3ms |
| model switch (after a turn) | ~14.7s | <1ms |
## Tests
- New end-to-end cache test: a turn's authoritative window (learned
under the resolved id even when the assistant message reports the bare
id) is served on a later switch with no `getContextUsage`.
- New provider-isolation test: the same resolved id on a different
provider does not read another provider's cached window; the same
provider does.
- New non-positive-window test: a nonsensical `contextWindow` is ignored
and never poisons the cache.
- Rewrote the existing context-window tests to the new contract (assert
no `getContextUsage` on session/new and switch; window from
cache/inference/default).
Closes#886Closes#880🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
## Summary
Closes:
https://github.com/agentclientprotocol/claude-agent-acp/issues/878
Fixes the potential ReDoS warning reported by CodeQL in
`stripAgentTrailer()`.
- Replaces regex-based trailer stripping with bounded linear parsing
- Preserves valid `<usage>…</usage>` and `agentId: … (…)` trailer
handling
- Adds coverage for malformed trailers, which are left unchanged
## Testing
- `npm test -- --run src/tests/tools.test.ts`
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bumps the minor group with 14 updates:
| Package | From | To |
| --- | --- | --- |
|
[@anthropic-ai/claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk-typescript)
| `0.3.206` | `0.3.207` |
|
[@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript)
| `0.110.0` | `0.111.0` |
| [eslint](https://github.com/eslint/eslint) | `10.6.0` | `10.7.0` |
| @anthropic-ai/claude-agent-sdk-darwin-arm64 | `0.3.206` | `0.3.207` |
| @anthropic-ai/claude-agent-sdk-darwin-x64 | `0.3.206` | `0.3.207` |
| @anthropic-ai/claude-agent-sdk-linux-arm64 | `0.3.206` | `0.3.207` |
| @anthropic-ai/claude-agent-sdk-linux-arm64-musl | `0.3.206` |
`0.3.207` |
| @anthropic-ai/claude-agent-sdk-linux-x64 | `0.3.206` | `0.3.207` |
| @anthropic-ai/claude-agent-sdk-linux-x64-musl | `0.3.206` | `0.3.207`
|
| @anthropic-ai/claude-agent-sdk-win32-arm64 | `0.3.206` | `0.3.207` |
| @anthropic-ai/claude-agent-sdk-win32-x64 | `0.3.206` | `0.3.207` |
| [es-module-lexer](https://github.com/guybedford/es-module-lexer) |
`2.3.0` | `2.3.1` |
| [hono](https://github.com/honojs/hono) | `4.12.29` | `4.12.30` |
| [postcss](https://github.com/postcss/postcss) | `8.5.16` | `8.5.19` |
Updates `@anthropic-ai/claude-agent-sdk` from 0.3.206 to 0.3.207
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/claude-agent-sdk-typescript/releases">@anthropic-ai/claude-agent-sdk's
releases</a>.</em></p>
<blockquote>
<h2>v0.3.207</h2>
<h2>What's changed</h2>
<ul>
<li>Fixed <code>canUseTool</code> returning <code>{behavior:
'allow'}</code> without <code>updatedInput</code> being rejected as a
deny with a raw ZodError message; the tool now runs with the original
input per the documented contract</li>
<li>The Agent tool's structured result now has a published SDK type
(<code>AgentToolCompletedOutput</code>) that matches the emitted object
exactly</li>
</ul>
<h2>Update</h2>
<pre lang="sh"><code>npm install @anthropic-ai/claude-agent-sdk@0.3.207
# or
yarn add @anthropic-ai/claude-agent-sdk@0.3.207
# or
pnpm add @anthropic-ai/claude-agent-sdk@0.3.207
# or
bun add @anthropic-ai/claude-agent-sdk@0.3.207
</code></pre>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/claude-agent-sdk-typescript/blob/main/CHANGELOG.md">@anthropic-ai/claude-agent-sdk's
changelog</a>.</em></p>
<blockquote>
<h2>0.3.207</h2>
<ul>
<li>Fixed <code>canUseTool</code> returning <code>{behavior:
'allow'}</code> without <code>updatedInput</code> being rejected as a
deny with a raw ZodError message; the tool now runs with the original
input per the documented contract</li>
<li>The Agent tool's structured result now has a published SDK type
(<code>AgentToolCompletedOutput</code>) that matches the emitted object
exactly</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="79b6350e13"><code>79b6350</code></a>
chore: Update CHANGELOG.md</li>
<li>See full diff in <a
href="https://github.com/anthropics/claude-agent-sdk-typescript/compare/v0.3.206...v0.3.207">compare
view</a></li>
</ul>
</details>
<br />
Updates `@anthropic-ai/sdk` from 0.110.0 to 0.111.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/anthropic-sdk-typescript/releases">@anthropic-ai/sdk's
releases</a>.</em></p>
<blockquote>
<h2>sdk: v0.111.0</h2>
<h2>0.111.0 (2026-07-10)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.110.0...sdk-v0.111.0">sdk-v0.110.0...sdk-v0.111.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> add support for dreaming (<a
href="77b28a6472">77b28a6</a>)</li>
<li><strong>tools:</strong> gate session tool calls on
evaluated_permission; bound idle by server stop_reason (<a
href="68a6d7b92a">68a6d7b</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><strong>docs:</strong> small updates to field descriptions (<a
href="e25b885eac">e25b885</a>)</li>
<li><strong>docs:</strong> update model example (<a
href="a33f3f0b7c">a33f3f0</a>)</li>
<li><strong>docs:</strong> updates to descriptions and examples (<a
href="eac4bace32">eac4bac</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/anthropic-sdk-typescript/blob/main/CHANGELOG.md">@anthropic-ai/sdk's
changelog</a>.</em></p>
<blockquote>
<h2>0.111.0 (2026-07-10)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.110.0...sdk-v0.111.0">sdk-v0.110.0...sdk-v0.111.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> add support for dreaming (<a
href="77b28a6472">77b28a6</a>)</li>
<li><strong>tools:</strong> gate session tool calls on
evaluated_permission; bound idle by server stop_reason (<a
href="68a6d7b92a">68a6d7b</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><strong>docs:</strong> small updates to field descriptions (<a
href="e25b885eac">e25b885</a>)</li>
<li><strong>docs:</strong> update model example (<a
href="a33f3f0b7c">a33f3f0</a>)</li>
<li><strong>docs:</strong> updates to descriptions and examples (<a
href="eac4bace32">eac4bac</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9e46760688"><code>9e46760</code></a>
chore: release main</li>
<li><a
href="8d461ea962"><code>8d461ea</code></a>
feat(api): add support for dreaming</li>
<li><a
href="9436e29159"><code>9436e29</code></a>
codegen metadata</li>
<li><a
href="0aec1e748b"><code>0aec1e7</code></a>
feat(tools): gate session tool calls on evaluated_permission; bound idle
by s...</li>
<li><a
href="ac2fc6779d"><code>ac2fc67</code></a>
chore(docs): update model example</li>
<li><a
href="c8af65d6af"><code>c8af65d</code></a>
chore(docs): updates to descriptions and examples</li>
<li><a
href="2a3a9042ab"><code>2a3a904</code></a>
codegen metadata</li>
<li><a
href="57c56c9172"><code>57c56c9</code></a>
chore(docs): small updates to field descriptions</li>
<li>See full diff in <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.110.0...sdk-v0.111.0">compare
view</a></li>
</ul>
</details>
<br />
Updates `eslint` from 10.6.0 to 10.7.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/eslint/releases">eslint's
releases</a>.</em></p>
<blockquote>
<h2>v10.7.0</h2>
<h2>Features</h2>
<ul>
<li><a
href="cf2a9bf2d9"><code>cf2a9bf</code></a>
feat: add errorClassNames option to preserve-caught-error rule (<a
href="https://redirect.github.com/eslint/eslint/issues/21032">#21032</a>)
(sethamus)</li>
<li><a
href="f8b873aae5"><code>f8b873a</code></a>
feat: max-nested-callbacks option for constructor callbacks (<a
href="https://redirect.github.com/eslint/eslint/issues/21063">#21063</a>)
(fnx)</li>
<li><a
href="557fde8bc6"><code>557fde8</code></a>
feat: support computed <code>Number.parseInt</code> member access in
<code>radix</code> rule (<a
href="https://redirect.github.com/eslint/eslint/issues/21041">#21041</a>)
(Pixel)</li>
<li><a
href="0b4a73b658"><code>0b4a73b</code></a>
feat: add suggestions to no-compare-neg-zero (<a
href="https://redirect.github.com/eslint/eslint/issues/21034">#21034</a>)
(den$)</li>
<li><a
href="96cdd427db"><code>96cdd42</code></a>
feat: report invalid signed numeric radix values in <code>radix</code>
rule (<a
href="https://redirect.github.com/eslint/eslint/issues/21030">#21030</a>)
(Pixel)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="3e7bf15e69"><code>3e7bf15</code></a>
fix: apply <code>ignoreClassesWithImplements</code> to class expressions
(<a
href="https://redirect.github.com/eslint/eslint/issues/21069">#21069</a>)
(Pixel)</li>
<li><a
href="0d7d70cf01"><code>0d7d70c</code></a>
fix: insert cause outside wrapping parens in preserve-caught-error (<a
href="https://redirect.github.com/eslint/eslint/issues/21062">#21062</a>)
(Mahin Anowar)</li>
<li><a
href="75ec753226"><code>75ec753</code></a>
fix: handle static template literals in <code>eqeqeq</code> rule (<a
href="https://redirect.github.com/eslint/eslint/issues/21058">#21058</a>)
(Pixel)</li>
<li><a
href="b717a22e24"><code>b717a22</code></a>
fix: prevent <code>eqeqeq</code> null option from reporting non-equality
operators (<a
href="https://redirect.github.com/eslint/eslint/issues/21057">#21057</a>)
(Pixel)</li>
<li><a
href="e35b05f196"><code>e35b05f</code></a>
fix: avoid <code>no-invalid-regexp</code> false positive for shadowed
RegExp (<a
href="https://redirect.github.com/eslint/eslint/issues/21051">#21051</a>)
(Pixel)</li>
<li><a
href="a3172b69c7"><code>a3172b6</code></a>
fix: avoid <code>no-control-regex</code> false positive for shadowed
RegExp (<a
href="https://redirect.github.com/eslint/eslint/issues/21050">#21050</a>)
(Pixel)</li>
<li><a
href="d1f637eca2"><code>d1f637e</code></a>
fix: parenthesize sequence expression operands in no-implicit-coercion
(<a
href="https://redirect.github.com/eslint/eslint/issues/21045">#21045</a>)
(spokodev)</li>
<li><a
href="8859bafb01"><code>8859baf</code></a>
fix: avoid prefer-numeric-literals false positive for shadowed globals
(<a
href="https://redirect.github.com/eslint/eslint/issues/21047">#21047</a>)
(한국)</li>
<li><a
href="a9e5961050"><code>a9e5961</code></a>
fix: use-isnan false positive on shadowed NaN/Number (<a
href="https://redirect.github.com/eslint/eslint/issues/20958">#20958</a>)
(sethamus)</li>
<li><a
href="8a240a7610"><code>8a240a7</code></a>
fix: avoid false positives in <code>radix</code> rule for spread
arguments (<a
href="https://redirect.github.com/eslint/eslint/issues/21044">#21044</a>)
(Pixel)</li>
</ul>
<h2>Documentation</h2>
<ul>
<li><a
href="c30d80801c"><code>c30d808</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="5139800b23"><code>5139800</code></a>
docs: document ESLint migration codemods in v9 and v10 guides (<a
href="https://redirect.github.com/eslint/eslint/issues/20980">#20980</a>)
(Alex Bit)</li>
<li><a
href="04174cbfaa"><code>04174cb</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="026e130408"><code>026e130</code></a>
docs: update semver policy for bug fixes (<a
href="https://redirect.github.com/eslint/eslint/issues/21048">#21048</a>)
(Milos Djermanovic)</li>
<li><a
href="9d42fefb0e"><code>9d42fef</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="b23015955c"><code>b230159</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="0129972ba1"><code>0129972</code></a>
docs: correct <code>**/.js</code> glob to <code>**/*.js</code> in config
files guide (<a
href="https://redirect.github.com/eslint/eslint/issues/21036">#21036</a>)
(EduardF1)</li>
</ul>
<h2>Chores</h2>
<ul>
<li><a
href="948937986f"><code>9489379</code></a>
chore: update dependency <code>@eslint/eslintrc</code> to ^3.3.6 (<a
href="https://redirect.github.com/eslint/eslint/issues/21076">#21076</a>)
(renovate[bot])</li>
<li><a
href="81a4774a92"><code>81a4774</code></a>
chore: updates for v9.39.5 release (Jenkins)</li>
<li><a
href="9835414913"><code>9835414</code></a>
chore: enable <code>$ExpectType</code> annotations in all TypeScript
files (<a
href="https://redirect.github.com/eslint/eslint/issues/21071">#21071</a>)
(Francesco Trotta)</li>
<li><a
href="72adf6bd21"><code>72adf6b</code></a>
chore: restrict <code>markdownlint-cli2</code> updates in renovate (<a
href="https://redirect.github.com/eslint/eslint/issues/21067">#21067</a>)
(lumir)</li>
<li><a
href="833ec10fd7"><code>833ec10</code></a>
chore: update dependency prettier to v3.9.4 (<a
href="https://redirect.github.com/eslint/eslint/issues/21061">#21061</a>)
(renovate[bot])</li>
<li><a
href="7ea106ddcb"><code>7ea106d</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/21059">#21059</a>)
(ESLint Bot)</li>
<li><a
href="8fb550e7c2"><code>8fb550e</code></a>
chore: add prettier update commit to <code>.git-blame-ignore-revs</code>
(<a
href="https://redirect.github.com/eslint/eslint/issues/21056">#21056</a>)
(lumir)</li>
<li><a
href="e4e11668ea"><code>e4e1166</code></a>
chore: update dependency prettier to v3.9.1 (<a
href="https://redirect.github.com/eslint/eslint/issues/21055">#21055</a>)
(renovate[bot])</li>
<li><a
href="0493f53f3f"><code>0493f53</code></a>
chore: update prettier to v3.9.0 (<a
href="https://redirect.github.com/eslint/eslint/issues/21054">#21054</a>)
(Pixel)</li>
<li><a
href="1056a996c6"><code>1056a99</code></a>
chore: update dependency prettier to v3.8.5 (<a
href="https://redirect.github.com/eslint/eslint/issues/21049">#21049</a>)
(renovate[bot])</li>
<li><a
href="4d4155df4a"><code>4d4155d</code></a>
ci: run ecosystem tests on pull requests (<a
href="https://redirect.github.com/eslint/eslint/issues/21027">#21027</a>)
(sethamus)</li>
<li><a
href="993539fd45"><code>993539f</code></a>
chore: update dependency <code>@eslint/json</code> to ^2.0.1 (<a
href="https://redirect.github.com/eslint/eslint/issues/21042">#21042</a>)
(renovate[bot])</li>
<li><a
href="53f8b69c15"><code>53f8b69</code></a>
test: add error locations to <code>no-constant-binary-expression</code>
(<a
href="https://redirect.github.com/eslint/eslint/issues/21039">#21039</a>)
(lumir)</li>
<li><a
href="5ab71d52f9"><code>5ab71d5</code></a>
refactor: clean up radix rule internals (<a
href="https://redirect.github.com/eslint/eslint/issues/21015">#21015</a>)
(Pixel)</li>
<li><a
href="a80a9a4614"><code>a80a9a4</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/21035">#21035</a>)
(ESLint Bot)</li>
<li><a
href="7c9a02933c"><code>7c9a029</code></a>
ci: add Node.js 26 to CI (<a
href="https://redirect.github.com/eslint/eslint/issues/20847">#20847</a>)
(lumir)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fabd99bb74"><code>fabd99b</code></a>
10.7.0</li>
<li><a
href="37c5e75949"><code>37c5e75</code></a>
Build: changelog update for 10.7.0</li>
<li><a
href="948937986f"><code>9489379</code></a>
chore: update dependency <code>@eslint/eslintrc</code> to ^3.3.6 (<a
href="https://redirect.github.com/eslint/eslint/issues/21076">#21076</a>)</li>
<li><a
href="81a4774a92"><code>81a4774</code></a>
chore: updates for v9.39.5 release</li>
<li><a
href="3e7bf15e69"><code>3e7bf15</code></a>
fix: apply <code>ignoreClassesWithImplements</code> to class expressions
(<a
href="https://redirect.github.com/eslint/eslint/issues/21069">#21069</a>)</li>
<li><a
href="9835414913"><code>9835414</code></a>
chore: enable <code>$ExpectType</code> annotations in all TypeScript
files (<a
href="https://redirect.github.com/eslint/eslint/issues/21071">#21071</a>)</li>
<li><a
href="cf2a9bf2d9"><code>cf2a9bf</code></a>
feat: add errorClassNames option to preserve-caught-error rule (<a
href="https://redirect.github.com/eslint/eslint/issues/21032">#21032</a>)</li>
<li><a
href="c30d80801c"><code>c30d808</code></a>
docs: Update README</li>
<li><a
href="f8b873aae5"><code>f8b873a</code></a>
feat: max-nested-callbacks option for constructor callbacks (<a
href="https://redirect.github.com/eslint/eslint/issues/21063">#21063</a>)</li>
<li><a
href="72adf6bd21"><code>72adf6b</code></a>
chore: restrict <code>markdownlint-cli2</code> updates in renovate (<a
href="https://redirect.github.com/eslint/eslint/issues/21067">#21067</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/eslint/eslint/compare/v10.6.0...v10.7.0">compare
view</a></li>
</ul>
</details>
<br />
Updates `@anthropic-ai/claude-agent-sdk-darwin-arm64` from 0.3.206 to
0.3.207
Updates `@anthropic-ai/claude-agent-sdk-darwin-x64` from 0.3.206 to
0.3.207
Updates `@anthropic-ai/claude-agent-sdk-linux-arm64` from 0.3.206 to
0.3.207
Updates `@anthropic-ai/claude-agent-sdk-linux-arm64-musl` from 0.3.206
to 0.3.207
Updates `@anthropic-ai/claude-agent-sdk-linux-x64` from 0.3.206 to
0.3.207
Updates `@anthropic-ai/claude-agent-sdk-linux-x64-musl` from 0.3.206 to
0.3.207
Updates `@anthropic-ai/claude-agent-sdk-win32-arm64` from 0.3.206 to
0.3.207
Updates `@anthropic-ai/claude-agent-sdk-win32-x64` from 0.3.206 to
0.3.207
Updates `es-module-lexer` from 2.3.0 to 2.3.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/guybedford/es-module-lexer/releases">es-module-lexer's
releases</a>.</em></p>
<blockquote>
<h2>2.3.1</h2>
<h2>What's Changed</h2>
<ul>
<li>perf: fast native UTF-16 source copy into Wasm memory on Node by <a
href="https://github.com/guybedford"><code>@guybedford</code></a> in <a
href="https://redirect.github.com/guybedford/es-module-lexer/pull/224">guybedford/es-module-lexer#224</a></li>
<li>perf(lexer): gate keywordStart on the next byte for i/c tokens by <a
href="https://github.com/BridgeAR"><code>@BridgeAR</code></a> in <a
href="https://redirect.github.com/guybedford/es-module-lexer/pull/223">guybedford/es-module-lexer#223</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/guybedford/es-module-lexer/compare/2.3.0...2.3.1">https://github.com/guybedford/es-module-lexer/compare/2.3.0...2.3.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="2b2e6209ba"><code>2b2e620</code></a>
2.3.1</li>
<li><a
href="8c21b74b1f"><code>8c21b74</code></a>
perf(lexer): gate keywordStart on the next byte for i/c tokens (<a
href="https://redirect.github.com/guybedford/es-module-lexer/issues/223">#223</a>)</li>
<li><a
href="b8f9d89f9d"><code>b8f9d89</code></a>
perf: fast native UTF-16 source copy into Wasm memory on Node (<a
href="https://redirect.github.com/guybedford/es-module-lexer/issues/224">#224</a>)</li>
<li>See full diff in <a
href="https://github.com/guybedford/es-module-lexer/compare/2.3.0...2.3.1">compare
view</a></li>
</ul>
</details>
<br />
Updates `hono` from 4.12.29 to 4.12.30
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/honojs/hono/releases">hono's
releases</a>.</em></p>
<blockquote>
<h2>v4.12.30</h2>
<h2>What's Changed</h2>
<ul>
<li>chore(benchmark/routers): bump deps in <a
href="https://redirect.github.com/honojs/hono/pull/5107">honojs/hono#5107</a></li>
<li>chore(benchmark): remove not used benchmarks in <a
href="https://redirect.github.com/honojs/hono/pull/5108">honojs/hono#5108</a></li>
<li>chore: update to ts6 in prep for ts7 in <a
href="https://redirect.github.com/honojs/hono/pull/5104">honojs/hono#5104</a></li>
<li>fix(cache): deduplicate Cache-Control directives case-insensitively
in <a
href="https://redirect.github.com/honojs/hono/pull/5025">honojs/hono#5025</a></li>
<li>fix(compress): do not compress 206 Partial Content responses in <a
href="https://redirect.github.com/honojs/hono/pull/5020">honojs/hono#5020</a></li>
<li>fix(client): replaceUrlParam should not match a param that prefixes
another in <a
href="https://redirect.github.com/honojs/hono/pull/5096">honojs/hono#5096</a></li>
<li>fix(method-override): set duplex when forwarding a stream body in
query mode in <a
href="https://redirect.github.com/honojs/hono/pull/5110">honojs/hono#5110</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/honojs/hono/compare/v4.12.29...v4.12.30">https://github.com/honojs/hono/compare/v4.12.29...v4.12.30</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b2ae3a2204"><code>b2ae3a2</code></a>
4.12.30</li>
<li><a
href="e0cdeb0a89"><code>e0cdeb0</code></a>
fix(method-override): set duplex when forwarding a stream body in query
mode ...</li>
<li><a
href="653025e5c3"><code>653025e</code></a>
fix(client): replaceUrlParam should not match a param that prefixes
another (...</li>
<li><a
href="67efb27f7b"><code>67efb27</code></a>
fix(compress): do not compress 206 Partial Content responses (<a
href="https://redirect.github.com/honojs/hono/issues/5020">#5020</a>)</li>
<li><a
href="a48c8bf248"><code>a48c8bf</code></a>
fix(cache): deduplicate Cache-Control directives case-insensitively (<a
href="https://redirect.github.com/honojs/hono/issues/5025">#5025</a>)</li>
<li><a
href="3bb9a0e3a7"><code>3bb9a0e</code></a>
chore: update to ts6 in prep for ts7 (<a
href="https://redirect.github.com/honojs/hono/issues/5104">#5104</a>)</li>
<li><a
href="d3f97caa29"><code>d3f97ca</code></a>
chore(benchmark): remove not used benchmarks (<a
href="https://redirect.github.com/honojs/hono/issues/5108">#5108</a>)</li>
<li><a
href="29a3f73fd5"><code>29a3f73</code></a>
chore(benchmark/routers): bump deps (<a
href="https://redirect.github.com/honojs/hono/issues/5107">#5107</a>)</li>
<li>See full diff in <a
href="https://github.com/honojs/hono/compare/v4.12.29...v4.12.30">compare
view</a></li>
</ul>
</details>
<br />
Updates `postcss` from 8.5.16 to 8.5.19
<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.19</h2>
<ul>
<li>Fixed cleaning <code>before</code> for new nodes inserted to
<code>Root</code> (by <a
href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a>).</li>
</ul>
<h2>8.5.18</h2>
<ul>
<li>Restricted loading previous source maps file to the
<code>opts.from</code> folder for security reasons (use <code>unsafeMap:
true</code> to disable the check).</li>
</ul>
<h2>8.5.17</h2>
<ul>
<li>Fixed <code>Maximum call stack size exceeded</code> error.</li>
<li>Fixed Prototype hijacking for <code>postcss.fromJSON()</code>.</li>
<li>Fixed <code>Input#origin()</code> for unmapped end position (by <a
href="https://github.com/chatman-media"><code>@chatman-media</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.19</h2>
<ul>
<li>Fixed cleaning <code>before</code> for new nodes inserted to
<code>Root</code> (by <a
href="https://github.com/MahinAnowar"><code>@MahinAnowar</code></a>).</li>
</ul>
<h2>8.5.18</h2>
<ul>
<li>Restricted loading previous source maps file to the
<code>opts.from</code> folder for security reasons (use <code>unsafeMap:
true</code> to disable the check).</li>
</ul>
<h2>8.5.17</h2>
<ul>
<li>Fixed <code>Maximum call stack size exceeded</code> error.</li>
<li>Fixed Prototype hijacking for <code>postcss.fromJSON()</code>.</li>
<li>Fixed <code>Input#origin()</code> for unmapped end position (by <a
href="https://github.com/chatman-media"><code>@chatman-media</code></a>).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9543b22769"><code>9543b22</code></a>
Release 8.5.19 version</li>
<li><a
href="3d13bf9360"><code>3d13bf9</code></a>
Fix CI on Windows too</li>
<li><a
href="00d0dd2322"><code>00d0dd2</code></a>
Keep explicitly set raws.before when inserting nodes into root (<a
href="https://redirect.github.com/postcss/postcss/issues/2111">#2111</a>)</li>
<li><a
href="7a05b33e7a"><code>7a05b33</code></a>
Temporary fix CI</li>
<li><a
href="4c0d194c13"><code>4c0d194</code></a>
Release 8.5.18 version</li>
<li><a
href="92b4e7891e"><code>92b4e78</code></a>
Update dependencies</li>
<li><a
href="95663d3eb7"><code>95663d3</code></a>
Limit where source map can be loaded for security reasons</li>
<li><a
href="74e25ae9f4"><code>74e25ae</code></a>
Release 8.5.17 version</li>
<li><a
href="d1518afd5a"><code>d1518af</code></a>
Fix Maximum call stack size exceeded error</li>
<li><a
href="2421312ffe"><code>2421312</code></a>
Fix linter</li>
<li>Additional commits viewable in <a
href="https://github.com/postcss/postcss/compare/8.5.16...8.5.19">compare
view</a></li>
</ul>
</details>
<br />
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
</details>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
## Problem
`session/prompt` settled at the turn's terminal `result`, but a turn
that launched an **async subagent** is not done at that point.
Everything after settlement — the subagent's streamed tool calls, the
model's promised task-notification followup summary, and any
`session/request_permission` the subagent raises — landed **outside any
turn**. Some clients stops consuming updates at the prompt response, so
the output was silently lost and the permission request deadlocked on an
RPC nobody answers.
Reported as #864 (no signal for the post-turn activity), #865
(background tasks not trackable), and #866 (end-to-end field report
incl. the permission deadlock).
## What I verified before designing this
Driving the adapter over real ACP stdio against the bundled CLI
(2.1.206) with `emitRawSDKMessages` on showed that the SDK's trailing
`session_state_changed: idle` **does not wait for background agents** —
it follows the user result immediately, while the subagent is still
running, and the session then cycles:
```
user result → idle → (subagent works) → task_notification → followup turn → result(origin: task-notification) → idle
```
So the old #463-era "settle at idle" design would **not** fix this on
current CLIs (and plain re-adopting it would still trade away #773). The
hold has to be keyed on the live-subagent set and span those idle
cycles.
## Fix
A user turn whose terminal result arrives while subagents **it spawned**
are still live stores its outcome on `Turn.deferredSettle` instead of
settling. The prompt stays pending, so all of the subagent's output and
permission requests arrive inside a live turn. It settles with the
stored stop reason/usage:
- at the **task-notification followup's terminal result** — the promised
summary has fully streamed by then (the common case), or
- at an **idle with none of its subagents left**, when no followup
comes, or
- earlier, via `session/cancel` or the next prompt's echo hand-off — a
long-running subagent never holds the prompt hostage, and the hand-off
reports the recorded stop reason instead of rewriting it to `end_turn`.
Tracking: `Turn.spawnedTaskIds` ∩ `session.liveSubagentTasks`, fed by
`task_started` (only entries with `subagent_type`; background shells are
deliberately excluded — a dev server outlives every turn), pruned at
`task_notification`/terminal `task_updated`, and reconciled against
`background_tasks_changed`'s replace-semantics payload so a lost bookend
can't wedge the hold. A spawn during the held-open window (an agent
chain) extends the hold naturally.
Turns that spawned nothing (or whose subagents finished in-turn) still
settle at their result — the #773 responsiveness is untouched.
## Live verification (adapter on real stdio, CLI 2.1.206, temp cwd)
Prompt: *"launch a background agent to read the two files and create
summary.txt, then end your turn saying you'll report back"*:
```
[ 15.72] raw: result success ← user result; subagent live → HELD
[ 15.72] raw: session_state_changed idle ← immediate idle survives the hold
[ 17.50] update: tool_call Read hello.txt ← subagent work, in-turn
[ 21.39] update: tool_call Write summary.txt ← in-turn
[ 24.17] raw: task_notification completed
[ 34.35] update: agent_message_chunk "The background agent finished. It created summary.txt…" ← promised summary, in-turn
[ 35.70] raw: result success (origin task-notification)
[ 35.70] PROMPT RESOLVED end_turn, usage = user turn's own tokens
```
No-regression check: a plain `"say hello"` prompt resolves the instant
its result lands (2.09s, zero added latency).
## Hardening from the adversarial review pass
A high-effort review (8 finder angles) of the change surfaced three
confirmed defects, each fixed with a regression test that fails pre-fix:
- **cancel() of a held turn stalled ~30s**: the session is already idle
during the hold, so the interrupt may never emit the trailing idle the
cancelled-settle path waited on. cancel() now settles a deferred turn
immediately (its result is already in hand); this also prevents the
force-cancel backstop from seeding a phantom orphan for a result that
already passed.
- **A followup's `is_error` / "Please run /login" could reject a held
user turn** whose own result was a success (reachable with parallel
subagents). Followup results now never touch the user-turn lifecycle.
- **The followup's own trailing idle was un-owed**: settling at the
followup result unblocks the client at exactly the moment that idle can
lag past the next prompt's echo — which would have been read as the
fresh turn ending without a result (#825 false-fail). All results now
record their trailer debt.
A second review round on the post-merge state (after resolving conflicts
with #858) found and fixed five more: an echo-less command (`/context`)
during a hold overwrote the held turn's outcome and hung
(ensureActiveTurn now hands the held turn off and promotes the head);
the refusal lane bypassed the deferral gate (result-time settles now
route through a shared `settleOrDefer`); cancel()'s inline settle
couldn't record the interrupt trailer's owed-idle debt (the counter
moved onto the Session) and skipped the backstop disarm; `failAllTurns`
rejected a held turn whose answer had already streamed (now resolves the
stored outcome, like stream-done); and a followup result inside a cancel
window skipped the trailer count. Settling at a followup result also now
closes the #453 delivery stretch so a following replayed turn's fallback
isn't suppressed.
Known residuals, deliberately accepted: a subagent whose settle bookends
are all lost parks the held turn until `session/cancel` or the next
prompt (same rescue contract as the adapter's other wedge classes); a
wake whose origin can't be attributed (the SDK's `origin` carries no
task id) can settle the turn one followup early, degrading to today's
behavior, never worse.
## Verification
Unit: 530 tests green; the deferral/cancel/false-fail tests were each
run against the pre-fix adapter and fail there. Live (real ACP stdio,
CLI 2.1.206): held turn with in-turn subagent output + followup summary,
resolution at the followup's result; plain prompts resolve instantly at
their result.
## Out of scope (follow-ups)
- A background **shell**'s exit waking the model between turns remains
an out-of-turn episode — there is no turn to hold for it without
blocking every prompt behind a dev server. Same for clients that want a
session-level active/idle or background-task level signal (#864/#865's
additive asks): both raw signals are already available today via
`_meta.claudeCode.emitRawSDKMessages` → `_claude/sdkMessage` ext
notifications.
- Flipping the spawning `Task` tool call's status at terminal
`task_updated` (#865's optional ask).
A third review round on the consolidated state fixed: the reconciliation
deleting live sync-subagent attribution entries (the level's universe is
background-only — absent subagent entries are now kept but marked
`endedPerLevel` so holds stop waiting on them);
peer/coordinator/observer-origin results being treated as the user's
turn (now gated via `AUTONOMOUS_RESULT_ORIGINS`, preserving
channel-origin behavior); `emittedAssistantText` moving onto the Session
so every held-turn settle lane closes the #453 delivery stretch (with
the snapshot taken after the held-turn hand-off); the interrupt-trailer
pre-count gated on a running cycle so idle-cancels can't mask future
#825 detections; and `turnAwaitingSubagents` now reading `isSubagent` as
defense in depth for the shells-never-defer contract. Plus
`isHeldOpen()`/`disarmForceCancel()` deduplicating the hold predicate
and backstop disarm.
(An earlier follow-up — folding the attribution map and the
live-subagent set into one task registry — is now done in this PR:
`liveBackgroundTasks` keyed by task id, so the
`background_tasks_changed` reconciliation heals both concerns and future
terminal paths can't prune one but not the other.)
Fixes#866. Addresses the settlement half of #864 / #865.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.15 to 3.3.16.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ai/nanoid/releases">nanoid's
releases</a>.</em></p>
<blockquote>
<h2>3.3.16</h2>
<ul>
<li>Fixed infinite loop on negative size (by <a
href="https://github.com/greymoth-jp"><code>@greymoth-jp</code></a>).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ai/nanoid/blob/main/CHANGELOG.md">nanoid's
changelog</a>.</em></p>
<blockquote>
<h2>3.3.16</h2>
<ul>
<li>Fixed infinite loop on negative size (by <a
href="https://github.com/greymoth-jp"><code>@greymoth-jp</code></a>).</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9760e11275"><code>9760e11</code></a>
Release 3.3.16 version</li>
<li><a
href="e835c9b71e"><code>e835c9b</code></a>
fix(non-secure): clamp negative size to prevent infinite loop (<a
href="https://redirect.github.com/ai/nanoid/issues/601">#601</a>)</li>
<li><a
href="96dd086eb2"><code>96dd086</code></a>
Update CI action</li>
<li><a
href="ba0bc3b6b9"><code>ba0bc3b</code></a>
Do not create latest release for v3</li>
<li>See full diff in <a
href="https://github.com/ai/nanoid/compare/3.3.15...3.3.16">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Fixes#453.
On a cache-replayed turn the CLI can answer on the `result` alone:
output_tokens is 0, no `stream_event` deltas, and no consolidated
`assistant` message. The result handler never forwarded that text, so
the client rendered an empty turn.
The check suggested in the issue (output_tokens === 0 and a non-empty
result) isn't enough by itself. I tried it: it emits the answer twice
when the consolidated `assistant` message already delivered it,
including the case where the echo lands mid-message and the consolidated
message dedupes to nothing, and it forwards a background
task-notification followup's output into the user's turn.
So this tracks whether any top-level assistant text already reached the
client since the last user-turn result, and forwards `message.result`
only when none did and the turn isn't a task-notification followup. The
direct emitters in the `status` handler (compaction notices, local
command output) set the flag too, since they bypass the forwarding
loops. `compact_boundary` doesn't, because it only sends a usage update.
Tests: six added to the "assembled assistant text fallback" block.
Reverting the source change fails "forwards the result text when nothing
else carried it"; the other five pin the guards, and they catch the
naive version, which double-emits and leaks task-notification output.
Full suite: 501 passed, 2 failed, and both failures reproduce on a clean
main (Windows path separator assertions in the tool-conversion tests).
eslint, tsc --noEmit, and prettier --check are clean.
---------
Co-authored-by: Josh Kappler <boffytv@gmail.com>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
## Why
Tool-use `content_block_start` events arrive before their JSON input.
This leaves pending calls with generic labels such as `Read File` or
`Terminal`; long-running and concurrent calls can remain
indistinguishable in clients while they execute.
Anthropic specifies `input_json_delta.partial_json` as arbitrary string
fragments, so delta boundaries cannot be assumed to align with fields or
JSON values.
## What changed
- Buffer `input_json_delta` fragments per parent message and
content-block index.
- Recover completed top-level fields while the overall JSON is still
incomplete.
- Refine the existing ACP tool call immediately when distinguishing
fields such as `file_path`, `command`, `query`, `pattern`, `url`, or
`description` become available.
- Continue refining as later fields arrive, while keeping the early
pending lifecycle and cleaning incomplete buffers at block/message
boundaries.
- Avoid publishing ambiguous numeric suffixes (`10` may still become
`100` or `10.5`) until a delimiter arrives.
## Test coverage
Parameterized coverage now includes Agent/Task, Bash, Read/Write/Edit,
Glob/Grep, WebFetch/WebSearch, ReportFindings, ExitPlanMode,
AskUserQuestion, Other, custom MCP calls, TodoWrite plan updates, and
intentionally suppressed TaskCreate/Update/List/Get calls. Edge cases
cover arbitrary field splits, unfinished strings, escaped quotes and
commas, numbers, booleans, null, arrays, nested objects, and all three
tool block types (`tool_use`, `server_tool_use`, `mcp_tool_use`).
## Validation
- `npm run build`
- `npm run test:run` (535 passed, 20 skipped)
- `npm run check`
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Bumps the minor group with 11 updates:
| Package | From | To |
| --- | --- | --- |
|
[@anthropic-ai/claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk-typescript)
| `0.3.205` | `0.3.206` |
| [prettier](https://github.com/prettier/prettier) | `3.9.4` | `3.9.5` |
| @anthropic-ai/claude-agent-sdk-darwin-arm64 | `0.3.205` | `0.3.206` |
| @anthropic-ai/claude-agent-sdk-darwin-x64 | `0.3.205` | `0.3.206` |
| @anthropic-ai/claude-agent-sdk-linux-arm64 | `0.3.205` | `0.3.206` |
| @anthropic-ai/claude-agent-sdk-linux-arm64-musl | `0.3.205` |
`0.3.206` |
| @anthropic-ai/claude-agent-sdk-linux-x64 | `0.3.205` | `0.3.206` |
| @anthropic-ai/claude-agent-sdk-linux-x64-musl | `0.3.205` | `0.3.206`
|
| @anthropic-ai/claude-agent-sdk-win32-arm64 | `0.3.205` | `0.3.206` |
| @anthropic-ai/claude-agent-sdk-win32-x64 | `0.3.205` | `0.3.206` |
| [hono](https://github.com/honojs/hono) | `4.12.28` | `4.12.29` |
Updates `@anthropic-ai/claude-agent-sdk` from 0.3.205 to 0.3.206
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/claude-agent-sdk-typescript/releases">@anthropic-ai/claude-agent-sdk's
releases</a>.</em></p>
<blockquote>
<h2>v0.3.206</h2>
<h2>What's changed</h2>
<ul>
<li>Added <code>command_lifecycle</code> frames to stream-json and SDK
sessions, reporting each uuid-stamped message's terminal state
(<code>queued</code>/<code>started</code>/<code>completed</code>/<code>cancelled</code>/<code>discarded</code>);
zero-API results no longer report stale
<code>duration_api_ms</code></li>
</ul>
<h2>Update</h2>
<pre lang="sh"><code>npm install @anthropic-ai/claude-agent-sdk@0.3.206
# or
yarn add @anthropic-ai/claude-agent-sdk@0.3.206
# or
pnpm add @anthropic-ai/claude-agent-sdk@0.3.206
# or
bun add @anthropic-ai/claude-agent-sdk@0.3.206
</code></pre>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/claude-agent-sdk-typescript/blob/main/CHANGELOG.md">@anthropic-ai/claude-agent-sdk's
changelog</a>.</em></p>
<blockquote>
<h2>0.3.206</h2>
<ul>
<li>Added <code>command_lifecycle</code> frames to stream-json and SDK
sessions, reporting each uuid-stamped message's terminal state
(<code>queued</code>/<code>started</code>/<code>completed</code>/<code>cancelled</code>/<code>discarded</code>);
zero-API results no longer report stale
<code>duration_api_ms</code></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9fc7ea5ff6"><code>9fc7ea5</code></a>
chore: Update CHANGELOG.md</li>
<li>See full diff in <a
href="https://github.com/anthropics/claude-agent-sdk-typescript/compare/v0.3.205...v0.3.206">compare
view</a></li>
</ul>
</details>
<br />
Updates `prettier` from 3.9.4 to 3.9.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/prettier/prettier/releases">prettier's
releases</a>.</em></p>
<blockquote>
<h2>3.9.5</h2>
<p>🔗 <a
href="https://github.com/prettier/prettier/blob/3.9.5/CHANGELOG.md#395">Changelog</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/prettier/prettier/blob/main/CHANGELOG.md">prettier's
changelog</a>.</em></p>
<blockquote>
<h1>3.9.5</h1>
<p><a
href="https://github.com/prettier/prettier/compare/3.9.4...3.9.5">diff</a></p>
<h4>Markdown: Cap ordered list mark at 999,999,999 (<a
href="https://redirect.github.com/prettier/prettier/pull/19351">#19351</a>
by <a href="https://github.com/tats-u"><code>@tats-u</code></a>)</h4>
<p>CommonMark parsers only support ordered list item numbers up to
999,999,999.</p>
<p>With this change, Prettier now caps the ordered list item number at
999,999,999 to ensure that the output is correctly parsed as an ordered
list by CommonMark parsers. Numbers larger than 999,999,999 are not
parsed as list item numbers and are left unchanged in the output:</p>
<!-- raw HTML omitted -->
<pre lang="markdown"><code><!-- Input -->
999999998. text
999999998. text
999999998. text
999999998. text
<p>1234567890123456789012) text</p>
<p><!-- Prettier 3.9.4 -->
999999998. text
999999999. text
1000000000. text
1000000001. text</p>
<p>1234567890123456789012) text</p>
<p><!-- Prettier 3.9.5 -->
999999998. text
999999999. text
999999999. text
999999999. text</p>
<p>1234567890123456789012) text
</code></pre></p>
<h4>Markdown: Avoid corrupting empty link with title (<a
href="https://redirect.github.com/prettier/prettier/pull/19487">#19487</a>
by <a href="https://github.com/andersk"><code>@andersk</code></a>)</h4>
<p>Do not remove <code><></code> from an inline link or image with
an empty URL and a title, as this removal would change its
interpretation.</p>
<!-- raw HTML omitted -->
<pre lang="md"><code><!-- Input -->
[link](https://github.com/prettier/prettier/blob/main/<>
"title")
<p><!-- Prettier 3.9.4 -->
[link](<a
href="https://github.com/prettier/prettier/blob/main/">https://github.com/prettier/prettier/blob/main/</a>
"title")</p>
<p><!-- Prettier 3.9.5 -->
</tr></table>
</code></pre></p>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b6c7d18068"><code>b6c7d18</code></a>
Release 3.9.5</li>
<li><a
href="cd54ccc728"><code>cd54ccc</code></a>
Avoid corrupting empty Markdown link with title (<a
href="https://redirect.github.com/prettier/prettier/issues/19487">#19487</a>)</li>
<li><a
href="2bb67ce8cd"><code>2bb67ce</code></a>
Preserving comments' <code>placement</code> property (<a
href="https://redirect.github.com/prettier/prettier/issues/19567">#19567</a>)</li>
<li><a
href="91bcac88ec"><code>91bcac8</code></a>
Add more tests for comment-only object type (<a
href="https://redirect.github.com/prettier/prettier/issues/19587">#19587</a>)</li>
<li><a
href="cbee7377a1"><code>cbee737</code></a>
Remove space in empty object type (<a
href="https://redirect.github.com/prettier/prettier/issues/19583">#19583</a>)</li>
<li><a
href="6394c73209"><code>6394c73</code></a>
Align empty module declaration with TS (<a
href="https://redirect.github.com/prettier/prettier/issues/19568">#19568</a>)</li>
<li><a
href="a4e6f7a026"><code>a4e6f7a</code></a>
Prevent the addition of space in <code>type()</code> with <code>+</code>
(<a
href="https://redirect.github.com/prettier/prettier/issues/19516">#19516</a>)</li>
<li><a
href="3d063b57b1"><code>3d063b5</code></a>
Ignore dangling comments when checking type parameter comments (<a
href="https://redirect.github.com/prettier/prettier/issues/19572">#19572</a>)</li>
<li><a
href="908503e9ee"><code>908503e</code></a>
Handle dangling comments in <code>SwitchStatement</code> (<a
href="https://redirect.github.com/prettier/prettier/issues/19581">#19581</a>)</li>
<li><a
href="943a475c35"><code>943a475</code></a>
Angular: Support expression for exhaustive typechecking (<a
href="https://redirect.github.com/prettier/prettier/issues/19571">#19571</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/prettier/prettier/compare/3.9.4...3.9.5">compare
view</a></li>
</ul>
</details>
<br />
Updates `@anthropic-ai/claude-agent-sdk-darwin-arm64` from 0.3.205 to
0.3.206
Updates `@anthropic-ai/claude-agent-sdk-darwin-x64` from 0.3.205 to
0.3.206
Updates `@anthropic-ai/claude-agent-sdk-linux-arm64` from 0.3.205 to
0.3.206
Updates `@anthropic-ai/claude-agent-sdk-linux-arm64-musl` from 0.3.205
to 0.3.206
Updates `@anthropic-ai/claude-agent-sdk-linux-x64` from 0.3.205 to
0.3.206
Updates `@anthropic-ai/claude-agent-sdk-linux-x64-musl` from 0.3.205 to
0.3.206
Updates `@anthropic-ai/claude-agent-sdk-win32-arm64` from 0.3.205 to
0.3.206
Updates `@anthropic-ai/claude-agent-sdk-win32-x64` from 0.3.205 to
0.3.206
Updates `hono` from 4.12.28 to 4.12.29
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/honojs/hono/releases">hono's
releases</a>.</em></p>
<blockquote>
<h2>v4.12.29</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(client): merge function headers with per-request headers by <a
href="https://github.com/yusukebe"><code>@yusukebe</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/5092">honojs/hono#5092</a></li>
<li>chore: fix no-op tsc in test script by <a
href="https://github.com/yusukebe"><code>@yusukebe</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/5093">honojs/hono#5093</a></li>
<li>fix(lambda-edge): resolve the handler with the value passed to the
callback by <a
href="https://github.com/yusukebe"><code>@yusukebe</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/5094">honojs/hono#5094</a></li>
<li>docs(language): add JSDoc <a
href="https://github.com/example"><code>@example</code></a> to
languageDetector by <a
href="https://github.com/codebybilal18"><code>@codebybilal18</code></a>
in <a
href="https://redirect.github.com/honojs/hono/pull/5081">honojs/hono#5081</a></li>
<li>test(workerd): add <code>compatibilityDate</code> by <a
href="https://github.com/yusukebe"><code>@yusukebe</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/5100">honojs/hono#5100</a></li>
<li>fix(lambda-edge): base64 encode content-encoded response bodies by
<a href="https://github.com/yusukebe"><code>@yusukebe</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/5099">honojs/hono#5099</a></li>
<li>fix(aws-lambda): treat any non-identity content-encoding as binary
by <a href="https://github.com/yusukebe"><code>@yusukebe</code></a> in
<a
href="https://redirect.github.com/honojs/hono/pull/5101">honojs/hono#5101</a></li>
<li>fix(types): strip extra properties from array types in JSONParsed by
<a
href="https://github.com/Arman-Luthra"><code>@Arman-Luthra</code></a>
in <a
href="https://redirect.github.com/honojs/hono/pull/5103">honojs/hono#5103</a></li>
<li>fix(trie-router): match empty wildcard remainder after regexp param
by <a href="https://github.com/usualoma"><code>@usualoma</code></a> in
<a
href="https://redirect.github.com/honojs/hono/pull/5102">honojs/hono#5102</a></li>
<li>fix(etag): treat If-None-Match: <code>*</code> as a match by <a
href="https://github.com/yusukebe"><code>@yusukebe</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/5084">honojs/hono#5084</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/codebybilal18"><code>@codebybilal18</code></a>
made their first contribution in <a
href="https://redirect.github.com/honojs/hono/pull/5081">honojs/hono#5081</a></li>
<li><a
href="https://github.com/Arman-Luthra"><code>@Arman-Luthra</code></a>
made their first contribution in <a
href="https://redirect.github.com/honojs/hono/pull/5103">honojs/hono#5103</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/honojs/hono/compare/v4.12.28...v4.12.29">https://github.com/honojs/hono/compare/v4.12.28...v4.12.29</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="cda1af2002"><code>cda1af2</code></a>
4.12.29</li>
<li><a
href="2126289c15"><code>2126289</code></a>
fix(etag): treat If-None-Match: <code>*</code> as a match (<a
href="https://redirect.github.com/honojs/hono/issues/5084">#5084</a>)</li>
<li><a
href="0fc7ffc949"><code>0fc7ffc</code></a>
fix(trie-router): match empty wildcard remainder after regexp param (<a
href="https://redirect.github.com/honojs/hono/issues/5102">#5102</a>)</li>
<li><a
href="ab590e4ec8"><code>ab590e4</code></a>
fix(types): strip extra properties from array types in JSONParsed (<a
href="https://redirect.github.com/honojs/hono/issues/5103">#5103</a>)</li>
<li><a
href="b93a2547a3"><code>b93a254</code></a>
fix(aws-lambda): treat any non-identity content-encoding as binary (<a
href="https://redirect.github.com/honojs/hono/issues/5101">#5101</a>)</li>
<li><a
href="6217f4b74c"><code>6217f4b</code></a>
fix(lambda-edge): base64 encode content-encoded response bodies (<a
href="https://redirect.github.com/honojs/hono/issues/5099">#5099</a>)</li>
<li><a
href="ba89e973c7"><code>ba89e97</code></a>
test(workerd): add <code>compatibilityDate</code> (<a
href="https://redirect.github.com/honojs/hono/issues/5100">#5100</a>)</li>
<li><a
href="46557ef820"><code>46557ef</code></a>
docs(language): add JSDoc <a
href="https://github.com/example"><code>@example</code></a> to
languageDetector (<a
href="https://redirect.github.com/honojs/hono/issues/5081">#5081</a>)</li>
<li><a
href="24547a6ed5"><code>24547a6</code></a>
fix(lambda-edge): resolve the handler with the value passed to the
callback (...</li>
<li><a
href="9c6ccd76f1"><code>9c6ccd7</code></a>
chore: fix no-op tsc in test script (<a
href="https://redirect.github.com/honojs/hono/issues/5093">#5093</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/honojs/hono/compare/v4.12.28...v4.12.29">compare
view</a></li>
</ul>
</details>
<br />
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
</details>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
## Summary
This makes streamed text/thinking chunk handling defensive when gateways
emit empty or malformed delta payloads.
- Guard `text_delta.text` and `thinking_delta.thinking` before reading
`.length`
- Skip missing/non-string text or thinking content the same way empty
chunks are already skipped
- Add regression coverage for a missing `thinking` delta before a real
text delta
- Add direct `toAcpNotifications` coverage for missing/non-string text
and thinking chunks
## Why
The adapter already skips empty thinking chunks, but some
Anthropic-compatible gateways can emit signature-only or omitted
thinking deltas where `thinking` is absent rather than an empty string.
In that case the adapter currently throws:
```text
Cannot read properties of undefined (reading 'length')
```
That aborts the ACP session even though the following text chunks are
valid.
This change keeps the existing behavior for valid chunks, while treating
missing/non-string chunk text as empty content.
## Test Plan
- `npm run check`
- `npm test -- --run`
- `npm run build`
Also verified manually through a VibeAround Web Chat flow using Claude
Code ACP with an Anthropic-compatible custom endpoint; the session
completed and returned a normal assistant response.
---------
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
## Why this is needed
`toAcpNotifications` can emit an `agent_message_chunk` whose content is
an empty string. This happens in two situations:
1. **Streamed text deltas** — the `text` / `text_delta` case builds the
update unconditionally from `chunk.text`, and the Claude Agent SDK can
stream zero-length text deltas (for example, an empty trailing assistant
block at the end of a turn).
2. **Full-string content** — the string-content path emits a chunk even
when the string is empty.
An empty message chunk carries no information, so at best it is noise.
At worst it breaks clients: the ACP spec does not forbid empty content,
so clients handle it inconsistently and some throw. In JetBrains Air the
frontend event consumer throws on an empty-content `agent_message_chunk`
(`Failed to handle agent event`); once that happens the transcript is
**frozen for the rest of the turn** — no further updates render and
queued prompts are never dispatched. In practice this reproduced
repeatedly around image reads and end-of-turn, and the only recovery was
restarting the IDE.
Because the adapter is client-agnostic, this affects any ACP client that
is strict about chunk content, not a single editor — so the correct
place to fix it is here, in the adapter, rather than working around it
in each client.
## Fix
Do not emit empty content. Both call sites are guarded, mirroring the
empty-`thinking` guard that already exists a few lines below in the same
function, so behavior is consistent across content types:
- `text` / `text_delta`: only build the update when `chunk.text.length >
0`;
- string content: return `[]` when the string is empty.
The change is intentionally minimal and conservative — no information is
lost, and non-empty chunks are entirely unaffected.
## Tests
Three unit tests added on `toAcpNotifications`:
- empty string content → no notifications emitted;
- non-empty string content → still emitted unchanged;
- a stream containing an empty text block followed by a non-empty one →
only the non-empty block is emitted.
Full suite green (476 passing); eslint and prettier clean.
Bumps the minor group with 11 updates:
| Package | From | To |
| --- | --- | --- |
|
[@anthropic-ai/claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk-typescript)
| `0.3.198` | `0.3.199` |
|
[@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript)
| `0.109.1` | `0.110.0` |
| @anthropic-ai/claude-agent-sdk-darwin-arm64 | `0.3.198` | `0.3.199` |
| @anthropic-ai/claude-agent-sdk-darwin-x64 | `0.3.198` | `0.3.199` |
| @anthropic-ai/claude-agent-sdk-linux-arm64 | `0.3.198` | `0.3.199` |
| @anthropic-ai/claude-agent-sdk-linux-arm64-musl | `0.3.198` |
`0.3.199` |
| @anthropic-ai/claude-agent-sdk-linux-x64 | `0.3.198` | `0.3.199` |
| @anthropic-ai/claude-agent-sdk-linux-x64-musl | `0.3.198` | `0.3.199`
|
| @anthropic-ai/claude-agent-sdk-win32-arm64 | `0.3.198` | `0.3.199` |
| @anthropic-ai/claude-agent-sdk-win32-x64 | `0.3.198` | `0.3.199` |
| [picomatch](https://github.com/micromatch/picomatch) | `4.0.4` |
`4.0.5` |
Updates `@anthropic-ai/claude-agent-sdk` from 0.3.198 to 0.3.199
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/claude-agent-sdk-typescript/releases">@anthropic-ai/claude-agent-sdk's
releases</a>.</em></p>
<blockquote>
<h2>v0.3.199</h2>
<h2>What's changed</h2>
<ul>
<li>Added <code>requestId</code> to <code>canUseTool</code> callback
options for correlating out-of-band permission responses, and support
for returning <code>null</code> to suppress the SDK's automatic control
response</li>
<li>Added <code>blocked</code> field to <code>workflow_agent</code>
progress events indicating when an agent was blocked by the auto-mode
safety classifier</li>
<li>Added <code>mode:"mask"</code> and per-credential
<code>injectHosts</code> to <code>sandbox.credentials</code> settings
types for injecting masked credentials into sandboxed commands</li>
</ul>
<h2>Update</h2>
<pre lang="sh"><code>npm install @anthropic-ai/claude-agent-sdk@0.3.199
# or
yarn add @anthropic-ai/claude-agent-sdk@0.3.199
# or
pnpm add @anthropic-ai/claude-agent-sdk@0.3.199
# or
bun add @anthropic-ai/claude-agent-sdk@0.3.199
</code></pre>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/claude-agent-sdk-typescript/blob/main/CHANGELOG.md">@anthropic-ai/claude-agent-sdk's
changelog</a>.</em></p>
<blockquote>
<h2>0.3.199</h2>
<ul>
<li>Added <code>requestId</code> to <code>canUseTool</code> callback
options for correlating out-of-band permission responses, and support
for returning <code>null</code> to suppress the SDK's automatic control
response</li>
<li>Added <code>blocked</code> field to <code>workflow_agent</code>
progress events indicating when an agent was blocked by the auto-mode
safety classifier</li>
<li>Added <code>mode:"mask"</code> and per-credential
<code>injectHosts</code> to <code>sandbox.credentials</code> settings
types for injecting masked credentials into sandboxed commands</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="a0c02d6d99"><code>a0c02d6</code></a>
chore: Update CHANGELOG.md</li>
<li>See full diff in <a
href="https://github.com/anthropics/claude-agent-sdk-typescript/compare/v0.3.198...v0.3.199">compare
view</a></li>
</ul>
</details>
<br />
Updates `@anthropic-ai/sdk` from 0.109.1 to 0.110.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/anthropic-sdk-typescript/releases">@anthropic-ai/sdk's
releases</a>.</em></p>
<blockquote>
<h2>sdk: v0.110.0</h2>
<h2>0.110.0 (2026-07-02)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.109.1...sdk-v0.110.0">sdk-v0.109.1...sdk-v0.110.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> add agent-memory-2026-07-22 beta header (<a
href="a470e10aaa">a470e10</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/anthropic-sdk-typescript/blob/main/CHANGELOG.md">@anthropic-ai/sdk's
changelog</a>.</em></p>
<blockquote>
<h2>0.110.0 (2026-07-02)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.109.1...sdk-v0.110.0">sdk-v0.109.1...sdk-v0.110.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> add agent-memory-2026-07-22 beta header (<a
href="a470e10aaa">a470e10</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="4f2eb80719"><code>4f2eb80</code></a>
chore: release main (<a
href="https://redirect.github.com/anthropics/anthropic-sdk-typescript/issues/1107">#1107</a>)</li>
<li>See full diff in <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.109.1...sdk-v0.110.0">compare
view</a></li>
</ul>
</details>
<br />
Updates `@anthropic-ai/claude-agent-sdk-darwin-arm64` from 0.3.198 to
0.3.199
Updates `@anthropic-ai/claude-agent-sdk-darwin-x64` from 0.3.198 to
0.3.199
Updates `@anthropic-ai/claude-agent-sdk-linux-arm64` from 0.3.198 to
0.3.199
Updates `@anthropic-ai/claude-agent-sdk-linux-arm64-musl` from 0.3.198
to 0.3.199
Updates `@anthropic-ai/claude-agent-sdk-linux-x64` from 0.3.198 to
0.3.199
Updates `@anthropic-ai/claude-agent-sdk-linux-x64-musl` from 0.3.198 to
0.3.199
Updates `@anthropic-ai/claude-agent-sdk-win32-arm64` from 0.3.198 to
0.3.199
Updates `@anthropic-ai/claude-agent-sdk-win32-x64` from 0.3.198 to
0.3.199
Updates `picomatch` from 4.0.4 to 4.0.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/micromatch/picomatch/releases">picomatch's
releases</a>.</em></p>
<blockquote>
<h2>4.0.5</h2>
<h2>What's Changed</h2>
<ul>
<li>fix: preserve all branches when rewriting risky repeated extglobs by
<a href="https://github.com/MerlijnW70"><code>@MerlijnW70</code></a> in
<a
href="https://redirect.github.com/micromatch/picomatch/pull/182">micromatch/picomatch#182</a></li>
<li>fix: honor the windows option when matching basenames by <a
href="https://github.com/MerlijnW70"><code>@MerlijnW70</code></a> in <a
href="https://redirect.github.com/micromatch/picomatch/pull/183">micromatch/picomatch#183</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/MerlijnW70"><code>@MerlijnW70</code></a> made
their first contribution in <a
href="https://redirect.github.com/micromatch/picomatch/pull/182">micromatch/picomatch#182</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/micromatch/picomatch/compare/4.0.4...4.0.5">https://github.com/micromatch/picomatch/compare/4.0.4...4.0.5</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="4f41a8edad"><code>4f41a8e</code></a>
4.0.5</li>
<li><a
href="02cfc1bf91"><code>02cfc1b</code></a>
Update .verb.md and run verb to generate README documentation</li>
<li><a
href="cc52ff6e86"><code>cc52ff6</code></a>
Only run the upload code coverage step for 1 matrix permutation</li>
<li><a
href="6d426d7fe9"><code>6d426d7</code></a>
Allow workflow to continue if the code coverage step to fails</li>
<li><a
href="a00b954c04"><code>a00b954</code></a>
Merge branch 'codeql-coverage'</li>
<li><a
href="96803818ca"><code>9680381</code></a>
Merge pull request <a
href="https://redirect.github.com/micromatch/picomatch/issues/183">#183</a>
from MerlijnW70/fix/matchbase-windows-basename</li>
<li><a
href="648b4f2f13"><code>648b4f2</code></a>
Merge pull request <a
href="https://redirect.github.com/micromatch/picomatch/issues/182">#182</a>
from MerlijnW70/fix/repeated-extglob-drops-branches</li>
<li><a
href="70e6485a54"><code>70e6485</code></a>
Configure code coverage upload for CodeQL</li>
<li><a
href="ab8bc4df81"><code>ab8bc4d</code></a>
fix: honor the windows option when matching basenames</li>
<li><a
href="628930764f"><code>6289307</code></a>
fix: preserve all branches when rewriting risky repeated extglobs</li>
<li>Additional commits viewable in <a
href="https://github.com/micromatch/picomatch/compare/4.0.4...4.0.5">compare
view</a></li>
</ul>
</details>
<br />
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
</details>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>