Compare commits

...

14 Commits

Author SHA1 Message Date
acp-release-bot[bot]
794aa84684 chore(main): release 0.47.0 (#784)
🤖 I have created a release *beep* *boop*
---


##
[0.47.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.46.0...v0.47.0)
(2026-06-17)


### Features

* Update to claude-agent-sdk 0.3.179
([#783](https://github.com/agentclientprotocol/claude-agent-acp/issues/783))
([59a098c](59a098c2b5))


### Bug Fixes

* Duplicate assistant messages in feed
([#785](https://github.com/agentclientprotocol/claude-agent-acp/issues/785))
([12d34e6](12d34e64e5))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: acp-release-bot[bot] <246668977+acp-release-bot[bot]@users.noreply.github.com>
2026-06-17 12:17:10 +02:00
Ben Brandt
12d34e64e5 fix: Duplicate assistant messages in feed (#785) 2026-06-17 12:12:26 +02:00
Ben Brandt
59a098c2b5 feat: Update to claude-agent-sdk 0.3.179 (#783) 2026-06-17 09:04:56 +00:00
acp-release-bot[bot]
c27e6aec90 chore(main): release 0.46.0 (#778)
🤖 I have created a release *beep* *boop*
---


##
[0.46.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.45.1...v0.46.0)
(2026-06-16)


### Features

* Update to claude-agent-sdk 0.3.178
([#777](https://github.com/agentclientprotocol/claude-agent-acp/issues/777))
([58549ff](58549ffe6a))


### Bug Fixes

* Better handle out of turn events
([#780](https://github.com/agentclientprotocol/claude-agent-acp/issues/780))
([4f273a2](4f273a20d8))
* Forward option details in elicitation meta
([#779](https://github.com/agentclientprotocol/claude-agent-acp/issues/779))
([b364059](b3640599ae)),
closes
[#764](https://github.com/agentclientprotocol/claude-agent-acp/issues/764)

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: acp-release-bot[bot] <246668977+acp-release-bot[bot]@users.noreply.github.com>
2026-06-16 21:36:40 +02:00
Ben Brandt
4f273a20d8 fix: Better handle out of turn events (#780)
Claude has a lot of background tasks. If we wait for "idle", some people
experience turns that never end.
If we stop iterating the query after result, people end up with events
that never show up.

Given we already often have session_updates outside of the prompt (and
clients need to handle it for v2 if they aren't already) this moves the
setup to better handle how the SDK gives us this information.

I've been test-driving this build all day and it seems to be working
great.

Closes #773
Closes #679
Closes #435
Closes #497
Closes #688
Closes #630

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 21:33:54 +02:00
Ben Brandt
b3640599ae fix: Forward option details in elicitation meta (#779)
Closes #764
2026-06-16 12:32:54 +00:00
Ben Brandt
58549ffe6a feat: Update to claude-agent-sdk 0.3.178 (#777) 2026-06-16 14:25:08 +02:00
acp-release-bot[bot]
116f06eab1 chore(main): release 0.45.1 (#775)
🤖 I have created a release *beep* *boop*
---


##
[0.45.1](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.45.0...v0.45.1)
(2026-06-16)


### Bug Fixes

* Fix terminal error printing as text instead of terminal output
([#776](https://github.com/agentclientprotocol/claude-agent-acp/issues/776))
([db6eaaf](db6eaaf714))
* Scope custom answers per question
([#774](https://github.com/agentclientprotocol/claude-agent-acp/issues/774))
([d58004a](d58004a348))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: acp-release-bot[bot] <246668977+acp-release-bot[bot]@users.noreply.github.com>
2026-06-16 13:45:49 +02:00
Azad Abdulov
db6eaaf714 fix: Fix terminal error printing as text instead of terminal output (#776)
Co-authored-by: Azad Abdulov <azad.abdulov@jetbrains.com>
2026-06-16 11:43:43 +00:00
Ben Brandt
d58004a348 fix: Scope custom answers per question (#774)
Closes #770

Maps one custom answer per top-level question, not a single global one.
2026-06-16 08:55:52 +00:00
acp-release-bot[bot]
0525e6dacb chore(main): release 0.45.0 (#772)
🤖 I have created a release *beep* *boop*
---


##
[0.45.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.44.0...v0.45.0)
(2026-06-15)


### Features

* **deps-dev:** bump the minor group with 3 updates
([#763](https://github.com/agentclientprotocol/claude-agent-acp/issues/763))
([7de5e4b](7de5e4bcca))
* **deps:** bump @anthropic-ai/claude-agent-sdk to 0.3.177
([#771](https://github.com/agentclientprotocol/claude-agent-acp/issues/771))
([1be5ca5](1be5ca57ee))


### Bug Fixes

* preserve ANTHROPIC_CUSTOM_MODEL_OPTION when availableModels is set
([#768](https://github.com/agentclientprotocol/claude-agent-acp/issues/768))
([cc2885f](cc2885f6a9))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: acp-release-bot[bot] <246668977+acp-release-bot[bot]@users.noreply.github.com>
2026-06-15 18:17:10 +02:00
Luca Dibattista
cc2885f6a9 fix: preserve ANTHROPIC_CUSTOM_MODEL_OPTION when availableModels is set (#768)
## Summary

When `availableModels` is set to a slim list (e.g.
`["sonnet","opus","haiku"]`), the model from
`ANTHROPIC_CUSTOM_MODEL_OPTION` was dropped from `session/new`'s model
picker. Claude Code's CLI keeps it; ACP hid it.

Per the [model-config
docs](https://code.claude.com/docs/en/model-config#add-a-custom-model-option),
`ANTHROPIC_CUSTOM_MODEL_OPTION` adds a custom entry "without replacing
the built-in aliases" and "appears at the bottom of the `/model` picker"
— i.e. it's additive, not subject to the alias allowlist.

Observed under:
* `availableModels: ["sonnet","opus","haiku"]`
* `ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-4-6[1m]`
* `ANTHROPIC_CUSTOM_MODEL_OPTION=claude-opus-4-8[1m]`

| | Default | Sonnet | Opus | Haiku | Opus 4.8 |
|---|---|---|---|---|---|
| CLI picker | ✅ | ✅ | ✅ | ✅ | ✅ (bottom) |
| ACP (before) | ✅ | ✅ | ✅ | ✅ | ❌ |
| ACP (after) | ✅ | ✅ | ✅ | ✅ | ✅ (bottom) |

### Root cause

The SDK returns the custom option as an ordinary entry in
`initializationResult.models` with no flag distinguishing it
(`ModelInfo` has no `custom`/`isCustom` field).
`applyAvailableModelsAllowlist` treats `availableModels` as a strict
allowlist: keep `default`, then keep only SDK models matching an
allowlist entry. The custom value (`claude-opus-4-8[1m]`) matches no
alias, so it's filtered out — diverging from the CLI's additive
treatment.

### Fix

After the allowlist loop, append the model named by
`ANTHROPIC_CUSTOM_MODEL_OPTION` if the SDK surfaced it and it isn't
already present. It's placed last, matching the documented "bottom of
the picker" position, and exempted from the allowlist the same way we
already exempt `default` (the docs note the Default option is likewise
"not affected by `availableModels`").

The entry is preserved in the `ModelInfo[]` (`allowedModels` / session
`modelInfos`), not just the trimmed picker list, so its capability flags
(`supportedEffortLevels`, `supportsAutoMode`) flow to mode gating and
the effort dropdown when the custom model is selected.

Only the allowlist path needs this — when `availableModels` is absent,
ACP uses the full SDK list, which already contains the custom option.

## Test Plan

`src/tests/acp-agent-settings.test.ts` (TDD):
- Custom option preserved at the end of the list when absent from a slim
allowlist, with its name/description intact.
- No duplication when the custom option's exact ID is *also* in
`availableModels`.

No behavior change when `ANTHROPIC_CUSTOM_MODEL_OPTION` is unset or when
`availableModels` is absent.

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

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 15:26:30 +00:00
dependabot[bot]
1be5ca57ee feat(deps): bump @anthropic-ai/claude-agent-sdk to 0.3.177 (#771)
Bumps the minor group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
|
[@agentclientprotocol/sdk](https://github.com/agentclientprotocol/typescript-sdk)
| `0.25.0` | `0.25.1` |
|
[@anthropic-ai/claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk-typescript)
| `0.3.170` | `0.3.177` |
|
[@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)
| `25.9.2` | `25.9.3` |
| [eslint](https://github.com/eslint/eslint) | `10.4.1` | `10.5.0` |
|
[vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest)
| `4.1.8` | `4.1.9` |
| [acorn](https://github.com/acornjs/acorn) | `8.16.0` | `8.17.0` |
| [body-parser](https://github.com/expressjs/body-parser) | `2.2.2` |
`2.3.0` |
| [obug](https://github.com/sxzz/obug) | `2.1.2` | `2.1.3` |


Updates `@agentclientprotocol/sdk` from 0.25.0 to 0.25.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/agentclientprotocol/typescript-sdk/releases">@​agentclientprotocol/sdk's
releases</a>.</em></p>
<blockquote>
<h2>v0.25.1</h2>
<h2><a
href="https://github.com/agentclientprotocol/typescript-sdk/compare/v0.25.0...v0.25.1">0.25.1</a>
(2026-06-13)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>cleanup zod generation (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/170">#170</a>)
(<a
href="be44483cf0">be44483</a>)</li>
<li>Zod type inference errors (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/177">#177</a>)
(<a
href="d9fafa2053">d9fafa2</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/agentclientprotocol/typescript-sdk/blob/main/CHANGELOG.md">@​agentclientprotocol/sdk's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/agentclientprotocol/typescript-sdk/compare/v0.25.0...v0.25.1">0.25.1</a>
(2026-06-13)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>cleanup zod generation (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/170">#170</a>)
(<a
href="be44483cf0">be44483</a>)</li>
<li>Zod type inference errors (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/177">#177</a>)
(<a
href="d9fafa2053">d9fafa2</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="cd8dc79b94"><code>cd8dc79</code></a>
chore(main): release 0.25.1 (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/171">#171</a>)</li>
<li><a
href="d9fafa2053"><code>d9fafa2</code></a>
fix: Zod type inference errors (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/177">#177</a>)</li>
<li><a
href="04c7fd91d3"><code>04c7fd9</code></a>
chore(deps): bump esbuild from 0.28.0 to 0.28.1 (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/176">#176</a>)</li>
<li><a
href="8d9de29709"><code>8d9de29</code></a>
chore(deps): bump actions/checkout from 6.0.2 to 6.0.3 (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/173">#173</a>)</li>
<li><a
href="8ca7903ce1"><code>8ca7903</code></a>
chore(deps): bump crate-ci/typos from 1.47.0 to 1.47.2 (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/174">#174</a>)</li>
<li><a
href="1c6c0b80f4"><code>1c6c0b8</code></a>
chore(deps-dev): bump <code>@​types/node</code> in the minor group (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/175">#175</a>)</li>
<li><a
href="be44483cf0"><code>be44483</code></a>
fix: cleanup zod generation (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/170">#170</a>)</li>
<li>See full diff in <a
href="https://github.com/agentclientprotocol/typescript-sdk/compare/v0.25.0...v0.25.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `@anthropic-ai/claude-agent-sdk` from 0.3.170 to 0.3.177
<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.177</h2>
<h2>What's changed</h2>
<ul>
<li>Updated to parity with Claude Code v2.1.177</li>
</ul>
<h2>Update</h2>
<pre lang="sh"><code>npm install @anthropic-ai/claude-agent-sdk@0.3.177
# or
yarn add @anthropic-ai/claude-agent-sdk@0.3.177
# or
pnpm add @anthropic-ai/claude-agent-sdk@0.3.177
# or
bun add @anthropic-ai/claude-agent-sdk@0.3.177
</code></pre>
<h2>v0.3.176</h2>
<h2>What's changed</h2>
<ul>
<li>Fixed turn <code>result</code> messages being dropped when multiple
turns complete while a background agent or workflow is running</li>
<li>Fixed background agent, remote agent, and MCP task state not being
restored when resuming a session via the SDK</li>
</ul>
<h2>Update</h2>
<pre lang="sh"><code>npm install @anthropic-ai/claude-agent-sdk@0.3.176
# or
yarn add @anthropic-ai/claude-agent-sdk@0.3.176
# or
pnpm add @anthropic-ai/claude-agent-sdk@0.3.176
# or
bun add @anthropic-ai/claude-agent-sdk@0.3.176
</code></pre>
<h2>v0.3.175</h2>
<h2>What's changed</h2>
<ul>
<li>Updated to parity with Claude Code v2.1.175</li>
</ul>
<h2>Update</h2>
<pre lang="sh"><code>npm install @anthropic-ai/claude-agent-sdk@0.3.175
# or
yarn add @anthropic-ai/claude-agent-sdk@0.3.175
# or
pnpm add @anthropic-ai/claude-agent-sdk@0.3.175
# or
bun add @anthropic-ai/claude-agent-sdk@0.3.175
&lt;/tr&gt;&lt;/table&gt; 
</code></pre>
</blockquote>
<p>... (truncated)</p>
</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.177</h2>
<ul>
<li>Updated to parity with Claude Code v2.1.177</li>
</ul>
<h2>0.3.176</h2>
<ul>
<li>Fixed turn <code>result</code> messages being dropped when multiple
turns complete while a background agent or workflow is running</li>
<li>Fixed background agent, remote agent, and MCP task state not being
restored when resuming a session via the SDK</li>
</ul>
<h2>0.3.175</h2>
<ul>
<li>Updated to parity with Claude Code v2.1.175</li>
</ul>
<h2>0.3.174</h2>
<ul>
<li>SDK consumers now receive the <code>system/model_fallback</code>
message for all fallback triggers — <code>overloaded</code>,
<code>server_error</code>, and <code>last_resort</code> in addition to
<code>model_not_found</code> and <code>permission_denied</code> — and
the message's <code>trigger</code> field gained the
<code>server_error</code> and <code>last_resort</code> values</li>
</ul>
<h2>0.3.173</h2>
<ul>
<li>Updated to parity with Claude Code v2.1.173</li>
</ul>
<h2>0.3.172</h2>
<ul>
<li>SDK <code>plugins</code> option now accepts <code>skipMcpDiscovery:
true</code> per plugin, so a host that manages a plugin's MCP
connections itself can load skills/hooks from the plugin path without
the engine re-reading its <code>.mcp.json</code></li>
<li>Fixed slash-followed-by-whitespace input (e.g. <code>/ add
tests</code>) being silently dropped instead of treated as a plain
prompt</li>
</ul>
<h2>0.3.171</h2>
<ul>
<li>Updated to parity with Claude Code v2.1.171</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="12be9e52fd"><code>12be9e5</code></a>
chore: Update CHANGELOG.md</li>
<li><a
href="4bbff4fbf2"><code>4bbff4f</code></a>
chore: Update CHANGELOG.md</li>
<li><a
href="e05f10c790"><code>e05f10c</code></a>
chore: Update CHANGELOG.md</li>
<li><a
href="8ef4c3fe8e"><code>8ef4c3f</code></a>
chore: Update CHANGELOG.md</li>
<li><a
href="944ab13cf2"><code>944ab13</code></a>
chore: Update CHANGELOG.md</li>
<li><a
href="2cfb79cb35"><code>2cfb79c</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.170...v0.3.177">compare
view</a></li>
</ul>
</details>
<br />

Updates `@types/node` from 25.9.2 to 25.9.3
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node">compare
view</a></li>
</ul>
</details>
<br />

Updates `eslint` from 10.4.1 to 10.5.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.5.0</h2>
<h2>Features</h2>
<ul>
<li><a
href="5ca8c5278e"><code>5ca8c52</code></a>
feat: correct stack tracking in max-nested-callbacks (<a
href="https://redirect.github.com/eslint/eslint/issues/20973">#20973</a>)
(Pixel998)</li>
<li><a
href="b565783760"><code>b565783</code></a>
feat: report no-with violations at the with keyword (<a
href="https://redirect.github.com/eslint/eslint/issues/20971">#20971</a>)
(Pixel998)</li>
<li><a
href="2ce032fbc7"><code>2ce032f</code></a>
feat: report max-lines-per-function violations at function head (<a
href="https://redirect.github.com/eslint/eslint/issues/20966">#20966</a>)
(Pixel998)</li>
<li><a
href="732cb3e09d"><code>732cb3e</code></a>
feat: report max-nested-callbacks violations at function head (<a
href="https://redirect.github.com/eslint/eslint/issues/20967">#20967</a>)
(Pixel998)</li>
<li><a
href="f9c138a0ba"><code>f9c138a</code></a>
feat: report max-depth violations on keywords (<a
href="https://redirect.github.com/eslint/eslint/issues/20943">#20943</a>)
(Pixel998)</li>
<li><a
href="bdb496cc0d"><code>bdb496c</code></a>
feat: correct max-depth handling for else-if chains (<a
href="https://redirect.github.com/eslint/eslint/issues/20944">#20944</a>)
(Pixel998)</li>
<li><a
href="c29687354a"><code>c296873</code></a>
feat: update error loc in <code>max-statements</code> to function header
(<a
href="https://redirect.github.com/eslint/eslint/issues/20907">#20907</a>)
(Taejin Kim)</li>
</ul>
<h2>Documentation</h2>
<ul>
<li><a
href="8ae1b5b856"><code>8ae1b5b</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="ca7eb90127"><code>ca7eb90</code></a>
docs: update Node.js prerequisites to include ICU support (<a
href="https://redirect.github.com/eslint/eslint/issues/20962">#20962</a>)
(Francesco Trotta)</li>
<li><a
href="f99b47a679"><code>f99b47a</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="acf03d4eed"><code>acf03d4</code></a>
docs: clarify precedence of parserOptions over languageOptions (<a
href="https://redirect.github.com/eslint/eslint/issues/20926">#20926</a>)
(sethamus)</li>
</ul>
<h2>Chores</h2>
<ul>
<li><a
href="b18bf58c5a"><code>b18bf58</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/20959">#20959</a>)
(ESLint Bot)</li>
<li><a
href="c2d1444df7"><code>c2d1444</code></a>
refactor: replace areAllSegmentsUnreachable with !isAnySegmentReachable
(<a
href="https://redirect.github.com/eslint/eslint/issues/20951">#20951</a>)
(Taejin Kim)</li>
<li><a
href="243b8c5601"><code>243b8c5</code></a>
chore: enhance config-rule to support oneOf, anyOf, and nested schemas
(<a
href="https://redirect.github.com/eslint/eslint/issues/20788">#20788</a>)
(kuldeep kumar)</li>
<li><a
href="217b2a91f4"><code>217b2a9</code></a>
test: add unit tests for ParserService (<a
href="https://redirect.github.com/eslint/eslint/issues/20949">#20949</a>)
(Taejin Kim)</li>
<li><a
href="72003e781d"><code>72003e7</code></a>
test: add location information to error messages in
<code>max-statements</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20945">#20945</a>)
(lumir)</li>
<li><a
href="7797c26697"><code>7797c26</code></a>
refactor: deduplicate isAnySegmentReachable across rules (<a
href="https://redirect.github.com/eslint/eslint/issues/20890">#20890</a>)
(Taejin Kim)</li>
<li><a
href="67c46fa6e4"><code>67c46fa</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/20938">#20938</a>)
(ESLint Bot)</li>
<li><a
href="95d8c7a99f"><code>95d8c7a</code></a>
chore: update dependency <code>@​eslint/json</code> to v2 (<a
href="https://redirect.github.com/eslint/eslint/issues/20934">#20934</a>)
(renovate[bot])</li>
<li><a
href="cf9e496205"><code>cf9e496</code></a>
chore: update <code>@​arethetypeswrong/cli</code> to 0.18.3 (<a
href="https://redirect.github.com/eslint/eslint/issues/20933">#20933</a>)
(Pixel998)</li>
<li><a
href="fb6d3960ca"><code>fb6d396</code></a>
test: run type tests with TypeScript 7 (<a
href="https://redirect.github.com/eslint/eslint/issues/20868">#20868</a>)
(sethamus)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="de3b672a26"><code>de3b672</code></a>
10.5.0</li>
<li><a
href="362a518513"><code>362a518</code></a>
Build: changelog update for 10.5.0</li>
<li><a
href="5ca8c5278e"><code>5ca8c52</code></a>
feat: correct stack tracking in max-nested-callbacks (<a
href="https://redirect.github.com/eslint/eslint/issues/20973">#20973</a>)</li>
<li><a
href="b565783760"><code>b565783</code></a>
feat: report no-with violations at the with keyword (<a
href="https://redirect.github.com/eslint/eslint/issues/20971">#20971</a>)</li>
<li><a
href="2ce032fbc7"><code>2ce032f</code></a>
feat: report max-lines-per-function violations at function head (<a
href="https://redirect.github.com/eslint/eslint/issues/20966">#20966</a>)</li>
<li><a
href="732cb3e09d"><code>732cb3e</code></a>
feat: report max-nested-callbacks violations at function head (<a
href="https://redirect.github.com/eslint/eslint/issues/20967">#20967</a>)</li>
<li><a
href="f9c138a0ba"><code>f9c138a</code></a>
feat: report max-depth violations on keywords (<a
href="https://redirect.github.com/eslint/eslint/issues/20943">#20943</a>)</li>
<li><a
href="8ae1b5b856"><code>8ae1b5b</code></a>
docs: Update README</li>
<li><a
href="ca7eb90127"><code>ca7eb90</code></a>
docs: update Node.js prerequisites to include ICU support (<a
href="https://redirect.github.com/eslint/eslint/issues/20962">#20962</a>)</li>
<li><a
href="b18bf58c5a"><code>b18bf58</code></a>
chore: update ecosystem plugins (<a
href="https://redirect.github.com/eslint/eslint/issues/20959">#20959</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/eslint/eslint/compare/v10.4.1...v10.5.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `vitest` from 4.1.8 to 4.1.9
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/HEAD/packages/vitest">compare
view</a></li>
</ul>
</details>
<br />

Updates `@anthropic-ai/claude-agent-sdk-darwin-arm64` from 0.3.170 to
0.3.177

Updates `@anthropic-ai/claude-agent-sdk-darwin-x64` from 0.3.170 to
0.3.177

Updates `@anthropic-ai/claude-agent-sdk-linux-arm64` from 0.3.170 to
0.3.177

Updates `@anthropic-ai/claude-agent-sdk-linux-arm64-musl` from 0.3.170
to 0.3.177

Updates `@anthropic-ai/claude-agent-sdk-linux-x64` from 0.3.170 to
0.3.177

Updates `@anthropic-ai/claude-agent-sdk-linux-x64-musl` from 0.3.170 to
0.3.177

Updates `@anthropic-ai/claude-agent-sdk-win32-arm64` from 0.3.170 to
0.3.177

Updates `@anthropic-ai/claude-agent-sdk-win32-x64` from 0.3.170 to
0.3.177

Updates `@vitest/expect` from 4.1.8 to 4.1.9
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/HEAD/packages/expect">compare
view</a></li>
</ul>
</details>
<br />

Updates `@vitest/mocker` from 4.1.8 to 4.1.9
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/HEAD/packages/mocker">compare
view</a></li>
</ul>
</details>
<br />

Updates `@vitest/pretty-format` from 4.1.8 to 4.1.9
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/HEAD/packages/pretty-format">compare
view</a></li>
</ul>
</details>
<br />

Updates `@vitest/runner` from 4.1.8 to 4.1.9
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/HEAD/packages/runner">compare
view</a></li>
</ul>
</details>
<br />

Updates `@vitest/snapshot` from 4.1.8 to 4.1.9
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/HEAD/packages/snapshot">compare
view</a></li>
</ul>
</details>
<br />

Updates `@vitest/spy` from 4.1.8 to 4.1.9
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/HEAD/packages/spy">compare
view</a></li>
</ul>
</details>
<br />

Updates `@vitest/utils` from 4.1.8 to 4.1.9
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/HEAD/packages/utils">compare
view</a></li>
</ul>
</details>
<br />

Updates `acorn` from 8.16.0 to 8.17.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="5b9d16c256"><code>5b9d16c</code></a>
Mark version 8.17.0</li>
<li><a
href="449f9fafb8"><code>449f9fa</code></a>
Make linter happy</li>
<li><a
href="9e1bced50d"><code>9e1bced</code></a>
Add a strict option to turn on strict mode for scripts</li>
<li><a
href="8a47812670"><code>8a47812</code></a>
Convert stack overflow errors to SyntaxError instances</li>
<li><a
href="3bc83f91bb"><code>3bc83f9</code></a>
Update maintainer email</li>
<li><a
href="3f40dbe684"><code>3f40dbe</code></a>
Bump test262</li>
<li><a
href="8bd029044e"><code>8bd0290</code></a>
Improve handling of using/await using in for loops</li>
<li><a
href="f25fdeda46"><code>f25fded</code></a>
Upgrade some dev dependencies</li>
<li><a
href="27781e4542"><code>27781e4</code></a>
Remove unnecessary test</li>
<li><a
href="2dded4b9de"><code>2dded4b</code></a>
Forbid 'new super()'</li>
<li>Additional commits viewable in <a
href="https://github.com/acornjs/acorn/compare/8.16.0...8.17.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `body-parser` from 2.2.2 to 2.3.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.3.0</h2>
<h2>What's Changed</h2>
<ul>
<li>build(deps): bump actions/download-artifact from 6.0.0 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/681">expressjs/body-parser#681</a></li>
<li>build(deps): bump actions/checkout from 5.0.0 to 6.0.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/682">expressjs/body-parser#682</a></li>
<li>build(deps): bump actions/setup-node from 6.0.0 to 6.1.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/683">expressjs/body-parser#683</a></li>
<li>build(deps): bump actions/upload-artifact from 5.0.0 to 6.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/685">expressjs/body-parser#685</a></li>
<li>build(deps): bump github/codeql-action from 4.31.2 to 4.31.9 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/684">expressjs/body-parser#684</a></li>
<li>perf(urlencoded): move empty-body guard to avoid extra function
closure by <a
href="https://github.com/Phillip9587"><code>@​Phillip9587</code></a> in
<a
href="https://redirect.github.com/expressjs/body-parser/pull/647">expressjs/body-parser#647</a></li>
<li>Improve ESM compatibility by <a
href="https://github.com/Phillip9587"><code>@​Phillip9587</code></a> in
<a
href="https://redirect.github.com/expressjs/body-parser/pull/697">expressjs/body-parser#697</a></li>
<li>docs: add recommendations for configuring payload limits by <a
href="https://github.com/bjohansebas"><code>@​bjohansebas</code></a> in
<a
href="https://redirect.github.com/expressjs/body-parser/pull/699">expressjs/body-parser#699</a></li>
<li>build(deps): bump actions/setup-node from 6.1.0 to 6.2.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/701">expressjs/body-parser#701</a></li>
<li>build(deps): bump github/codeql-action from 4.31.10 to 4.32.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/702">expressjs/body-parser#702</a></li>
<li>build(deps): bump actions/checkout from 6.0.1 to 6.0.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/700">expressjs/body-parser#700</a></li>
<li>chore: add explicit type commonjs to package.json by <a
href="https://github.com/Phillip9587"><code>@​Phillip9587</code></a> in
<a
href="https://redirect.github.com/expressjs/body-parser/pull/711">expressjs/body-parser#711</a></li>
<li>deps: update dependencies to latest versions by <a
href="https://github.com/Phillip9587"><code>@​Phillip9587</code></a> in
<a
href="https://redirect.github.com/expressjs/body-parser/pull/708">expressjs/body-parser#708</a></li>
<li>build(deps): bump actions/download-artifact from 7.0.0 to 8.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/712">expressjs/body-parser#712</a></li>
<li>build(deps): bump github/codeql-action from 4.32.0 to 4.32.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/713">expressjs/body-parser#713</a></li>
<li>build(deps): bump actions/upload-artifact from 6.0.0 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/714">expressjs/body-parser#714</a></li>
<li>fix: improve limit option validation by <a
href="https://github.com/Phillip9587"><code>@​Phillip9587</code></a> in
<a
href="https://redirect.github.com/expressjs/body-parser/pull/698">expressjs/body-parser#698</a></li>
<li>build(deps): bump github/codeql-action from 4.32.4 to 4.35.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/719">expressjs/body-parser#719</a></li>
<li>build(deps): bump actions/setup-node from 6.2.0 to 6.3.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/718">expressjs/body-parser#718</a></li>
<li>build(deps): bump actions/download-artifact from 8.0.0 to 8.0.1 by
<a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/717">expressjs/body-parser#717</a></li>
<li>perf: eliminate conditional check in json strict mode hot path by <a
href="https://github.com/Phillip9587"><code>@​Phillip9587</code></a> in
<a
href="https://redirect.github.com/expressjs/body-parser/pull/651">expressjs/body-parser#651</a></li>
<li>ci: add node.js 26 to text matrix by <a
href="https://github.com/Phillip9587"><code>@​Phillip9587</code></a> in
<a
href="https://redirect.github.com/expressjs/body-parser/pull/726">expressjs/body-parser#726</a></li>
<li>build(deps): bump actions/setup-node from 6.3.0 to 6.4.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/725">expressjs/body-parser#725</a></li>
<li>build(deps): bump actions/upload-artifact from 7.0.0 to 7.0.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/724">expressjs/body-parser#724</a></li>
<li>build(deps): bump github/codeql-action from 4.35.1 to 4.35.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/723">expressjs/body-parser#723</a></li>
<li>Upgrade &quot;content-type&quot; by <a
href="https://github.com/blakeembrey"><code>@​blakeembrey</code></a> in
<a
href="https://redirect.github.com/expressjs/body-parser/pull/728">expressjs/body-parser#728</a></li>
<li>refactor: switch to const/let and enable eslint no-var rule by <a
href="https://github.com/Phillip9587"><code>@​Phillip9587</code></a> in
<a
href="https://redirect.github.com/expressjs/body-parser/pull/729">expressjs/body-parser#729</a></li>
<li>Update outdated reference to MDN docs by <a
href="https://github.com/krzysdz"><code>@​krzysdz</code></a> in <a
href="https://redirect.github.com/expressjs/body-parser/pull/730">expressjs/body-parser#730</a></li>
<li>build(deps): bump github/codeql-action from 4.35.3 to 4.36.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/731">expressjs/body-parser#731</a></li>
<li>build(deps): bump actions/checkout from 6.0.2 to 6.0.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/732">expressjs/body-parser#732</a></li>
<li>chore: updated deps to latest by <a
href="https://github.com/Phillip9587"><code>@​Phillip9587</code></a> in
<a
href="https://redirect.github.com/expressjs/body-parser/pull/733">expressjs/body-parser#733</a></li>
<li>2.3.0 by <a
href="https://github.com/UlisesGascon"><code>@​UlisesGascon</code></a>
in <a
href="https://redirect.github.com/expressjs/body-parser/pull/735">expressjs/body-parser#735</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/krzysdz"><code>@​krzysdz</code></a> made
their first contribution in <a
href="https://redirect.github.com/expressjs/body-parser/pull/730">expressjs/body-parser#730</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/expressjs/body-parser/compare/v2.2.2...v2.3.0">https://github.com/expressjs/body-parser/compare/v2.2.2...v2.3.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.3.0 / 2026-06-15</h1>
<ul>
<li>fix: use static exports instead of lazy getters to improve ESM
compatibility</li>
<li>feat: add subpath exports for individual parsers</li>
<li>fix: improve <code>limit</code> option validation (<a
href="https://redirect.github.com/expressjs/body-parser/issues/698">#698</a>)
<ul>
<li>Invalid <code>limit</code> values (e.g. unparseable strings or
<code>NaN</code>) now throw instead of being silently ignored, which
previously disabled size limit enforcement</li>
<li><code>null</code> and <code>undefined</code> fall back to the
default 100kb limit</li>
</ul>
</li>
<li>deps:
<ul>
<li>content-type@^2.0.0</li>
<li>http-errors@^2.0.1</li>
<li>iconv-lite^0.7.2</li>
<li>qs@^6.15.2</li>
<li>raw-body@^3.0.2</li>
<li>type-is@^2.1.0</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="d0f2ace6c7"><code>d0f2ace</code></a>
2.3.0 (<a
href="https://redirect.github.com/expressjs/body-parser/issues/735">#735</a>)</li>
<li><a
href="7d03f2f9d5"><code>7d03f2f</code></a>
chore: updated deps to latest (<a
href="https://redirect.github.com/expressjs/body-parser/issues/733">#733</a>)</li>
<li><a
href="8024ba7a81"><code>8024ba7</code></a>
build(deps): bump actions/checkout from 6.0.2 to 6.0.3 (<a
href="https://redirect.github.com/expressjs/body-parser/issues/732">#732</a>)</li>
<li><a
href="32b4ed4639"><code>32b4ed4</code></a>
build(deps): bump github/codeql-action from 4.35.3 to 4.36.1 (<a
href="https://redirect.github.com/expressjs/body-parser/issues/731">#731</a>)</li>
<li><a
href="ff0f6b9071"><code>ff0f6b9</code></a>
docs: update outdated reference to MDN docs (<a
href="https://redirect.github.com/expressjs/body-parser/issues/730">#730</a>)</li>
<li><a
href="14d001a9c9"><code>14d001a</code></a>
refactor: switch to const/let and enable eslint no-var rule (<a
href="https://redirect.github.com/expressjs/body-parser/issues/729">#729</a>)</li>
<li><a
href="37f36a2752"><code>37f36a2</code></a>
deps: update content-type and type-is (<a
href="https://redirect.github.com/expressjs/body-parser/issues/728">#728</a>)</li>
<li><a
href="e1c244bf55"><code>e1c244b</code></a>
build(deps): bump github/codeql-action from 4.35.1 to 4.35.3 (<a
href="https://redirect.github.com/expressjs/body-parser/issues/723">#723</a>)</li>
<li><a
href="e01087f521"><code>e01087f</code></a>
build(deps): bump actions/upload-artifact from 7.0.0 to 7.0.1 (<a
href="https://redirect.github.com/expressjs/body-parser/issues/724">#724</a>)</li>
<li><a
href="a7698d3028"><code>a7698d3</code></a>
build(deps): bump actions/setup-node from 6.3.0 to 6.4.0 (<a
href="https://redirect.github.com/expressjs/body-parser/issues/725">#725</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/expressjs/body-parser/compare/v2.2.2...v2.3.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `obug` from 2.1.2 to 2.1.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/sxzz/obug/releases">obug's
releases</a>.</em></p>
<blockquote>
<h2>v2.1.3</h2>
<h3>   🚀 Features</h3>
<ul>
<li>Add <code>sideEffects</code> field  -  by <a
href="https://github.com/sxzz"><code>@​sxzz</code></a> <a
href="https://github.com/sxzz/obug/commit/014584c"><!-- raw HTML omitted
-->(01458)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/sxzz/obug/compare/v2.1.2...v2.1.3">View changes
on GitHub</a></h5>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="6508a03a1e"><code>6508a03</code></a>
chore: release v2.1.3</li>
<li><a
href="014584c3c8"><code>014584c</code></a>
feat: add <code>sideEffects</code> field</li>
<li>See full diff in <a
href="https://github.com/sxzz/obug/compare/v2.1.2...v2.1.3">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>
2026-06-15 17:21:31 +02:00
dependabot[bot]
7de5e4bcca feat(deps-dev): bump the minor group with 3 updates (#763)
Bumps the minor group with 3 updates:
[@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript),
[@napi-rs/wasm-runtime](https://github.com/napi-rs/napi-rs/tree/HEAD/wasm-runtime)
and [semver](https://github.com/npm/node-semver).

Updates `@anthropic-ai/sdk` from 0.103.0 to 0.104.1
<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.104.1</h2>
<h2>0.104.1 (2026-06-09)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.104.0...sdk-v0.104.1">sdk-v0.104.0...sdk-v0.104.1</a></p>
<h3>Bug Fixes</h3>
<ul>
<li><strong>api:</strong> add <code>frontier_llm</code> refusal category
(<a
href="465e6866d6">465e686</a>)</li>
</ul>
<h2>sdk: v0.104.0</h2>
<h2>0.104.0 (2026-06-09)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.103.0...sdk-v0.104.0">sdk-v0.103.0...sdk-v0.104.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> add support for Managed Agents deployments and
environment variable credentials (<a
href="d01e38b5b6">d01e38b</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.104.1 (2026-06-09)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.104.0...sdk-v0.104.1">sdk-v0.104.0...sdk-v0.104.1</a></p>
<h3>Bug Fixes</h3>
<ul>
<li><strong>api:</strong> add <code>frontier_llm</code> refusal category
(<a
href="465e6866d6">465e686</a>)</li>
</ul>
<h2>0.104.0 (2026-06-09)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.103.0...sdk-v0.104.0">sdk-v0.103.0...sdk-v0.104.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> add support for Managed Agents deployments and
environment variable credentials (<a
href="d01e38b5b6">d01e38b</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="9a0442d88e"><code>9a0442d</code></a>
chore: release main</li>
<li><a
href="1ccd4012e7"><code>1ccd401</code></a>
fix(api): add <code>frontier_llm</code> refusal category</li>
<li><a
href="8be0232e92"><code>8be0232</code></a>
chore: release main</li>
<li><a
href="813af32183"><code>813af32</code></a>
feat(api): add support for Managed Agents deployments and environment
variabl...</li>
<li>See full diff in <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.103.0...sdk-v0.104.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `@napi-rs/wasm-runtime` from 1.1.4 to 1.1.5
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/napi-rs/napi-rs/blob/main/wasm-runtime/CHANGELOG.md">@​napi-rs/wasm-runtime's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/napi-rs/napi-rs/compare/@napi-rs/wasm-runtime@1.1.4...@napi-rs/wasm-runtime@1.1.5">1.1.5</a>
(2026-06-10)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>wasm-runtime:</strong> preserve Buffer return values in
fs-proxy (<a
href="https://redirect.github.com/napi-rs/napi-rs/issues/3250">#3250</a>)
(<a
href="c70f205a07">c70f205</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="670e5d3195"><code>670e5d3</code></a>
chore(release): publish</li>
<li><a
href="ad7b1c8fbf"><code>ad7b1c8</code></a>
chore(deps): lock file maintenance (<a
href="https://github.com/napi-rs/napi-rs/tree/HEAD/wasm-runtime/issues/3318">#3318</a>)</li>
<li><a
href="c70f205a07"><code>c70f205</code></a>
fix(wasm-runtime): preserve Buffer return values in fs-proxy (<a
href="https://github.com/napi-rs/napi-rs/tree/HEAD/wasm-runtime/issues/3250">#3250</a>)</li>
<li>See full diff in <a
href="https://github.com/napi-rs/napi-rs/commits/@napi-rs/wasm-runtime@1.1.5/wasm-runtime">compare
view</a></li>
</ul>
</details>
<br />

Updates `semver` from 7.8.3 to 7.8.4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/npm/node-semver/releases">semver's
releases</a>.</em></p>
<blockquote>
<h2>v7.8.4</h2>
<h2><a
href="https://github.com/npm/node-semver/compare/v7.8.3...v7.8.4">7.8.4</a>
(2026-06-09)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><a
href="e583226b16"><code>e583226</code></a>
<a href="https://redirect.github.com/npm/node-semver/pull/874">#874</a>
reject numeric segments after x-ranges (<a
href="https://github.com/pupuking723"><code>@​pupuking723</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/npm/node-semver/blob/main/CHANGELOG.md">semver's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/npm/node-semver/compare/v7.8.3...v7.8.4">7.8.4</a>
(2026-06-09)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><a
href="e583226b16"><code>e583226</code></a>
<a href="https://redirect.github.com/npm/node-semver/pull/874">#874</a>
reject numeric segments after x-ranges (<a
href="https://github.com/pupuking723"><code>@​pupuking723</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="8640bd68f1"><code>8640bd6</code></a>
chore: release 7.8.4 (<a
href="https://redirect.github.com/npm/node-semver/issues/875">#875</a>)</li>
<li><a
href="e583226b16"><code>e583226</code></a>
fix: reject numeric segments after x-ranges</li>
<li>See full diff in <a
href="https://github.com/npm/node-semver/compare/v7.8.3...v7.8.4">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>
2026-06-10 17:21:39 +02:00
12 changed files with 2202 additions and 747 deletions

View File

@@ -1,3 +1,3 @@
{
".": "0.44.0"
".": "0.47.0"
}

View File

@@ -1,5 +1,51 @@
# Changelog
## [0.47.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.46.0...v0.47.0) (2026-06-17)
### Features
* Update to claude-agent-sdk 0.3.179 ([#783](https://github.com/agentclientprotocol/claude-agent-acp/issues/783)) ([59a098c](https://github.com/agentclientprotocol/claude-agent-acp/commit/59a098c2b530bbae034e9a2dfbd31f8b4ef2a4d0))
### Bug Fixes
* Duplicate assistant messages in feed ([#785](https://github.com/agentclientprotocol/claude-agent-acp/issues/785)) ([12d34e6](https://github.com/agentclientprotocol/claude-agent-acp/commit/12d34e64e53564602ac1c38a30127e234c5c25ff))
## [0.46.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.45.1...v0.46.0) (2026-06-16)
### Features
* Update to claude-agent-sdk 0.3.178 ([#777](https://github.com/agentclientprotocol/claude-agent-acp/issues/777)) ([58549ff](https://github.com/agentclientprotocol/claude-agent-acp/commit/58549ffe6a8b02ce59894e567407bd4299c11428))
### Bug Fixes
* Better handle out of turn events ([#780](https://github.com/agentclientprotocol/claude-agent-acp/issues/780)) ([4f273a2](https://github.com/agentclientprotocol/claude-agent-acp/commit/4f273a20d870c9c69f71556b8e0519f1de30f285))
* Forward option details in elicitation meta ([#779](https://github.com/agentclientprotocol/claude-agent-acp/issues/779)) ([b364059](https://github.com/agentclientprotocol/claude-agent-acp/commit/b3640599ae685beecacd93e012d5bbc9dac716f7)), closes [#764](https://github.com/agentclientprotocol/claude-agent-acp/issues/764)
## [0.45.1](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.45.0...v0.45.1) (2026-06-16)
### Bug Fixes
* Fix terminal error printing as text instead of terminal output ([#776](https://github.com/agentclientprotocol/claude-agent-acp/issues/776)) ([db6eaaf](https://github.com/agentclientprotocol/claude-agent-acp/commit/db6eaaf71484a321e47093ad65bcf8994943cb31))
* Scope custom answers per question ([#774](https://github.com/agentclientprotocol/claude-agent-acp/issues/774)) ([d58004a](https://github.com/agentclientprotocol/claude-agent-acp/commit/d58004a34880e0a76833697319eb2a9efa6a43c7))
## [0.45.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.44.0...v0.45.0) (2026-06-15)
### Features
* **deps-dev:** bump the minor group with 3 updates ([#763](https://github.com/agentclientprotocol/claude-agent-acp/issues/763)) ([7de5e4b](https://github.com/agentclientprotocol/claude-agent-acp/commit/7de5e4bcca9bfea70593092060f82bc8abe33e0e))
* **deps:** bump @anthropic-ai/claude-agent-sdk to 0.3.177 ([#771](https://github.com/agentclientprotocol/claude-agent-acp/issues/771)) ([1be5ca5](https://github.com/agentclientprotocol/claude-agent-acp/commit/1be5ca57ee772fe90e41126365dc4186a18ad257))
### Bug Fixes
* preserve ANTHROPIC_CUSTOM_MODEL_OPTION when availableModels is set ([#768](https://github.com/agentclientprotocol/claude-agent-acp/issues/768)) ([cc2885f](https://github.com/agentclientprotocol/claude-agent-acp/commit/cc2885f6a9993cf61e759c3c770015f94c218627))
## [0.44.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.43.0...v0.44.0) (2026-06-09)

523
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
"publishConfig": {
"access": "public"
},
"version": "0.44.0",
"version": "0.47.0",
"description": "An ACP-compatible coding agent powered by the Claude Agent SDK (TypeScript)",
"main": "dist/lib.js",
"types": "dist/lib.d.ts",
@@ -60,22 +60,22 @@
"author": "Zed Industries",
"license": "Apache-2.0",
"dependencies": {
"@agentclientprotocol/sdk": "0.25.0",
"@anthropic-ai/claude-agent-sdk": "0.3.170",
"@agentclientprotocol/sdk": "0.26.0",
"@anthropic-ai/claude-agent-sdk": "0.3.179",
"zod": "^3.25.0 || ^4.0.0"
},
"devDependencies": {
"@anthropic-ai/sdk": "0.103.0",
"@anthropic-ai/sdk": "0.104.2",
"@eslint/js": "10.0.1",
"@types/node": "25.9.2",
"@typescript-eslint/eslint-plugin": "8.61.0",
"@typescript-eslint/parser": "8.61.0",
"eslint": "10.4.1",
"@types/node": "25.9.3",
"@typescript-eslint/eslint-plugin": "8.61.1",
"@typescript-eslint/parser": "8.61.1",
"eslint": "10.5.0",
"eslint-config-prettier": "10.1.8",
"globals": "17.6.0",
"prettier": "3.8.4",
"ts-node": "10.9.2",
"typescript": "6.0.3",
"vitest": "4.1.8"
"vitest": "4.1.9"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -116,8 +116,42 @@ function questionFieldKey(index: number): string {
return `question_${index}`;
}
/** Form-field key for the optional free-text "custom answer" field. */
const CUSTOM_ANSWER_FIELD = "customAnswer";
/**
* Form-field key for the per-question free-text "custom answer" field that sits
* alongside `question_<n>`. Mirrors the first-party clients, where every
* question carries its own "Other" box rather than one form-level field.
*/
function questionCustomFieldKey(index: number): string {
return `question_${index}_custom`;
}
/**
* `_meta` key under which a bridged enum option carries its structured
* `description`/`preview`, since ACP's `EnumOption` has no field for either.
* Namespaced like the agent's other `_meta` extensions (`_claude/...`).
*/
const OPTION_META_KEY = "_claude/askUserQuestionOption";
/** A single option as supplied by the AskUserQuestion tool. */
type AskUserQuestionOption = AskUserQuestion["options"][number];
/**
* Build the `_meta` payload that carries an option's structured `description`
* and optional `preview` for clients that can render them as distinct fields.
* Returns `undefined` when neither is present, so we don't emit an empty `_meta`.
*/
function askUserQuestionOptionMeta(
option: AskUserQuestionOption,
): NonNullable<EnumOption["_meta"]> | undefined {
const detail: { description?: string; preview?: string } = {};
if (option.description) {
detail.description = option.description;
}
if (option.preview) {
detail.preview = option.preview;
}
return Object.keys(detail).length > 0 ? { [OPTION_META_KEY]: detail } : undefined;
}
/**
* Render the AskUserQuestion tool's questions as an ACP form elicitation.
@@ -128,10 +162,11 @@ const CUSTOM_ANSWER_FIELD = "customAnswer";
* an array with a titled `anyOf` item enum. The enum `const` is always the
* option label, since that is what the tool records as the answer.
*
* A trailing optional free-text field mirrors the CLI's custom-answer box: the
* user can type their own answer instead of (or as well as) picking an option.
* Nothing is marked required, so the user can also just skip — matching the
* built-in tool, which always offers Skip + a free-text box.
* Each question is followed by its own optional free-text "custom answer" field
* (`question_<n>_custom`), mirroring the CLI's per-question "Other" box: the
* user can type their own answer instead of picking an option, scoped to that
* specific question. Nothing is marked required, so the user can also just skip
* — matching the built-in tool, which always offers Skip + a free-text box.
*/
export function askUserQuestionsToCreateRequest(
questions: AskUserQuestion[],
@@ -142,10 +177,25 @@ export function askUserQuestionsToCreateRequest(
const properties: Record<string, ElicitationPropertySchema> = {};
questions.forEach((question, index) => {
const options: EnumOption[] = question.options.map((option) => ({
const: option.label,
title: option.description ? `${option.label} — ${option.description}` : option.label,
}));
const options: EnumOption[] = question.options.map((option) => {
const enumOption: EnumOption = {
const: option.label,
// `title` stays a flattened "label — description" string so clients that
// only read `const`/`title` still surface the description. Clients that
// understand the `_meta` below should prefer its structured fields (and
// treat `const` as the clean label) rather than parsing this title.
title: option.description ? `${option.label} — ${option.description}` : option.label,
};
// The SDK option carries a `description` (secondary text) and an optional
// `preview` (mockups, code snippets, comparisons shown on focus). Neither
// has a structural slot in `EnumOption`, so forward them under ACP's
// reserved `_meta` extension point for clients that can render them.
const meta = askUserQuestionOptionMeta(option);
if (meta) {
enumOption._meta = meta;
}
return enumOption;
});
// For a single question the prompt is carried by `message`, so we don't
// repeat it in the field description. With multiple questions each field
@@ -156,13 +206,13 @@ export function askUserQuestionsToCreateRequest(
properties[questionFieldKey(index)] = question.multiSelect
? { type: "array", title, description, items: { anyOf: options } }
: { type: "string", title, description, oneOf: options };
});
properties[CUSTOM_ANSWER_FIELD] = {
type: "string",
title: "Other",
description: "Type your own answer instead of choosing an option above (optional).",
};
properties[questionCustomFieldKey(index)] = {
type: "string",
title: "Other",
description: "Type your own answer instead of choosing an option above (optional).",
};
});
const requestedSchema: ElicitationSchema = {
type: "object",
@@ -190,10 +240,11 @@ export type AskUserQuestionOutcome =
*
* Selected labels are read back from the indexed form fields and written into
* `answers` as a `{ [questionText]: label }` map (comma-joining multi-selects)
* — the key shape the tool's own `call()` reads. Free text from the custom-
* answer field becomes the tool's top-level `response`. Decline yields empty
* answers (the model is told the user skipped rather than the turn aborting);
* cancel aborts the tool call.
* — the key shape the tool's own `call()` reads. A non-empty per-question
* custom-answer field (`question_<n>_custom`) takes precedence over that
* question's selection, since the user typed their own answer instead of
* picking one. Decline yields empty answers (the model is told the user skipped
* rather than the turn aborting); cancel aborts the tool call.
*/
export function applyAskElicitationResponse(
response: CreateElicitationResponse,
@@ -213,6 +264,14 @@ export function applyAskElicitationResponse(
// stay in sync with what the built-in tool's call() expects to read back.
const answers: AskUserQuestionOutput["answers"] = {};
questions.forEach((question, index) => {
// A typed custom answer wins over the selection: the user chose to write
// their own answer for this question instead of picking an option.
const custom = content[questionCustomFieldKey(index)];
if (typeof custom === "string" && custom.trim() !== "") {
answers[question.question] = custom.trim();
return;
}
const value = content[questionFieldKey(index)];
if (value === undefined || value === null) {
return;
@@ -224,14 +283,7 @@ export function applyAskElicitationResponse(
answers[question.question] = text;
});
const updatedInput: Record<string, unknown> = { ...toolInput, answers };
const custom = content[CUSTOM_ANSWER_FIELD];
if (typeof custom === "string" && custom.trim() !== "") {
const response: AskUserQuestionOutput["response"] = custom;
updatedInput.response = response;
}
return { action: "answered", updatedInput };
return { action: "answered", updatedInput: { ...toolInput, answers } };
}
/**

View File

@@ -700,6 +700,118 @@ describe("ClaudeAcpAgent settings", () => {
expect(byValue["claude-opus-4-6[1m]"].name).toBe("claude-opus-4-6[1m]");
expect(byValue["claude-opus-4-6"].name).toBe("claude-opus-4-6");
});
it("preserves ANTHROPIC_CUSTOM_MODEL_OPTION even when absent from the allowlist", async () => {
// Per the model-config docs, ANTHROPIC_CUSTOM_MODEL_OPTION adds an entry
// "without replacing the built-in aliases" and "appears at the bottom of
// the /model picker", so it is exempt from the availableModels allowlist
// (the same way the Default option is "not affected by availableModels").
// ACP must match: a slim alias allowlist must not hide the custom model
// row, and it appears last, after the allowlisted entries.
// https://code.claude.com/docs/en/model-config#add-a-custom-model-option
const originalEnv = process.env.ANTHROPIC_CUSTOM_MODEL_OPTION;
process.env.ANTHROPIC_CUSTOM_MODEL_OPTION = "claude-opus-4-8[1m]";
try {
await fs.promises.writeFile(
path.join(tempDir, "settings.json"),
JSON.stringify({
availableModels: ["sonnet", "opus", "haiku"],
}),
);
const projectDir = path.join(tempDir, "project");
await fs.promises.mkdir(projectDir, { recursive: true });
mockQueryWithModels([
{ value: "default", displayName: "Default", description: "Default model" },
{ value: "sonnet", displayName: "Sonnet", description: "Claude Sonnet 4.6" },
{ value: "opus", displayName: "Opus", description: "Claude Opus 4.6" },
{ value: "haiku", displayName: "Haiku", description: "Claude Haiku 4.5" },
{
value: "claude-opus-4-8[1m]",
displayName: "Opus 4.8",
description: "Claude Opus 4.8",
},
]);
const { ClaudeAcpAgent } = await import("../acp-agent.js");
const agent: ClaudeAcpAgentType = new ClaudeAcpAgent(createMockClient());
const response = await (agent as any).createSession({
cwd: projectDir,
mcpServers: [],
_meta: { disableBuiltInTools: true },
});
const modelOption = response.configOptions.find((o: any) => o.id === "model");
expect(modelOption.options.map((o: any) => o.value)).toEqual([
"default",
"sonnet",
"opus",
"haiku",
"claude-opus-4-8[1m]",
]);
const custom = modelOption.options.find((o: any) => o.value === "claude-opus-4-8[1m]");
expect(custom.name).toBe("Opus 4.8");
expect(custom.description).toBe("Claude Opus 4.8");
} finally {
if (originalEnv === undefined) {
delete process.env.ANTHROPIC_CUSTOM_MODEL_OPTION;
} else {
process.env.ANTHROPIC_CUSTOM_MODEL_OPTION = originalEnv;
}
}
});
it("does not duplicate the custom model option when also in the allowlist", async () => {
// If the user lists the custom model's exact ID in availableModels AND it
// is set as ANTHROPIC_CUSTOM_MODEL_OPTION, it must appear exactly once.
const originalEnv = process.env.ANTHROPIC_CUSTOM_MODEL_OPTION;
process.env.ANTHROPIC_CUSTOM_MODEL_OPTION = "claude-opus-4-8[1m]";
try {
await fs.promises.writeFile(
path.join(tempDir, "settings.json"),
JSON.stringify({
availableModels: ["sonnet", "claude-opus-4-8[1m]"],
}),
);
const projectDir = path.join(tempDir, "project");
await fs.promises.mkdir(projectDir, { recursive: true });
mockQueryWithModels([
{ value: "default", displayName: "Default", description: "Default model" },
{ value: "sonnet", displayName: "Sonnet", description: "Claude Sonnet 4.6" },
{
value: "claude-opus-4-8[1m]",
displayName: "Opus 4.8",
description: "Claude Opus 4.8",
},
]);
const { ClaudeAcpAgent } = await import("../acp-agent.js");
const agent: ClaudeAcpAgentType = new ClaudeAcpAgent(createMockClient());
const response = await (agent as any).createSession({
cwd: projectDir,
mcpServers: [],
_meta: { disableBuiltInTools: true },
});
const modelOption = response.configOptions.find((o: any) => o.id === "model");
expect(modelOption.options.map((o: any) => o.value)).toEqual([
"default",
"sonnet",
"claude-opus-4-8[1m]",
]);
} finally {
if (originalEnv === undefined) {
delete process.env.ANTHROPIC_CUSTOM_MODEL_OPTION;
} else {
process.env.ANTHROPIC_CUSTOM_MODEL_OPTION = originalEnv;
}
}
});
});
it("resolves model aliases like opus[1m] to the correct model", async () => {

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,9 @@
import { describe, it, expect } from "vitest";
import type { CreateElicitationRequest, CreateElicitationResponse } from "@agentclientprotocol/sdk";
import type {
CreateElicitationRequest,
CreateElicitationResponse,
EnumOption,
} from "@agentclientprotocol/sdk";
import type { ElicitationRequest } from "@anthropic-ai/claude-agent-sdk";
import {
applyAskElicitationResponse,
@@ -19,14 +23,18 @@ const SESSION_ID = "session-1";
*/
function mkQuestion(
question: string,
options: Array<{ label: string; description?: string }>,
options: Array<{ label: string; description?: string; preview?: string }>,
opts: { header?: string; multiSelect?: boolean } = {},
): AskUserQuestion {
return {
question,
header: opts.header ?? "",
multiSelect: opts.multiSelect ?? false,
options: options.map((o) => ({ label: o.label, description: o.description ?? "" })),
options: options.map((o) => ({
label: o.label,
description: o.description ?? "",
...(o.preview ? { preview: o.preview } : {}),
})),
} as AskUserQuestion;
}
@@ -179,7 +187,14 @@ describe("askUserQuestionsToCreateRequest", () => {
title: "Library",
description: undefined,
oneOf: [
{ const: "date-fns", title: "date-fns — Lightweight" },
{
const: "date-fns",
title: "date-fns — Lightweight",
// Structured description forwarded under `_meta` so clients can render
// it as secondary text instead of parsing it out of the title.
_meta: { "_claude/askUserQuestionOption": { description: "Lightweight" } },
},
// No description → no `_meta` emitted.
{ const: "luxon", title: "luxon" },
],
});
@@ -187,8 +202,52 @@ describe("askUserQuestionsToCreateRequest", () => {
expect(schema.properties?.["Which library?"]).toBeUndefined();
});
it("includes an optional free-text custom-answer field", () => {
const questions = [mkQuestion("Which?", [{ label: "A" }, { label: "B" }])];
it("forwards option description and preview under _meta for rich clients", () => {
const questions = [
mkQuestion("Which layout?", [
{
label: "Grid",
description: "Cards in a responsive grid",
preview: "```\n[ ] [ ] [ ]\n[ ] [ ] [ ]\n```",
},
{ label: "List", description: "Stacked rows" },
{ label: "Plain" },
]),
];
const schema = (
askUserQuestionsToCreateRequest(questions, SESSION_ID, undefined) as Extract<
CreateElicitationRequest,
{ mode: "form" }
>
).requestedSchema;
const oneOf = (schema.properties?.["question_0"] as { oneOf: EnumOption[] }).oneOf;
// Both description and preview travel structurally; the title still flattens
// the description for clients that only read const/title.
expect(oneOf[0]).toEqual({
const: "Grid",
title: "Grid — Cards in a responsive grid",
_meta: {
"_claude/askUserQuestionOption": {
description: "Cards in a responsive grid",
preview: "```\n[ ] [ ] [ ]\n[ ] [ ] [ ]\n```",
},
},
});
// Description only → preview omitted from _meta.
expect(oneOf[1]._meta).toEqual({
"_claude/askUserQuestionOption": { description: "Stacked rows" },
});
// Neither → no _meta at all.
expect(oneOf[2]._meta).toBeUndefined();
});
it("includes a per-question optional free-text custom-answer field", () => {
const questions = [
mkQuestion("Which?", [{ label: "A" }, { label: "B" }]),
mkQuestion("What else?", [{ label: "C" }, { label: "D" }]),
];
const schema = (
askUserQuestionsToCreateRequest(questions, SESSION_ID, undefined) as Extract<
CreateElicitationRequest,
@@ -196,7 +255,15 @@ describe("askUserQuestionsToCreateRequest", () => {
>
).requestedSchema;
expect(schema.properties?.["customAnswer"]).toMatchObject({ type: "string", title: "Other" });
// Each question gets its own "Other" box, not one shared form-level field.
expect(schema.properties?.["question_0_custom"]).toMatchObject({
type: "string",
title: "Other",
});
expect(schema.properties?.["question_1_custom"]).toMatchObject({
type: "string",
title: "Other",
});
});
it("builds an array property for multi-select questions and includes per-field question text", () => {
@@ -250,10 +317,10 @@ describe("applyAskElicitationResponse", () => {
});
});
it("maps the free-text custom-answer field to the tool's response", () => {
it("folds a per-question custom answer into that question's answer", () => {
const response = {
action: "accept",
content: { question_0: "A", customAnswer: "something else entirely" },
content: { question_0: "A", question_1_custom: "something else entirely" },
} as CreateElicitationResponse;
expect(applyAskElicitationResponse(response, toolInput, questions)).toEqual({
@@ -261,8 +328,23 @@ describe("applyAskElicitationResponse", () => {
updatedInput: {
questions,
metadata: { source: "test" },
answers: { "Single?": "A" },
response: "something else entirely",
answers: { "Single?": "A", "Multi?": "something else entirely" },
},
});
});
it("prefers a question's custom answer over its selection", () => {
const response = {
action: "accept",
content: { question_0: "A", question_0_custom: " my own take " },
} as CreateElicitationResponse;
expect(applyAskElicitationResponse(response, toolInput, questions)).toEqual({
action: "answered",
updatedInput: {
questions,
metadata: { source: "test" },
answers: { "Single?": "my own take" },
},
});
});
@@ -270,7 +352,7 @@ describe("applyAskElicitationResponse", () => {
it("ignores empty selections and blank custom answers", () => {
const response = {
action: "accept",
content: { question_1: [], customAnswer: " " },
content: { question_1: [], question_0_custom: " " },
} as CreateElicitationResponse;
expect(applyAskElicitationResponse(response, toolInput, questions)).toEqual({

View File

@@ -216,6 +216,31 @@ describe("session config options", () => {
).rejects.toThrow("Invalid value for config option mode: invalid-mode");
});
it("rejects mode and config changes once the query stream has closed (husk session)", async () => {
// After an unexpected stream death the session lingers as a husk
// (queryClosed=true) so prompt() can answer with a clear error. The
// config/mode handlers must do the same rather than calling setModel/
// setPermissionMode on the closed query.
const session = (agent as unknown as { sessions: Record<string, { queryClosed?: boolean }> })
.sessions[SESSION_ID];
session.queryClosed = true;
await expect(
agent.setSessionConfigOption({
sessionId: SESSION_ID,
configId: "model",
value: "claude-sonnet-4-6",
}),
).rejects.toThrow(/start a new session/);
await expect(agent.setSessionMode({ sessionId: SESSION_ID, modeId: "plan" })).rejects.toThrow(
/start a new session/,
);
// Short-circuited before touching the (closed) query.
expect(setModelSpy).not.toHaveBeenCalled();
expect(setPermissionModeSpy).not.toHaveBeenCalled();
});
it("changes mode, sends current_mode_update but not config_option_update", async () => {
await agent.setSessionConfigOption({
sessionId: SESSION_ID,

View File

@@ -502,6 +502,23 @@ describe("Bash terminal output", () => {
});
});
it("should route failed commands through the terminal when supportsTerminalOutput is true", () => {
const toolResult: ToolResultBlockParam = {
type: "tool_result",
tool_use_id: "toolu_bash",
content: "some error output",
is_error: true,
};
const update = toolUpdateFromToolResult(toolResult, bashToolUse, true);
expect(update.content).toEqual([{ type: "terminal", terminalId: "toolu_bash" }]);
expect(update._meta).toEqual({
terminal_info: { terminal_id: "toolu_bash" },
terminal_output: { terminal_id: "toolu_bash", data: "some error output" },
terminal_exit: { terminal_id: "toolu_bash", exit_code: 1, signal: null },
});
});
it("should fall back to stderr when stdout is empty", () => {
const toolResult = makeBashResult("", "some error output", 1);
const update = toolUpdateFromToolResult(toolResult, bashToolUse, false);
@@ -610,10 +627,25 @@ describe("Bash terminal output", () => {
});
});
it("should use error handler when is_error is true (early return before Bash case)", () => {
it("should route is_error through the terminal when supportsTerminalOutput is true", () => {
const toolResult = makeStringBashResult("command not found: bad_cmd", true);
const update = toolUpdateFromToolResult(toolResult, bashToolUse, true);
// Failed Bash commands skip the early error return and reach the Bash
// case so the client receives terminal output with a non-zero exit code
// instead of plain markdown details.
expect(update.content).toEqual([{ type: "terminal", terminalId: "toolu_bash" }]);
expect(update._meta).toEqual({
terminal_info: { terminal_id: "toolu_bash" },
terminal_output: { terminal_id: "toolu_bash", data: "command not found: bad_cmd" },
terminal_exit: { terminal_id: "toolu_bash", exit_code: 1, signal: null },
});
});
it("should use error handler when is_error is true and terminal output is unsupported", () => {
const toolResult = makeStringBashResult("command not found: bad_cmd", true);
const update = toolUpdateFromToolResult(toolResult, bashToolUse, false);
// is_error with content hits the early error return at the top of
// toolUpdateFromToolResult, before reaching the Bash switch case.
// So there's no terminal _meta, just error-formatted content.

View File

@@ -485,7 +485,8 @@ export function toolUpdateFromToolResult(
"is_error" in toolResult &&
toolResult.is_error &&
toolResult.content &&
toolResult.content.length > 0
toolResult.content.length > 0 &&
!(toolUse?.name === "Bash" && supportsTerminalOutput)
) {
// Only return errors
return toAcpContentUpdate(toolResult.content, true);