Compare commits

...

24 Commits

Author SHA1 Message Date
acp-release-bot[bot]
0a501434c0 chore(main): release 0.26.0 (#524)
🤖 I have created a release *beep* *boop*
---


##
[0.26.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.25.3...v0.26.0)
(2026-04-08)


### Features

* Update claude-agent-sdk to 0.2.96
([#526](https://github.com/agentclientprotocol/claude-agent-acp/issues/526))
([c073131](c073131488))


### Bug Fixes

* Remove bun builds from release
([#525](https://github.com/agentclientprotocol/claude-agent-acp/issues/525))
([fcf5aaf](fcf5aaf06d))
* Use TUI login for remote environments
([#523](https://github.com/agentclientprotocol/claude-agent-acp/issues/523))
([cc73e37](cc73e37b41))

---
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-04-08 12:51:09 +02:00
Ben Brandt
c073131488 feat: Update claude-agent-sdk to 0.2.96 (#526) 2026-04-08 12:48:54 +02:00
Ben Brandt
fcf5aaf06d fix: Remove bun builds from release (#525)
The SDK is broken for bun builds, and these had poor support for various
reasons anyway. Going to turn off these pipelines until we can fix.
2026-04-08 10:18:30 +00:00
Ben Brandt
cc73e37b41 fix: Use TUI login for remote environments (#523)
The auth subcommand goes through a flow that requires pasting in a code
on remote environments, but does not allow for pasting that code in.
Until they fix this in the CLI subcommand, we'll have to go to the old
flow of launching the full CLI.
2026-04-08 11:58:48 +02:00
dependabot[bot]
41f04ec31c chore(deps-dev): bump @anthropic-ai/sdk from 0.82.0 to 0.84.0 (#520)
Bumps
[@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript)
from 0.82.0 to 0.84.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/anthropic-sdk-typescript/releases"><code>@​anthropic-ai/sdk</code>'s
releases</a>.</em></p>
<blockquote>
<h2>sdk: v0.84.0</h2>
<h2>0.84.0 (2026-04-07)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.83.0...sdk-v0.84.0">sdk-v0.83.0...sdk-v0.84.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> Add support for claude-mythos-preview (<a
href="d4057b0a95">d4057b0</a>)</li>
<li><strong>tools:</strong> add AbortSignal support for tool runner (<a
href="https://redirect.github.com/anthropics/anthropic-sdk-typescript/issues/848">#848</a>)
(<a
href="972d5918a4">972d591</a>)</li>
</ul>
<h2>sdk: v0.83.0</h2>
<h2>0.83.0 (2026-04-03)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.82.0...sdk-v0.83.0">sdk-v0.82.0...sdk-v0.83.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>vertex:</strong> add support for US multi-region endpoint
(<a
href="5e5aea72e8">5e5aea7</a>)</li>
<li><strong>vertex:</strong> add support for US multi-region endpoint
(<a
href="0de0e98aac">0de0e98</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><strong>client:</strong> deprecate client-side compaction helpers
(<a
href="1926e87039">1926e87</a>)</li>
<li><strong>client:</strong> internal updates (<a
href="3d64763154">3d64763</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"><code>@​anthropic-ai/sdk</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>0.84.0 (2026-04-07)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.83.0...sdk-v0.84.0">sdk-v0.83.0...sdk-v0.84.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> Add support for claude-mythos-preview (<a
href="d4057b0a95">d4057b0</a>)</li>
<li><strong>tools:</strong> add AbortSignal support for tool runner (<a
href="https://redirect.github.com/anthropics/anthropic-sdk-typescript/issues/848">#848</a>)
(<a
href="972d5918a4">972d591</a>)</li>
</ul>
<h2>0.83.0 (2026-04-03)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.82.0...sdk-v0.83.0">sdk-v0.82.0...sdk-v0.83.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>vertex:</strong> add support for US multi-region endpoint
(<a
href="5e5aea72e8">5e5aea7</a>)</li>
<li><strong>vertex:</strong> add support for US multi-region endpoint
(<a
href="0de0e98aac">0de0e98</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><strong>client:</strong> dont upload aws artifact (<a
href="https://redirect.github.com/anthropics/anthropic-sdk-typescript/issues/844">#844</a>)
(<a
href="d1a31fcd59">d1a31fc</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><strong>client:</strong> deprecate client-side compaction helpers
(<a
href="1926e87039">1926e87</a>)</li>
<li><strong>client:</strong> internal updates (<a
href="3d64763154">3d64763</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="4105fd6cf6"><code>4105fd6</code></a>
chore: release main (<a
href="https://redirect.github.com/anthropics/anthropic-sdk-typescript/issues/973">#973</a>)</li>
<li><a
href="0b536ae0e9"><code>0b536ae</code></a>
chore: release main (<a
href="https://redirect.github.com/anthropics/anthropic-sdk-typescript/issues/970">#970</a>)</li>
<li>See full diff in <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.82.0...sdk-v0.84.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@anthropic-ai/sdk&package-manager=npm_and_yarn&previous-version=0.82.0&new-version=0.84.0)](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)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/agentclientprotocol/claude-agent-acp/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-08 08:04:37 +02:00
dependabot[bot]
8acd0bd27f chore(deps): bump @hono/node-server from 1.19.12 to 1.19.13 (#521)
Bumps [@hono/node-server](https://github.com/honojs/node-server) from
1.19.12 to 1.19.13.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/honojs/node-server/releases"><code>@​hono/node-server</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v1.19.13</h2>
<h2>Security Fix</h2>
<p>Fixed an issue in Serve Static Middleware where inconsistent handling
of repeated slashes (<code>//</code>) between the router and static file
resolution could allow middleware to be bypassed. Users of Serve Static
Middleware are encouraged to upgrade to this version.</p>
<p>See GHSA-92pp-h63x-v22m for details.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fd64e659a3"><code>fd64e65</code></a>
1.19.13</li>
<li><a
href="025c30f55d"><code>025c30f</code></a>
Merge commit from fork</li>
<li>See full diff in <a
href="https://github.com/honojs/node-server/compare/v1.19.12...v1.19.13">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@hono/node-server&package-manager=npm_and_yarn&previous-version=1.19.12&new-version=1.19.13)](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)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/agentclientprotocol/claude-agent-acp/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-08 08:04:11 +02:00
dependabot[bot]
4b82236c1f chore(deps): bump hono from 4.12.11 to 4.12.12 (#522)
Bumps [hono](https://github.com/honojs/hono) from 4.12.11 to 4.12.12.
<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.12</h2>
<h2>Security fixes</h2>
<p>This release includes fixes for the following security issues:</p>
<h3>Middleware bypass via repeated slashes in serveStatic</h3>
<p>Affects: Serve Static middleware. Fixes a path normalization
inconsistency where repeated slashes (<code>//</code>) could bypass
route-based middleware protections and allow access to protected static
files. GHSA-wmmm-f939-6g9c</p>
<h3>Path traversal in toSSG() allows writing files outside the output
directory</h3>
<p>Affects: <code>toSSG()</code> for Static Site Generation. Fixes a
path traversal issue where crafted <code>ssgParams</code> values could
write files outside the configured output directory.
GHSA-xf4j-xp2r-rqqx</p>
<h3>Incorrect IP matching in ipRestriction() for IPv4-mapped IPv6
addresses</h3>
<p>Affects: IP Restriction Middleware. Fixes improper handling of
IPv4-mapped IPv6 addresses (e.g. <code>::ffff:127.0.0.1</code>) that
could cause allow/deny rules to be bypassed. GHSA-xpcf-pg52-r92g</p>
<h3>Missing validation of cookie name on write path in setCookie()</h3>
<p>Affects: <code>setCookie()</code>, <code>serialize()</code>, and
<code>serializeSigned()</code> from <code>hono/cookie</code>. Fixes
missing validation of cookie names on the write path, preventing
inconsistent handling between parsing and serialization.
GHSA-26pp-8wgv-hjvm</p>
<h3>Non-breaking space prefix bypass in cookie name handling in
getCookie()</h3>
<p>Affects: <code>getCookie()</code> from <code>hono/cookie</code>.
Fixes a discrepancy in cookie name handling that could allow
attacker-controlled cookies to override legitimate ones and bypass
prefix protections. GHSA-r5rp-j6wh-rvv4</p>
<hr />
<p>Users who use Serve Static, Static Site Generation, Cookie utilities,
or IP restriction middleware are strongly encouraged to upgrade to this
version.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="c37ba26da9"><code>c37ba26</code></a>
4.12.12</li>
<li><a
href="cc067c8559"><code>cc067c8</code></a>
Merge commit from fork</li>
<li><a
href="a586cd72e3"><code>a586cd7</code></a>
Merge commit from fork</li>
<li><a
href="48fa2233bc"><code>48fa223</code></a>
Merge commit from fork</li>
<li><a
href="b470278920"><code>b470278</code></a>
Merge commit from fork</li>
<li><a
href="9aff14bd72"><code>9aff14b</code></a>
Merge commit from fork</li>
<li>See full diff in <a
href="https://github.com/honojs/hono/compare/v4.12.11...v4.12.12">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=hono&package-manager=npm_and_yarn&previous-version=4.12.11&new-version=4.12.12)](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)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/agentclientprotocol/claude-agent-acp/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-08 08:03:57 +02:00
acp-release-bot[bot]
0111786af2 chore(main): release 0.25.3 (#514)
🤖 I have created a release *beep* *boop*
---


##
[0.25.3](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.25.2...v0.25.3)
(2026-04-06)


### Bug Fixes

* Drop claude-agent-sdk back to 0.2.91 to fix broken import
([#513](https://github.com/agentclientprotocol/claude-agent-acp/issues/513))
([26f3e8a](26f3e8a521))
* Recreate resumed sessions when params change
([#515](https://github.com/agentclientprotocol/claude-agent-acp/issues/515))
([aa82193](aa82193330))

---
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-04-06 22:45:35 +02:00
Ben Brandt
aa82193330 fix: Recreate resumed sessions when params change (#515)
Closes #512

Fingerprint session-defining params to detect cwd or MCP server
changes, reuse sessions when unchanged, and ignore MCP server
ordering differences. Extract session teardown into a helper and add
tests covering reuse and recreation paths.
2026-04-06 22:44:14 +02:00
Ben Brandt
26f3e8a521 fix: Drop claude-agent-sdk back to 0.2.91 to fix broken import (#513)
Seems they released with a missing file that breaks the release builds.
2026-04-06 19:59:41 +00:00
acp-release-bot[bot]
769255c9a9 chore(main): release 0.25.2 (#511)
🤖 I have created a release *beep* *boop*
---


##
[0.25.2](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.25.1...v0.25.2)
(2026-04-06)


### Bug Fixes

* prioritize ANTHROPIC_MODEL env var over settings.model in model …
([#505](https://github.com/agentclientprotocol/claude-agent-acp/issues/505))
([bea1a40](bea1a40e9b))

---
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-04-06 21:50:32 +02:00
soddygo
bea1a40e9b fix: prioritize ANTHROPIC_MODEL env var over settings.model in model … (#505)
Title:
fix: ANTHROPIC_MODEL env var not respected in ACP agent model selection
                                                                  
Body:
   
## Summary
                                                                  
The `ANTHROPIC_MODEL` environment variable is not being respected when
using Claude Code via the ACP (Agent Client Protocol). This causes users
who set their preferred model via
environment variable to have their setting ignored, with the default
model (`claude-sonnet-4-6`) being used instead.
  ## Problem                                                      

When using Claude Code through ACP integrations (e.g., agent platforms),
users expect the `ANTHROPIC_MODEL` environment variable to control which
model is used for LLM requests.
However, the current implementation only checks `settings.model` (from
configuration files) and completely ignores `ANTHROPIC_MODEL`.
  ## Root Cause                                                   

In `src/acp-agent.ts`, the `getAvailableModels` function only checks
`settings.model`:

  ```typescript
  let currentModel = models[0];

if (settings.model) {
    const match = resolveModelPreference(models, settings.model);
if (match) {
      currentModel = match;                                       
    }
  }

The ANTHROPIC_MODEL environment variable is never read, so
environment-based model configuration is silently ignored.
   
Reproduction
                                                                  
1. Set ANTHROPIC_MODEL=glm-4.7 (or any custom model)
  2. Start Claude Code via ACP protocol
3. Send a prompt request
4. Capture network traffic - the actual model used is claude-sonnet-4-6
instead of glm-4.7
  Fix
Added priority-based model selection that respects the ANTHROPIC_MODEL
environment variable, aligning with the main Claude Code CLI behavior:
   
// Model priority (highest to lowest):
  // 1. ANTHROPIC_MODEL environment variable                      
  // 2. settings.model (user configuration)
// 3. models[0] (default first model)
  if (process.env.ANTHROPIC_MODEL) {
const match = resolveModelPreference(models,
process.env.ANTHROPIC_MODEL);
    if (match) {                                                  
      currentModel = match;
    }
  } else if (settings.model) {
const match = resolveModelPreference(models, settings.model);
    if (match) {
currentModel = match;
    }                                                             
  }

This matches the model selection priority used by the main Claude Code
CLI.
   
Testing
                                                                  
- Verified ANTHROPIC_MODEL is now respected when set
  - Verified settings.model still works when ANTHROPIC_MODEL is not set
- Verified default model (models[0]) is used when neither is set
  Breaking Change
None - this fix makes behavior more consistent with user expectations
and the main CLI.
2026-04-06 19:48:24 +00:00
dependabot[bot]
f9b15ba1c5 chore(deps): bump the minor group with 10 updates (#510)
Bumps the minor group with 10 updates:

| Package | From | To |
| --- | --- | --- |
|
[@anthropic-ai/claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk-typescript)
| `0.2.91` | `0.2.92` |
|
[@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)
| `25.5.1` | `25.5.2` |
| [eslint](https://github.com/eslint/eslint) | `10.1.0` | `10.2.0` |
|
[@eslint/config-array](https://github.com/eslint/rewrite/tree/HEAD/packages/config-array)
| `0.23.3` | `0.23.4` |
|
[@eslint/config-helpers](https://github.com/eslint/rewrite/tree/HEAD/packages/config-helpers)
| `0.5.3` | `0.5.4` |
|
[@eslint/core](https://github.com/eslint/rewrite/tree/HEAD/packages/core)
| `1.1.1` | `1.2.0` |
|
[@eslint/object-schema](https://github.com/eslint/rewrite/tree/HEAD/packages/object-schema)
| `3.0.3` | `3.0.4` |
|
[@eslint/plugin-kit](https://github.com/eslint/rewrite/tree/HEAD/packages/plugin-kit)
| `0.6.1` | `0.7.0` |
| [hono](https://github.com/honojs/hono) | `4.12.10` | `4.12.11` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) |
`8.0.3` | `8.0.5` |

Updates `@anthropic-ai/claude-agent-sdk` from 0.2.91 to 0.2.92
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/claude-agent-sdk-typescript/releases"><code>@​anthropic-ai/claude-agent-sdk</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v0.2.92</h2>
<h2>What's changed</h2>
<ul>
<li>Updated to parity with Claude Code v2.1.92</li>
</ul>
<h2>Update</h2>
<pre lang="sh"><code>npm install @anthropic-ai/claude-agent-sdk@0.2.92
# or
yarn add @anthropic-ai/claude-agent-sdk@0.2.92
# or
pnpm add @anthropic-ai/claude-agent-sdk@0.2.92
# or
bun add @anthropic-ai/claude-agent-sdk@0.2.92
</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"><code>@​anthropic-ai/claude-agent-sdk</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>0.2.92</h2>
<ul>
<li>Updated to parity with Claude Code v2.1.92</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="4d9db79513"><code>4d9db79</code></a>
chore: Update CHANGELOG.md</li>
<li>See full diff in <a
href="https://github.com/anthropics/claude-agent-sdk-typescript/compare/v0.2.91...v0.2.92">compare
view</a></li>
</ul>
</details>
<br />

Updates `@types/node` from 25.5.1 to 25.5.2
<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.1.0 to 10.2.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.2.0</h2>
<h2>Features</h2>
<ul>
<li><a
href="586ec2f430"><code>586ec2f</code></a>
feat: Add <code>meta.languages</code> support to rules (<a
href="https://redirect.github.com/eslint/eslint/issues/20571">#20571</a>)
(Copilot)</li>
<li><a
href="14207dee39"><code>14207de</code></a>
feat: add <code>Temporal</code> to <code>no-obj-calls</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20675">#20675</a>)
(Pixel998)</li>
<li><a
href="bbb2c93a2b"><code>bbb2c93</code></a>
feat: add Temporal to ES2026 globals (<a
href="https://redirect.github.com/eslint/eslint/issues/20672">#20672</a>)
(Pixel998)</li>
</ul>
<h2>Bug Fixes</h2>
<ul>
<li><a
href="542cb3e644"><code>542cb3e</code></a>
fix: update first-party dependencies (<a
href="https://redirect.github.com/eslint/eslint/issues/20714">#20714</a>)
(Francesco Trotta)</li>
</ul>
<h2>Documentation</h2>
<ul>
<li><a
href="a2af743ea6"><code>a2af743</code></a>
docs: add <code>language</code> to configuration objects (<a
href="https://redirect.github.com/eslint/eslint/issues/20712">#20712</a>)
(Francesco Trotta)</li>
<li><a
href="845f23f137"><code>845f23f</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="5fbcf5958b"><code>5fbcf59</code></a>
docs: remove <code>sourceType</code> from ts playground link (<a
href="https://redirect.github.com/eslint/eslint/issues/20477">#20477</a>)
(Tanuj Kanti)</li>
<li><a
href="8702a47465"><code>8702a47</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="ddeaded2ab"><code>ddeaded</code></a>
docs: Update README (GitHub Actions Bot)</li>
<li><a
href="2b44966912"><code>2b44966</code></a>
docs: add Major Releases section to Manage Releases (<a
href="https://redirect.github.com/eslint/eslint/issues/20269">#20269</a>)
(Milos Djermanovic)</li>
<li><a
href="eab65c700e"><code>eab65c7</code></a>
docs: update <code>eslint</code> versions in examples (<a
href="https://redirect.github.com/eslint/eslint/issues/20664">#20664</a>)
(루밀LuMir)</li>
<li><a
href="3e4a29903b"><code>3e4a299</code></a>
docs: update ESM Dependencies policies with note for own-usage packages
(<a
href="https://redirect.github.com/eslint/eslint/issues/20660">#20660</a>)
(Milos Djermanovic)</li>
</ul>
<h2>Chores</h2>
<ul>
<li><a
href="8120e30f83"><code>8120e30</code></a>
refactor: extract no unmodified loop condition (<a
href="https://redirect.github.com/eslint/eslint/issues/20679">#20679</a>)
(kuldeep kumar)</li>
<li><a
href="46e8469786"><code>46e8469</code></a>
chore: update dependency markdownlint-cli2 to ^0.22.0 (<a
href="https://redirect.github.com/eslint/eslint/issues/20697">#20697</a>)
(renovate[bot])</li>
<li><a
href="01ed3aa684"><code>01ed3aa</code></a>
test: add unit tests for unicode utilities (<a
href="https://redirect.github.com/eslint/eslint/issues/20622">#20622</a>)
(Manish chaudhary)</li>
<li><a
href="811f4930f8"><code>811f493</code></a>
ci: remove <code>--legacy-peer-deps</code> from types integration tests
(<a
href="https://redirect.github.com/eslint/eslint/issues/20667">#20667</a>)
(Milos Djermanovic)</li>
<li><a
href="6b86fcfc5c"><code>6b86fcf</code></a>
chore: update dependency npm-run-all2 to v8 (<a
href="https://redirect.github.com/eslint/eslint/issues/20663">#20663</a>)
(renovate[bot])</li>
<li><a
href="632c4f83bf"><code>632c4f8</code></a>
chore: add <code>prettier</code> update commit to
<code>.git-blame-ignore-revs</code> (<a
href="https://redirect.github.com/eslint/eslint/issues/20662">#20662</a>)
(루밀LuMir)</li>
<li><a
href="b0b0f21927"><code>b0b0f21</code></a>
chore: update dependency eslint-plugin-regexp to ^3.1.0 (<a
href="https://redirect.github.com/eslint/eslint/issues/20659">#20659</a>)
(Milos Djermanovic)</li>
<li><a
href="228a2dd4b2"><code>228a2dd</code></a>
chore: update dependency eslint-plugin-eslint-plugin to ^7.3.2 (<a
href="https://redirect.github.com/eslint/eslint/issues/20661">#20661</a>)
(Milos Djermanovic)</li>
<li><a
href="3ab4d7e244"><code>3ab4d7e</code></a>
test: Add tests for eslintrc-style keys (<a
href="https://redirect.github.com/eslint/eslint/issues/20645">#20645</a>)
(kuldeep kumar)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="000128c292"><code>000128c</code></a>
10.2.0</li>
<li><a
href="1988fad70e"><code>1988fad</code></a>
Build: changelog update for 10.2.0</li>
<li><a
href="542cb3e644"><code>542cb3e</code></a>
fix: update first-party dependencies (<a
href="https://redirect.github.com/eslint/eslint/issues/20714">#20714</a>)</li>
<li><a
href="a2af743ea6"><code>a2af743</code></a>
docs: add <code>language</code> to configuration objects (<a
href="https://redirect.github.com/eslint/eslint/issues/20712">#20712</a>)</li>
<li><a
href="845f23f137"><code>845f23f</code></a>
docs: Update README</li>
<li><a
href="5fbcf5958b"><code>5fbcf59</code></a>
docs: remove <code>sourceType</code> from ts playground link (<a
href="https://redirect.github.com/eslint/eslint/issues/20477">#20477</a>)</li>
<li><a
href="8702a47465"><code>8702a47</code></a>
docs: Update README</li>
<li><a
href="ddeaded2ab"><code>ddeaded</code></a>
docs: Update README</li>
<li><a
href="8120e30f83"><code>8120e30</code></a>
refactor: extract no unmodified loop condition (<a
href="https://redirect.github.com/eslint/eslint/issues/20679">#20679</a>)</li>
<li><a
href="46e8469786"><code>46e8469</code></a>
chore: update dependency markdownlint-cli2 to ^0.22.0 (<a
href="https://redirect.github.com/eslint/eslint/issues/20697">#20697</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/eslint/eslint/compare/v10.1.0...v10.2.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `@eslint/config-array` from 0.23.3 to 0.23.4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/rewrite/releases"><code>@​eslint/config-array</code>'s
releases</a>.</em></p>
<blockquote>
<h2>config-array: v0.23.4</h2>
<h2><a
href="https://github.com/eslint/rewrite/compare/config-array-v0.23.3...config-array-v0.23.4">0.23.4</a>
(2026-04-03)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>re-export ESM types in CommonJS (<a
href="https://redirect.github.com/eslint/rewrite/issues/416">#416</a>)
(<a
href="ef16f80b92">ef16f80</a>)</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@​eslint/object-schema</code> bumped from ^3.0.3 to
^3.0.4</li>
</ul>
</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/rewrite/blob/main/packages/config-array/CHANGELOG.md"><code>@​eslint/config-array</code>'s
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/eslint/rewrite/compare/config-array-v0.23.3...config-array-v0.23.4">0.23.4</a>
(2026-04-03)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>re-export ESM types in CommonJS (<a
href="https://redirect.github.com/eslint/rewrite/issues/416">#416</a>)
(<a
href="ef16f80b92">ef16f80</a>)</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@​eslint/object-schema</code> bumped from ^3.0.3 to
^3.0.4</li>
</ul>
</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fe114eed69"><code>fe114ee</code></a>
chore: release main (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/config-array/issues/413">#413</a>)</li>
<li><a
href="8863791972"><code>8863791</code></a>
docs: Update README sponsors</li>
<li><a
href="ef16f80b92"><code>ef16f80</code></a>
fix: re-export ESM types in CommonJS (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/config-array/issues/416">#416</a>)</li>
<li><a
href="835ddf95b0"><code>835ddf9</code></a>
docs: Update README sponsors</li>
<li><a
href="8cd3676402"><code>8cd3676</code></a>
docs: Update README sponsors</li>
<li><a
href="4d734592f3"><code>4d73459</code></a>
docs: Update README sponsors</li>
<li>See full diff in <a
href="https://github.com/eslint/rewrite/commits/config-array-v0.23.4/packages/config-array">compare
view</a></li>
</ul>
</details>
<br />

Updates `@eslint/config-helpers` from 0.5.3 to 0.5.4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/rewrite/releases"><code>@​eslint/config-helpers</code>'s
releases</a>.</em></p>
<blockquote>
<h2>config-helpers: v0.5.4</h2>
<h2><a
href="https://github.com/eslint/rewrite/compare/config-helpers-v0.5.3...config-helpers-v0.5.4">0.5.4</a>
(2026-04-03)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>re-export ESM types in CommonJS (<a
href="https://redirect.github.com/eslint/rewrite/issues/416">#416</a>)
(<a
href="ef16f80b92">ef16f80</a>)</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@​eslint/core</code> bumped from ^1.1.1 to ^1.2.0</li>
</ul>
</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/rewrite/blob/main/packages/config-helpers/CHANGELOG.md"><code>@​eslint/config-helpers</code>'s
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/eslint/rewrite/compare/config-helpers-v0.5.3...config-helpers-v0.5.4">0.5.4</a>
(2026-04-03)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>re-export ESM types in CommonJS (<a
href="https://redirect.github.com/eslint/rewrite/issues/416">#416</a>)
(<a
href="ef16f80b92">ef16f80</a>)</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@​eslint/core</code> bumped from ^1.1.1 to ^1.2.0</li>
</ul>
</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fe114eed69"><code>fe114ee</code></a>
chore: release main (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/config-helpers/issues/413">#413</a>)</li>
<li><a
href="8863791972"><code>8863791</code></a>
docs: Update README sponsors</li>
<li><a
href="ef16f80b92"><code>ef16f80</code></a>
fix: re-export ESM types in CommonJS (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/config-helpers/issues/416">#416</a>)</li>
<li><a
href="835ddf95b0"><code>835ddf9</code></a>
docs: Update README sponsors</li>
<li><a
href="8cd3676402"><code>8cd3676</code></a>
docs: Update README sponsors</li>
<li><a
href="4d734592f3"><code>4d73459</code></a>
docs: Update README sponsors</li>
<li><a
href="a6c7a26a85"><code>a6c7a26</code></a>
chore: update <code>eslint</code> and <code>eslint-config-eslint</code>
(<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/config-helpers/issues/401">#401</a>)</li>
<li>See full diff in <a
href="https://github.com/eslint/rewrite/commits/config-helpers-v0.5.4/packages/config-helpers">compare
view</a></li>
</ul>
</details>
<br />

Updates `@eslint/core` from 1.1.1 to 1.2.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/rewrite/releases"><code>@​eslint/core</code>'s
releases</a>.</em></p>
<blockquote>
<h2>core: v1.2.0</h2>
<h2><a
href="https://github.com/eslint/rewrite/compare/core-v1.1.1...core-v1.2.0">1.2.0</a>
(2026-04-03)</h2>
<h3>Features</h3>
<ul>
<li>add <code>languages</code> and <code>docs.dialects</code> to rule
<code>meta</code> types (<a
href="https://redirect.github.com/eslint/rewrite/issues/421">#421</a>)
(<a
href="7680f69211">7680f69</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>re-export ESM types in CommonJS (<a
href="https://redirect.github.com/eslint/rewrite/issues/416">#416</a>)
(<a
href="ef16f80b92">ef16f80</a>)</li>
<li>type-check defaultLanguageOptions against LangOptions (<a
href="https://redirect.github.com/eslint/rewrite/issues/420">#420</a>)
(<a
href="7bf57046b8">7bf5704</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/rewrite/blob/main/packages/core/CHANGELOG.md"><code>@​eslint/core</code>'s
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/eslint/rewrite/compare/core-v1.1.1...core-v1.2.0">1.2.0</a>
(2026-04-03)</h2>
<h3>Features</h3>
<ul>
<li>add <code>languages</code> and <code>docs.dialects</code> to rule
<code>meta</code> types (<a
href="https://redirect.github.com/eslint/rewrite/issues/421">#421</a>)
(<a
href="7680f69211">7680f69</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>re-export ESM types in CommonJS (<a
href="https://redirect.github.com/eslint/rewrite/issues/416">#416</a>)
(<a
href="ef16f80b92">ef16f80</a>)</li>
<li>type-check defaultLanguageOptions against LangOptions (<a
href="https://redirect.github.com/eslint/rewrite/issues/420">#420</a>)
(<a
href="7bf57046b8">7bf5704</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fe114eed69"><code>fe114ee</code></a>
chore: release main (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/core/issues/413">#413</a>)</li>
<li><a
href="7680f69211"><code>7680f69</code></a>
feat: add <code>languages</code> and <code>docs.dialects</code> to rule
<code>meta</code> types (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/core/issues/421">#421</a>)</li>
<li><a
href="8863791972"><code>8863791</code></a>
docs: Update README sponsors</li>
<li><a
href="ef16f80b92"><code>ef16f80</code></a>
fix: re-export ESM types in CommonJS (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/core/issues/416">#416</a>)</li>
<li><a
href="835ddf95b0"><code>835ddf9</code></a>
docs: Update README sponsors</li>
<li><a
href="8cd3676402"><code>8cd3676</code></a>
docs: Update README sponsors</li>
<li><a
href="7bf57046b8"><code>7bf5704</code></a>
fix: type-check defaultLanguageOptions against LangOptions (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/core/issues/420">#420</a>)</li>
<li><a
href="4d734592f3"><code>4d73459</code></a>
docs: Update README sponsors</li>
<li>See full diff in <a
href="https://github.com/eslint/rewrite/commits/core-v1.2.0/packages/core">compare
view</a></li>
</ul>
</details>
<br />

Updates `@eslint/object-schema` from 3.0.3 to 3.0.4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/rewrite/releases"><code>@​eslint/object-schema</code>'s
releases</a>.</em></p>
<blockquote>
<h2>object-schema: v3.0.4</h2>
<h2><a
href="https://github.com/eslint/rewrite/compare/object-schema-v3.0.3...object-schema-v3.0.4">3.0.4</a>
(2026-04-03)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>avoid mutating object schema definitions during construction (<a
href="https://redirect.github.com/eslint/rewrite/issues/412">#412</a>)
(<a
href="f0fd9a2ff7">f0fd9a2</a>)</li>
<li>correct ValidationStrategy parameter types (<a
href="https://redirect.github.com/eslint/rewrite/issues/406">#406</a>)
(<a
href="42a30eaae5">42a30ea</a>)</li>
<li>re-export ESM types in CommonJS (<a
href="https://redirect.github.com/eslint/rewrite/issues/416">#416</a>)
(<a
href="ef16f80b92">ef16f80</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/rewrite/blob/main/packages/object-schema/CHANGELOG.md"><code>@​eslint/object-schema</code>'s
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/eslint/rewrite/compare/object-schema-v3.0.3...object-schema-v3.0.4">3.0.4</a>
(2026-04-03)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>avoid mutating object schema definitions during construction (<a
href="https://redirect.github.com/eslint/rewrite/issues/412">#412</a>)
(<a
href="f0fd9a2ff7">f0fd9a2</a>)</li>
<li>correct ValidationStrategy parameter types (<a
href="https://redirect.github.com/eslint/rewrite/issues/406">#406</a>)
(<a
href="42a30eaae5">42a30ea</a>)</li>
<li>re-export ESM types in CommonJS (<a
href="https://redirect.github.com/eslint/rewrite/issues/416">#416</a>)
(<a
href="ef16f80b92">ef16f80</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fe114eed69"><code>fe114ee</code></a>
chore: release main (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/object-schema/issues/413">#413</a>)</li>
<li><a
href="8863791972"><code>8863791</code></a>
docs: Update README sponsors</li>
<li><a
href="ef16f80b92"><code>ef16f80</code></a>
fix: re-export ESM types in CommonJS (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/object-schema/issues/416">#416</a>)</li>
<li><a
href="835ddf95b0"><code>835ddf9</code></a>
docs: Update README sponsors</li>
<li><a
href="8cd3676402"><code>8cd3676</code></a>
docs: Update README sponsors</li>
<li><a
href="b281abb94e"><code>b281abb</code></a>
docs: clarify ValidationStrategy object behavior (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/object-schema/issues/415">#415</a>)</li>
<li><a
href="42a30eaae5"><code>42a30ea</code></a>
fix: correct ValidationStrategy parameter types (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/object-schema/issues/406">#406</a>)</li>
<li><a
href="f0fd9a2ff7"><code>f0fd9a2</code></a>
fix: avoid mutating object schema definitions during construction (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/object-schema/issues/412">#412</a>)</li>
<li><a
href="9189536016"><code>9189536</code></a>
refactor: use lowercase boolean in validation errors (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/object-schema/issues/405">#405</a>)</li>
<li><a
href="4d734592f3"><code>4d73459</code></a>
docs: Update README sponsors</li>
<li>See full diff in <a
href="https://github.com/eslint/rewrite/commits/object-schema-v3.0.4/packages/object-schema">compare
view</a></li>
</ul>
</details>
<br />

Updates `@eslint/plugin-kit` from 0.6.1 to 0.7.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/rewrite/releases"><code>@​eslint/plugin-kit</code>'s
releases</a>.</em></p>
<blockquote>
<h2>plugin-kit: v0.7.0</h2>
<h2><a
href="https://github.com/eslint/rewrite/compare/plugin-kit-v0.6.1...plugin-kit-v0.7.0">0.7.0</a>
(2026-04-03)</h2>
<h3>Features</h3>
<ul>
<li>add <code>languages</code> and <code>docs.dialects</code> to rule
<code>meta</code> types (<a
href="https://redirect.github.com/eslint/rewrite/issues/421">#421</a>)
(<a
href="7680f69211">7680f69</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>re-export ESM types in CommonJS (<a
href="https://redirect.github.com/eslint/rewrite/issues/416">#416</a>)
(<a
href="ef16f80b92">ef16f80</a>)</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@​eslint/core</code> bumped from ^1.1.1 to ^1.2.0</li>
</ul>
</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/rewrite/blob/main/packages/plugin-kit/CHANGELOG.md"><code>@​eslint/plugin-kit</code>'s
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/eslint/rewrite/compare/plugin-kit-v0.6.1...plugin-kit-v0.7.0">0.7.0</a>
(2026-04-03)</h2>
<h3>Features</h3>
<ul>
<li>add <code>languages</code> and <code>docs.dialects</code> to rule
<code>meta</code> types (<a
href="https://redirect.github.com/eslint/rewrite/issues/421">#421</a>)
(<a
href="7680f69211">7680f69</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>re-export ESM types in CommonJS (<a
href="https://redirect.github.com/eslint/rewrite/issues/416">#416</a>)
(<a
href="ef16f80b92">ef16f80</a>)</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@​eslint/core</code> bumped from ^1.1.1 to ^1.2.0</li>
</ul>
</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="80eb5455aa"><code>80eb545</code></a>
chore: release main (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/plugin-kit/issues/124">#124</a>)</li>
<li><a
href="0008606415"><code>0008606</code></a>
docs: Use prerendered sponsors for README (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/plugin-kit/issues/122">#122</a>)</li>
<li><a
href="169d83bf82"><code>169d83b</code></a>
docs: Update README sponsors</li>
<li><a
href="8d2509a218"><code>8d2509a</code></a>
docs: Update README sponsors</li>
<li><a
href="dcacd03f4b"><code>dcacd03</code></a>
docs: Update README sponsors</li>
<li><a
href="002a6da6e3"><code>002a6da</code></a>
docs: Update README sponsors</li>
<li><a
href="5cb3dad034"><code>5cb3dad</code></a>
docs: Update README sponsors</li>
<li><a
href="dc69bd15a5"><code>dc69bd1</code></a>
docs: Update README sponsors</li>
<li><a
href="47db20bc82"><code>47db20b</code></a>
docs: Update README sponsors</li>
<li><a
href="9dbefdff4f"><code>9dbefdf</code></a>
docs: Update README sponsors</li>
<li>Additional commits viewable in <a
href="https://github.com/eslint/rewrite/commits/core-v0.7.0/packages/plugin-kit">compare
view</a></li>
</ul>
</details>
<br />

Updates `hono` from 4.12.10 to 4.12.11
<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.11</h2>
<h2>What's Changed</h2>
<ul>
<li>feat(css): add classNameSlug option to createCssContext by <a
href="https://github.com/flow-pie"><code>@​flow-pie</code></a> in <a
href="https://redirect.github.com/honojs/hono/pull/4834">honojs/hono#4834</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/flow-pie"><code>@​flow-pie</code></a>
made their first contribution in <a
href="https://redirect.github.com/honojs/hono/pull/4834">honojs/hono#4834</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/honojs/hono/compare/v4.12.10...v4.12.11">https://github.com/honojs/hono/compare/v4.12.10...v4.12.11</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="2c403c67eb"><code>2c403c6</code></a>
4.12.11</li>
<li><a
href="f82aba8e8e"><code>f82aba8</code></a>
feat(css): add classNameSlug option to createCssContext (<a
href="https://redirect.github.com/honojs/hono/issues/4834">#4834</a>)</li>
<li>See full diff in <a
href="https://github.com/honojs/hono/compare/v4.12.10...v4.12.11">compare
view</a></li>
</ul>
</details>
<br />

Updates `vite` from 8.0.3 to 8.0.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitejs/vite/releases">vite's
releases</a>.</em></p>
<blockquote>
<h2>v8.0.5</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v8.0.5/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v8.0.4</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v8.0.4/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md">vite's
changelog</a>.</em></p>
<blockquote>
<h2><!-- raw HTML omitted --><a
href="https://github.com/vitejs/vite/compare/v8.0.4...v8.0.5">8.0.5</a>
(2026-04-06)<!-- raw HTML omitted --></h2>
<h3>Bug Fixes</h3>
<ul>
<li>apply server.fs check to env transport (<a
href="https://redirect.github.com/vitejs/vite/issues/22159">#22159</a>)
(<a
href="f02d9fde0b">f02d9fd</a>)</li>
<li>avoid path traversal with optimize deps sourcemap handler (<a
href="https://redirect.github.com/vitejs/vite/issues/22161">#22161</a>)
(<a
href="79f002f228">79f002f</a>)</li>
<li>check <code>server.fs</code> after stripping query as well (<a
href="https://redirect.github.com/vitejs/vite/issues/22160">#22160</a>)
(<a
href="a9a3df2993">a9a3df2</a>)</li>
<li>disallow referencing files outside the package from sourcemap (<a
href="https://redirect.github.com/vitejs/vite/issues/22158">#22158</a>)
(<a
href="f05f501734">f05f501</a>)</li>
</ul>
<h2><!-- raw HTML omitted --><a
href="https://github.com/vitejs/vite/compare/v8.0.3...v8.0.4">8.0.4</a>
(2026-04-06)<!-- raw HTML omitted --></h2>
<h3>Features</h3>
<ul>
<li>allow esbuild 0.28 as peer deps (<a
href="https://redirect.github.com/vitejs/vite/issues/22155">#22155</a>)
(<a
href="b0da97372f">b0da973</a>)</li>
<li><strong>hmr:</strong> truncate list of files on hmr update (<a
href="https://redirect.github.com/vitejs/vite/issues/21535">#21535</a>)
(<a
href="d00e806d7b">d00e806</a>)</li>
<li><strong>optimizer:</strong> log when dependency scanning or bundling
takes over 1s (<a
href="https://redirect.github.com/vitejs/vite/issues/21797">#21797</a>)
(<a
href="f61a1ab33b">f61a1ab</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><code>hasBothRollupOptionsAndRolldownOptions</code> should return
<code>false</code> for proxy case (<a
href="https://redirect.github.com/vitejs/vite/issues/22043">#22043</a>)
(<a
href="99897d27b4">99897d2</a>)</li>
<li>add types for <code>vite/modulepreload-polyfill</code> (<a
href="https://redirect.github.com/vitejs/vite/issues/22126">#22126</a>)
(<a
href="17330d2b9e">17330d2</a>)</li>
<li><strong>deps:</strong> update all non-major dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/22073">#22073</a>)
(<a
href="6daa10ff1e">6daa10f</a>)</li>
<li><strong>deps:</strong> update all non-major dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/22143">#22143</a>)
(<a
href="22b0166127">22b0166</a>)</li>
<li><strong>resolve:</strong> resolve tsconfig paths starting with
<code>#</code> (<a
href="https://redirect.github.com/vitejs/vite/issues/22038">#22038</a>)
(<a
href="3460fc55aa">3460fc5</a>)</li>
<li><strong>ssr:</strong> use browser platform for webworker SSR builds
(fix <a
href="https://redirect.github.com/vitejs/vite/issues/21969">#21969</a>)
(<a
href="https://redirect.github.com/vitejs/vite/issues/21963">#21963</a>)
(<a
href="364c2273a1">364c227</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>add <code>environment.fetchModule</code> documentation (<a
href="https://redirect.github.com/vitejs/vite/issues/22035">#22035</a>)
(<a
href="54229e7863">54229e7</a>)</li>
</ul>
<h3>Miscellaneous Chores</h3>
<ul>
<li><strong>deps:</strong> update rolldown-related dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/21989">#21989</a>)
(<a
href="0ded627457">0ded627</a>)</li>
</ul>
<h3>Code Refactoring</h3>
<ul>
<li>upgrade to typescript 6 (<a
href="https://redirect.github.com/vitejs/vite/issues/22110">#22110</a>)
(<a
href="cc41398c2c">cc41398</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="1a12d4ca4c"><code>1a12d4c</code></a>
release: v8.0.5</li>
<li><a
href="79f002f228"><code>79f002f</code></a>
fix: avoid path traversal with optimize deps sourcemap handler (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22161">#22161</a>)</li>
<li><a
href="a9a3df2993"><code>a9a3df2</code></a>
fix: check <code>server.fs</code> after stripping query as well (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22160">#22160</a>)</li>
<li><a
href="f02d9fde0b"><code>f02d9fd</code></a>
fix: apply server.fs check to env transport (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22159">#22159</a>)</li>
<li><a
href="f05f501734"><code>f05f501</code></a>
fix: disallow referencing files outside the package from sourcemap (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22158">#22158</a>)</li>
<li><a
href="7339bdc915"><code>7339bdc</code></a>
release: v8.0.4</li>
<li><a
href="54229e7863"><code>54229e7</code></a>
docs: add <code>environment.fetchModule</code> documentation (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22035">#22035</a>)</li>
<li><a
href="b0da97372f"><code>b0da973</code></a>
feat: allow esbuild 0.28 as peer deps (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22155">#22155</a>)</li>
<li><a
href="22b0166127"><code>22b0166</code></a>
fix(deps): update all non-major dependencies (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22143">#22143</a>)</li>
<li><a
href="17330d2b9e"><code>17330d2</code></a>
fix: add types for <code>vite/modulepreload-polyfill</code> (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/22126">#22126</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/vitejs/vite/commits/v8.0.5/packages/vite">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-04-06 19:31:14 +02:00
acp-release-bot[bot]
0990a8e520 chore(main): release 0.25.1 (#509)
🤖 I have created a release *beep* *boop*
---


##
[0.25.1](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.25.0...v0.25.1)
(2026-04-06)


### Bug Fixes

* add `auto` to valid modes in applySessionMode to fix mode cycling
([#507](https://github.com/agentclientprotocol/claude-agent-acp/issues/507))
([15e91fb](15e91fb5c3))

---
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-04-06 09:01:18 +02:00
K4YT3X
15e91fb5c3 fix: add auto to valid modes in applySessionMode to fix mode cycling (#507)
ACP version is `v0.25.0`. Should be the newest.

I get this error when pressing Shift+Tab to cycle through the modes:

```
Caused by:
    RPC request LspQuery failed: unknown buffer id 12884902333
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: Error handling request {
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: jsonrpc: '2.0',
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: id: 48,
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: method: 'session/set_config_option',
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: params: {
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: sessionId: '$UUID_GOES_HERE',
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: configId: 'mode',
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: value: 'auto'
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: }
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: } {
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: code: -32603,
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: message: 'Internal error',
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: data: { details: 'Invalid Mode' }
2026-04-05T21:46:02+00:00 WARN  [agent_servers::acp] agent stderr: }
2026-04-05T21:46:02+00:00 ERROR [agent_ui::config_options] Failed to set config option: Internal error: {
  "details": "Invalid Mode"
}
```

I looked through the code on both sides and I think what might be
happening is, here are the modes:


f422c7c954/src/acp-agent.ts (L236-L244)

When a user gets to `bypassPermissions` and cycle again, the next
selected mode is `auto` but that option seems to be missing from here:


f422c7c954/src/acp-agent.ts (L1007-L1013)

Could the maintainers please help verify and test?

Signed-off-by: k4yt3x <i@k4yt3x.com>
2026-04-06 06:59:16 +00:00
acp-release-bot[bot]
f422c7c954 chore(main): release 0.25.0 (#489)
🤖 I have created a release *beep* *boop*
---


##
[0.25.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.24.2...v0.25.0)
(2026-04-03)


### Features

* Add auto permission mode support
([#501](https://github.com/agentclientprotocol/claude-agent-acp/issues/501))
([a161453](a16145396f))
* Add separate Claude and Console terminal logins
([#502](https://github.com/agentclientprotocol/claude-agent-acp/issues/502))
([063cd35](063cd35380))
* Update to claude-agent-sdk 0.2.91
([#500](https://github.com/agentclientprotocol/claude-agent-acp/issues/500))
([65a2230](65a2230385))


### Bug Fixes

* log warnings for malformed settings files instead of silent fallback
([#486](https://github.com/agentclientprotocol/claude-agent-acp/issues/486))
([ae6c388](ae6c388314))
* prevent race conditions in SettingsManager setCwd and debounce
([#485](https://github.com/agentclientprotocol/claude-agent-acp/issues/485))
([7506223](7506223cff))
* use current model's context window for usage_update size
([#412](https://github.com/agentclientprotocol/claude-agent-acp/issues/412))
([d07799d](d07799d7b3))

---
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-04-03 10:49:52 +00:00
Ben Brandt
063cd35380 feat: Add separate Claude and Console terminal logins (#502)
Expose distinct terminal auth methods for Claude subscription and
Anthropic Console, including terminal-auth metadata for both.
2026-04-03 12:48:57 +02:00
Ben Brandt
a16145396f feat: Add auto permission mode support (#501) 2026-04-03 12:34:06 +02:00
Ben Brandt
65a2230385 feat: Update to claude-agent-sdk 0.2.91 (#500) 2026-04-03 10:09:29 +00:00
dependabot[bot]
1d36b58cfb chore(deps): bump the minor group with 11 updates (#494)
Bumps the minor group with 11 updates:

| Package | From | To |
| --- | --- | --- |
|
[@agentclientprotocol/sdk](https://github.com/agentclientprotocol/typescript-sdk)
| `0.17.0` | `0.17.1` |
|
[@anthropic-ai/claude-agent-sdk](https://github.com/anthropics/claude-agent-sdk-typescript)
| `0.2.84` | `0.2.87` |
|
[vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest)
| `4.1.1` | `4.1.2` |
|
[@napi-rs/wasm-runtime](https://github.com/napi-rs/napi-rs/tree/HEAD/wasi-runtime)
| `1.1.1` | `1.1.2` |
|
[@vitest/expect](https://github.com/vitest-dev/vitest/tree/HEAD/packages/expect)
| `4.1.1` | `4.1.2` |
|
[@vitest/mocker](https://github.com/vitest-dev/vitest/tree/HEAD/packages/mocker)
| `4.1.1` | `4.1.2` |
|
[@vitest/pretty-format](https://github.com/vitest-dev/vitest/tree/HEAD/packages/pretty-format)
| `4.1.1` | `4.1.2` |
|
[@vitest/runner](https://github.com/vitest-dev/vitest/tree/HEAD/packages/runner)
| `4.1.1` | `4.1.2` |
|
[@vitest/snapshot](https://github.com/vitest-dev/vitest/tree/HEAD/packages/snapshot)
| `4.1.1` | `4.1.2` |
|
[@vitest/spy](https://github.com/vitest-dev/vitest/tree/HEAD/packages/spy)
| `4.1.1` | `4.1.2` |
|
[@vitest/utils](https://github.com/vitest-dev/vitest/tree/HEAD/packages/utils)
| `4.1.1` | `4.1.2` |

Updates `@agentclientprotocol/sdk` from 0.17.0 to 0.17.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/agentclientprotocol/typescript-sdk/releases"><code>@​agentclientprotocol/sdk</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v0.17.1</h2>
<h2><a
href="https://github.com/agentclientprotocol/typescript-sdk/compare/v0.17.0...v0.17.1">0.17.1</a>
(2026-03-27)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Make sure we use zod/v4 path for imports (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/99">#99</a>)
(<a
href="e632d3be54">e632d3b</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"><code>@​agentclientprotocol/sdk</code>'s
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/agentclientprotocol/typescript-sdk/compare/v0.17.0...v0.17.1">0.17.1</a>
(2026-03-27)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>Make sure we use zod/v4 path for imports (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/99">#99</a>)
(<a
href="e632d3be54">e632d3b</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="521078adcb"><code>521078a</code></a>
chore(main): release 0.17.1 (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/100">#100</a>)</li>
<li><a
href="e632d3be54"><code>e632d3b</code></a>
fix: Make sure we use zod/v4 path for imports (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/99">#99</a>)</li>
<li><a
href="4eebf350c0"><code>4eebf35</code></a>
chore(deps): bump actions/deploy-pages from 4.0.5 to 5.0.0 (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/95">#95</a>)</li>
<li><a
href="e63f49f416"><code>e63f49f</code></a>
chore(deps): bump picomatch in the npm_and_yarn group across 1 directory
(<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/93">#93</a>)</li>
<li><a
href="ed274cae24"><code>ed274ca</code></a>
chore(deps): bump the minor group with 48 updates (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/96">#96</a>)</li>
<li><a
href="cd701b29d8"><code>cd701b2</code></a>
chore: Use dependabot for NPM packages too (<a
href="https://redirect.github.com/agentclientprotocol/typescript-sdk/issues/94">#94</a>)</li>
<li>See full diff in <a
href="https://github.com/agentclientprotocol/typescript-sdk/compare/v0.17.0...v0.17.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `@anthropic-ai/claude-agent-sdk` from 0.2.84 to 0.2.87
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/claude-agent-sdk-typescript/releases"><code>@​anthropic-ai/claude-agent-sdk</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v0.2.87</h2>
<h2>What's changed</h2>
<ul>
<li>Updated to parity with Claude Code v2.1.87</li>
</ul>
<h2>Update</h2>
<pre lang="sh"><code>npm install @anthropic-ai/claude-agent-sdk@0.2.87
# or
yarn add @anthropic-ai/claude-agent-sdk@0.2.87
# or
pnpm add @anthropic-ai/claude-agent-sdk@0.2.87
# or
bun add @anthropic-ai/claude-agent-sdk@0.2.87
</code></pre>
<h2>v0.2.86</h2>
<h2>What's changed</h2>
<ul>
<li>Added <code>getContextUsage()</code> control method to retrieve a
breakdown of context window usage by category</li>
<li>Made <code>session_id</code> optional in <code>SDKUserMessage</code>
type — callers no longer need to provide a session ID when sending user
messages, as the SDK assigns one automatically</li>
<li>Fixed TypeScript types resolving to <code>any</code> by adding
<code>@anthropic-ai/sdk</code> and
<code>@modelcontextprotocol/sdk</code> as dependencies</li>
<li>Updated to parity with Claude Code v2.1.86</li>
</ul>
<h2>Update</h2>
<pre lang="sh"><code>npm install @anthropic-ai/claude-agent-sdk@0.2.86
# or
yarn add @anthropic-ai/claude-agent-sdk@0.2.86
# or
pnpm add @anthropic-ai/claude-agent-sdk@0.2.86
# or
bun add @anthropic-ai/claude-agent-sdk@0.2.86
</code></pre>
<h2>v0.2.85</h2>
<h2>What's changed</h2>
<ul>
<li>Added <code>reloadPlugins()</code> SDK method to reload plugins and
receive refreshed commands, agents, and MCP server status</li>
<li>Fixed PreToolUse hooks with <code>permissionDecision:
&quot;ask&quot;</code> being ignored in SDK mode</li>
<li>Updated to parity with Claude Code v2.1.85</li>
</ul>
<h2>Update</h2>
<pre lang="sh"><code>npm install @anthropic-ai/claude-agent-sdk@0.2.85
# or
yarn add @anthropic-ai/claude-agent-sdk@0.2.85
&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"><code>@​anthropic-ai/claude-agent-sdk</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>0.2.87</h2>
<ul>
<li>Updated to parity with Claude Code v2.1.87</li>
</ul>
<h2>0.2.86</h2>
<ul>
<li>Added <code>getContextUsage()</code> control method to retrieve a
breakdown of context window usage by category</li>
<li>Made <code>session_id</code> optional in <code>SDKUserMessage</code>
type — callers no longer need to provide a session ID when sending user
messages, as the SDK assigns one automatically</li>
<li>Fixed TypeScript types resolving to <code>any</code> by adding
<code>@anthropic-ai/sdk</code> and
<code>@modelcontextprotocol/sdk</code> as dependencies</li>
<li>Updated to parity with Claude Code v2.1.86</li>
</ul>
<h2>0.2.85</h2>
<ul>
<li>Added <code>reloadPlugins()</code> SDK method to reload plugins and
receive refreshed commands, agents, and MCP server status</li>
<li>Fixed PreToolUse hooks with <code>permissionDecision:
&quot;ask&quot;</code> being ignored in SDK mode</li>
<li>Updated to parity with Claude Code v2.1.85</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="af1bd5387b"><code>af1bd53</code></a>
chore: Update CHANGELOG.md</li>
<li><a
href="86b848bcf6"><code>86b848b</code></a>
chore: Update CHANGELOG.md</li>
<li><a
href="0f3a95b224"><code>0f3a95b</code></a>
chore: Update CHANGELOG.md</li>
<li>See full diff in <a
href="https://github.com/anthropics/claude-agent-sdk-typescript/compare/v0.2.84...v0.2.87">compare
view</a></li>
</ul>
</details>
<br />

Updates `vitest` from 4.1.1 to 4.1.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitest-dev/vitest/releases">vitest's
releases</a>.</em></p>
<blockquote>
<h2>v4.1.2</h2>
<p>This release bumps Vitest's <code>flatted</code> version and removes
version pinning to resolve <code>flatted</code>'s CVE related issues (<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9975">vitest-dev/vitest#9975</a>).</p>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li>Don't resolve <code>setupFiles</code> from parent directory  -  by
<a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9960">vitest-dev/vitest#9960</a>
<a href="https://github.com/vitest-dev/vitest/commit/7aa937776"><!-- raw
HTML omitted -->(7aa93)<!-- raw HTML omitted --></a></li>
<li>Ensure sequential mock/unmock resolution  -  by <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> and
<strong>Claude Opus 4.6</strong> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9830">vitest-dev/vitest#9830</a>
<a href="https://github.com/vitest-dev/vitest/commit/7c06598db"><!-- raw
HTML omitted -->(7c065)<!-- raw HTML omitted --></a></li>
<li><strong>browser</strong>: Take failure screenshot if
<code>toMatchScreenshot</code> can't capture a stable screenshot  -  by
<a href="https://github.com/macarie"><code>@​macarie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9847">vitest-dev/vitest#9847</a>
<a href="https://github.com/vitest-dev/vitest/commit/faace1fbe"><!-- raw
HTML omitted -->(faace)<!-- raw HTML omitted --></a></li>
<li><strong>coverage</strong>: Correct
<code>coverageConfigDefaults</code> values and types  -  by <a
href="https://github.com/Arthie"><code>@​Arthie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9940">vitest-dev/vitest#9940</a>
<a href="https://github.com/vitest-dev/vitest/commit/b3c992cb2"><!-- raw
HTML omitted -->(b3c99)<!-- raw HTML omitted --></a></li>
<li><strong>pretty-format</strong>: Fix output limit over counting  - 
by <a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9965">vitest-dev/vitest#9965</a>
<a href="https://github.com/vitest-dev/vitest/commit/d3b7a40fa"><!-- raw
HTML omitted -->(d3b7a)<!-- raw HTML omitted --></a></li>
<li>Disable colors if agent is detected  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> and
<a href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9851">vitest-dev/vitest#9851</a>
<a href="https://github.com/vitest-dev/vitest/commit/6f97b55dd"><!-- raw
HTML omitted -->(6f97b)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.1.1...v4.1.2">View
changes on GitHub</a></h5>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fc6f482f4c"><code>fc6f482</code></a>
chore: release v4.1.2</li>
<li><a
href="6f97b55ddc"><code>6f97b55</code></a>
feat: disable colors if agent is detected (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/9851">#9851</a>)</li>
<li><a
href="b3c992cb29"><code>b3c992c</code></a>
fix(coverage): correct <code>coverageConfigDefaults</code> values and
types (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/9940">#9940</a>)</li>
<li><a
href="7c06598dbb"><code>7c06598</code></a>
fix: ensure sequential mock/unmock resolution (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/9830">#9830</a>)</li>
<li><a
href="f54abad136"><code>f54abad</code></a>
chore: add typo-checker skill and fix typos (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/9963">#9963</a>)</li>
<li><a
href="7aa9377764"><code>7aa9377</code></a>
fix: don't resolve <code>setupFiles</code> from parent directory (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/9960">#9960</a>)</li>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/v4.1.2/packages/vitest">compare
view</a></li>
</ul>
</details>
<br />

Updates `@napi-rs/wasm-runtime` from 1.1.1 to 1.1.2
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/napi-rs/napi-rs/commits/@napi-rs/wasm-runtime@1.1.2/wasi-runtime">compare
view</a></li>
</ul>
</details>
<br />

Updates `@vitest/expect` from 4.1.1 to 4.1.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitest-dev/vitest/releases"><code>@​vitest/expect</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v4.1.2</h2>
<p>This release bumps Vitest's <code>flatted</code> version and removes
version pinning to resolve <code>flatted</code>'s CVE related issues (<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9975">vitest-dev/vitest#9975</a>).</p>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li>Don't resolve <code>setupFiles</code> from parent directory  -  by
<a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9960">vitest-dev/vitest#9960</a>
<a href="https://github.com/vitest-dev/vitest/commit/7aa937776"><!-- raw
HTML omitted -->(7aa93)<!-- raw HTML omitted --></a></li>
<li>Ensure sequential mock/unmock resolution  -  by <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> and
<strong>Claude Opus 4.6</strong> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9830">vitest-dev/vitest#9830</a>
<a href="https://github.com/vitest-dev/vitest/commit/7c06598db"><!-- raw
HTML omitted -->(7c065)<!-- raw HTML omitted --></a></li>
<li><strong>browser</strong>: Take failure screenshot if
<code>toMatchScreenshot</code> can't capture a stable screenshot  -  by
<a href="https://github.com/macarie"><code>@​macarie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9847">vitest-dev/vitest#9847</a>
<a href="https://github.com/vitest-dev/vitest/commit/faace1fbe"><!-- raw
HTML omitted -->(faace)<!-- raw HTML omitted --></a></li>
<li><strong>coverage</strong>: Correct
<code>coverageConfigDefaults</code> values and types  -  by <a
href="https://github.com/Arthie"><code>@​Arthie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9940">vitest-dev/vitest#9940</a>
<a href="https://github.com/vitest-dev/vitest/commit/b3c992cb2"><!-- raw
HTML omitted -->(b3c99)<!-- raw HTML omitted --></a></li>
<li><strong>pretty-format</strong>: Fix output limit over counting  - 
by <a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9965">vitest-dev/vitest#9965</a>
<a href="https://github.com/vitest-dev/vitest/commit/d3b7a40fa"><!-- raw
HTML omitted -->(d3b7a)<!-- raw HTML omitted --></a></li>
<li>Disable colors if agent is detected  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> and
<a href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9851">vitest-dev/vitest#9851</a>
<a href="https://github.com/vitest-dev/vitest/commit/6f97b55dd"><!-- raw
HTML omitted -->(6f97b)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.1.1...v4.1.2">View
changes on GitHub</a></h5>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fc6f482f4c"><code>fc6f482</code></a>
chore: release v4.1.2</li>
<li><a
href="faace1fbe0"><code>faace1f</code></a>
fix(browser): take failure screenshot if <code>toMatchScreenshot</code>
can't capture a ...</li>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/v4.1.2/packages/expect">compare
view</a></li>
</ul>
</details>
<br />

Updates `@vitest/mocker` from 4.1.1 to 4.1.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitest-dev/vitest/releases"><code>@​vitest/mocker</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v4.1.2</h2>
<p>This release bumps Vitest's <code>flatted</code> version and removes
version pinning to resolve <code>flatted</code>'s CVE related issues (<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9975">vitest-dev/vitest#9975</a>).</p>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li>Don't resolve <code>setupFiles</code> from parent directory  -  by
<a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9960">vitest-dev/vitest#9960</a>
<a href="https://github.com/vitest-dev/vitest/commit/7aa937776"><!-- raw
HTML omitted -->(7aa93)<!-- raw HTML omitted --></a></li>
<li>Ensure sequential mock/unmock resolution  -  by <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> and
<strong>Claude Opus 4.6</strong> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9830">vitest-dev/vitest#9830</a>
<a href="https://github.com/vitest-dev/vitest/commit/7c06598db"><!-- raw
HTML omitted -->(7c065)<!-- raw HTML omitted --></a></li>
<li><strong>browser</strong>: Take failure screenshot if
<code>toMatchScreenshot</code> can't capture a stable screenshot  -  by
<a href="https://github.com/macarie"><code>@​macarie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9847">vitest-dev/vitest#9847</a>
<a href="https://github.com/vitest-dev/vitest/commit/faace1fbe"><!-- raw
HTML omitted -->(faace)<!-- raw HTML omitted --></a></li>
<li><strong>coverage</strong>: Correct
<code>coverageConfigDefaults</code> values and types  -  by <a
href="https://github.com/Arthie"><code>@​Arthie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9940">vitest-dev/vitest#9940</a>
<a href="https://github.com/vitest-dev/vitest/commit/b3c992cb2"><!-- raw
HTML omitted -->(b3c99)<!-- raw HTML omitted --></a></li>
<li><strong>pretty-format</strong>: Fix output limit over counting  - 
by <a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9965">vitest-dev/vitest#9965</a>
<a href="https://github.com/vitest-dev/vitest/commit/d3b7a40fa"><!-- raw
HTML omitted -->(d3b7a)<!-- raw HTML omitted --></a></li>
<li>Disable colors if agent is detected  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> and
<a href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9851">vitest-dev/vitest#9851</a>
<a href="https://github.com/vitest-dev/vitest/commit/6f97b55dd"><!-- raw
HTML omitted -->(6f97b)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.1.1...v4.1.2">View
changes on GitHub</a></h5>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fc6f482f4c"><code>fc6f482</code></a>
chore: release v4.1.2</li>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/v4.1.2/packages/mocker">compare
view</a></li>
</ul>
</details>
<br />

Updates `@vitest/pretty-format` from 4.1.1 to 4.1.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitest-dev/vitest/releases"><code>@​vitest/pretty-format</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v4.1.2</h2>
<p>This release bumps Vitest's <code>flatted</code> version and removes
version pinning to resolve <code>flatted</code>'s CVE related issues (<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9975">vitest-dev/vitest#9975</a>).</p>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li>Don't resolve <code>setupFiles</code> from parent directory  -  by
<a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9960">vitest-dev/vitest#9960</a>
<a href="https://github.com/vitest-dev/vitest/commit/7aa937776"><!-- raw
HTML omitted -->(7aa93)<!-- raw HTML omitted --></a></li>
<li>Ensure sequential mock/unmock resolution  -  by <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> and
<strong>Claude Opus 4.6</strong> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9830">vitest-dev/vitest#9830</a>
<a href="https://github.com/vitest-dev/vitest/commit/7c06598db"><!-- raw
HTML omitted -->(7c065)<!-- raw HTML omitted --></a></li>
<li><strong>browser</strong>: Take failure screenshot if
<code>toMatchScreenshot</code> can't capture a stable screenshot  -  by
<a href="https://github.com/macarie"><code>@​macarie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9847">vitest-dev/vitest#9847</a>
<a href="https://github.com/vitest-dev/vitest/commit/faace1fbe"><!-- raw
HTML omitted -->(faace)<!-- raw HTML omitted --></a></li>
<li><strong>coverage</strong>: Correct
<code>coverageConfigDefaults</code> values and types  -  by <a
href="https://github.com/Arthie"><code>@​Arthie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9940">vitest-dev/vitest#9940</a>
<a href="https://github.com/vitest-dev/vitest/commit/b3c992cb2"><!-- raw
HTML omitted -->(b3c99)<!-- raw HTML omitted --></a></li>
<li><strong>pretty-format</strong>: Fix output limit over counting  - 
by <a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9965">vitest-dev/vitest#9965</a>
<a href="https://github.com/vitest-dev/vitest/commit/d3b7a40fa"><!-- raw
HTML omitted -->(d3b7a)<!-- raw HTML omitted --></a></li>
<li>Disable colors if agent is detected  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> and
<a href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9851">vitest-dev/vitest#9851</a>
<a href="https://github.com/vitest-dev/vitest/commit/6f97b55dd"><!-- raw
HTML omitted -->(6f97b)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.1.1...v4.1.2">View
changes on GitHub</a></h5>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fc6f482f4c"><code>fc6f482</code></a>
chore: release v4.1.2</li>
<li><a
href="d3b7a40fa8"><code>d3b7a40</code></a>
fix(pretty-format): fix output limit over counting (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/pretty-format/issues/9965">#9965</a>)</li>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/v4.1.2/packages/pretty-format">compare
view</a></li>
</ul>
</details>
<br />

Updates `@vitest/runner` from 4.1.1 to 4.1.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitest-dev/vitest/releases"><code>@​vitest/runner</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v4.1.2</h2>
<p>This release bumps Vitest's <code>flatted</code> version and removes
version pinning to resolve <code>flatted</code>'s CVE related issues (<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9975">vitest-dev/vitest#9975</a>).</p>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li>Don't resolve <code>setupFiles</code> from parent directory  -  by
<a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9960">vitest-dev/vitest#9960</a>
<a href="https://github.com/vitest-dev/vitest/commit/7aa937776"><!-- raw
HTML omitted -->(7aa93)<!-- raw HTML omitted --></a></li>
<li>Ensure sequential mock/unmock resolution  -  by <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> and
<strong>Claude Opus 4.6</strong> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9830">vitest-dev/vitest#9830</a>
<a href="https://github.com/vitest-dev/vitest/commit/7c06598db"><!-- raw
HTML omitted -->(7c065)<!-- raw HTML omitted --></a></li>
<li><strong>browser</strong>: Take failure screenshot if
<code>toMatchScreenshot</code> can't capture a stable screenshot  -  by
<a href="https://github.com/macarie"><code>@​macarie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9847">vitest-dev/vitest#9847</a>
<a href="https://github.com/vitest-dev/vitest/commit/faace1fbe"><!-- raw
HTML omitted -->(faace)<!-- raw HTML omitted --></a></li>
<li><strong>coverage</strong>: Correct
<code>coverageConfigDefaults</code> values and types  -  by <a
href="https://github.com/Arthie"><code>@​Arthie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9940">vitest-dev/vitest#9940</a>
<a href="https://github.com/vitest-dev/vitest/commit/b3c992cb2"><!-- raw
HTML omitted -->(b3c99)<!-- raw HTML omitted --></a></li>
<li><strong>pretty-format</strong>: Fix output limit over counting  - 
by <a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9965">vitest-dev/vitest#9965</a>
<a href="https://github.com/vitest-dev/vitest/commit/d3b7a40fa"><!-- raw
HTML omitted -->(d3b7a)<!-- raw HTML omitted --></a></li>
<li>Disable colors if agent is detected  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> and
<a href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9851">vitest-dev/vitest#9851</a>
<a href="https://github.com/vitest-dev/vitest/commit/6f97b55dd"><!-- raw
HTML omitted -->(6f97b)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.1.1...v4.1.2">View
changes on GitHub</a></h5>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fc6f482f4c"><code>fc6f482</code></a>
chore: release v4.1.2</li>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/v4.1.2/packages/runner">compare
view</a></li>
</ul>
</details>
<br />

Updates `@vitest/snapshot` from 4.1.1 to 4.1.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitest-dev/vitest/releases"><code>@​vitest/snapshot</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v4.1.2</h2>
<p>This release bumps Vitest's <code>flatted</code> version and removes
version pinning to resolve <code>flatted</code>'s CVE related issues (<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9975">vitest-dev/vitest#9975</a>).</p>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li>Don't resolve <code>setupFiles</code> from parent directory  -  by
<a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9960">vitest-dev/vitest#9960</a>
<a href="https://github.com/vitest-dev/vitest/commit/7aa937776"><!-- raw
HTML omitted -->(7aa93)<!-- raw HTML omitted --></a></li>
<li>Ensure sequential mock/unmock resolution  -  by <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> and
<strong>Claude Opus 4.6</strong> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9830">vitest-dev/vitest#9830</a>
<a href="https://github.com/vitest-dev/vitest/commit/7c06598db"><!-- raw
HTML omitted -->(7c065)<!-- raw HTML omitted --></a></li>
<li><strong>browser</strong>: Take failure screenshot if
<code>toMatchScreenshot</code> can't capture a stable screenshot  -  by
<a href="https://github.com/macarie"><code>@​macarie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9847">vitest-dev/vitest#9847</a>
<a href="https://github.com/vitest-dev/vitest/commit/faace1fbe"><!-- raw
HTML omitted -->(faace)<!-- raw HTML omitted --></a></li>
<li><strong>coverage</strong>: Correct
<code>coverageConfigDefaults</code> values and types  -  by <a
href="https://github.com/Arthie"><code>@​Arthie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9940">vitest-dev/vitest#9940</a>
<a href="https://github.com/vitest-dev/vitest/commit/b3c992cb2"><!-- raw
HTML omitted -->(b3c99)<!-- raw HTML omitted --></a></li>
<li><strong>pretty-format</strong>: Fix output limit over counting  - 
by <a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9965">vitest-dev/vitest#9965</a>
<a href="https://github.com/vitest-dev/vitest/commit/d3b7a40fa"><!-- raw
HTML omitted -->(d3b7a)<!-- raw HTML omitted --></a></li>
<li>Disable colors if agent is detected  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> and
<a href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9851">vitest-dev/vitest#9851</a>
<a href="https://github.com/vitest-dev/vitest/commit/6f97b55dd"><!-- raw
HTML omitted -->(6f97b)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.1.1...v4.1.2">View
changes on GitHub</a></h5>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fc6f482f4c"><code>fc6f482</code></a>
chore: release v4.1.2</li>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/v4.1.2/packages/snapshot">compare
view</a></li>
</ul>
</details>
<br />

Updates `@vitest/spy` from 4.1.1 to 4.1.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitest-dev/vitest/releases"><code>@​vitest/spy</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v4.1.2</h2>
<p>This release bumps Vitest's <code>flatted</code> version and removes
version pinning to resolve <code>flatted</code>'s CVE related issues (<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9975">vitest-dev/vitest#9975</a>).</p>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li>Don't resolve <code>setupFiles</code> from parent directory  -  by
<a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9960">vitest-dev/vitest#9960</a>
<a href="https://github.com/vitest-dev/vitest/commit/7aa937776"><!-- raw
HTML omitted -->(7aa93)<!-- raw HTML omitted --></a></li>
<li>Ensure sequential mock/unmock resolution  -  by <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> and
<strong>Claude Opus 4.6</strong> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9830">vitest-dev/vitest#9830</a>
<a href="https://github.com/vitest-dev/vitest/commit/7c06598db"><!-- raw
HTML omitted -->(7c065)<!-- raw HTML omitted --></a></li>
<li><strong>browser</strong>: Take failure screenshot if
<code>toMatchScreenshot</code> can't capture a stable screenshot  -  by
<a href="https://github.com/macarie"><code>@​macarie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9847">vitest-dev/vitest#9847</a>
<a href="https://github.com/vitest-dev/vitest/commit/faace1fbe"><!-- raw
HTML omitted -->(faace)<!-- raw HTML omitted --></a></li>
<li><strong>coverage</strong>: Correct
<code>coverageConfigDefaults</code> values and types  -  by <a
href="https://github.com/Arthie"><code>@​Arthie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9940">vitest-dev/vitest#9940</a>
<a href="https://github.com/vitest-dev/vitest/commit/b3c992cb2"><!-- raw
HTML omitted -->(b3c99)<!-- raw HTML omitted --></a></li>
<li><strong>pretty-format</strong>: Fix output limit over counting  - 
by <a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9965">vitest-dev/vitest#9965</a>
<a href="https://github.com/vitest-dev/vitest/commit/d3b7a40fa"><!-- raw
HTML omitted -->(d3b7a)<!-- raw HTML omitted --></a></li>
<li>Disable colors if agent is detected  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> and
<a href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9851">vitest-dev/vitest#9851</a>
<a href="https://github.com/vitest-dev/vitest/commit/6f97b55dd"><!-- raw
HTML omitted -->(6f97b)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.1.1...v4.1.2">View
changes on GitHub</a></h5>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fc6f482f4c"><code>fc6f482</code></a>
chore: release v4.1.2</li>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/v4.1.2/packages/spy">compare
view</a></li>
</ul>
</details>
<br />

Updates `@vitest/utils` from 4.1.1 to 4.1.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitest-dev/vitest/releases"><code>@​vitest/utils</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v4.1.2</h2>
<p>This release bumps Vitest's <code>flatted</code> version and removes
version pinning to resolve <code>flatted</code>'s CVE related issues (<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9975">vitest-dev/vitest#9975</a>).</p>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li>Don't resolve <code>setupFiles</code> from parent directory  -  by
<a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9960">vitest-dev/vitest#9960</a>
<a href="https://github.com/vitest-dev/vitest/commit/7aa937776"><!-- raw
HTML omitted -->(7aa93)<!-- raw HTML omitted --></a></li>
<li>Ensure sequential mock/unmock resolution  -  by <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> and
<strong>Claude Opus 4.6</strong> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9830">vitest-dev/vitest#9830</a>
<a href="https://github.com/vitest-dev/vitest/commit/7c06598db"><!-- raw
HTML omitted -->(7c065)<!-- raw HTML omitted --></a></li>
<li><strong>browser</strong>: Take failure screenshot if
<code>toMatchScreenshot</code> can't capture a stable screenshot  -  by
<a href="https://github.com/macarie"><code>@​macarie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9847">vitest-dev/vitest#9847</a>
<a href="https://github.com/vitest-dev/vitest/commit/faace1fbe"><!-- raw
HTML omitted -->(faace)<!-- raw HTML omitted --></a></li>
<li><strong>coverage</strong>: Correct
<code>coverageConfigDefaults</code> values and types  -  by <a
href="https://github.com/Arthie"><code>@​Arthie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9940">vitest-dev/vitest#9940</a>
<a href="https://github.com/vitest-dev/vitest/commit/b3c992cb2"><!-- raw
HTML omitted -->(b3c99)<!-- raw HTML omitted --></a></li>
<li><strong>pretty-format</strong>: Fix output limit over counting  - 
by <a href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9965">vitest-dev/vitest#9965</a>
<a href="https://github.com/vitest-dev/vitest/commit/d3b7a40fa"><!-- raw
HTML omitted -->(d3b7a)<!-- raw HTML omitted --></a></li>
<li>Disable colors if agent is detected  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> and
<a href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9851">vitest-dev/vitest#9851</a>
<a href="https://github.com/vitest-dev/vitest/commit/6f97b55dd"><!-- raw
HTML omitted -->(6f97b)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.1.1...v4.1.2">View
changes on GitHub</a></h5>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="fc6f482f4c"><code>fc6f482</code></a>
chore: release v4.1.2</li>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/v4.1.2/packages/utils">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-04-03 11:58:51 +02:00
dependabot[bot]
ee324b54dd chore(deps-dev): bump @anthropic-ai/sdk from 0.80.0 to 0.81.0 (#499)
Bumps
[@anthropic-ai/sdk](https://github.com/anthropics/anthropic-sdk-typescript)
from 0.80.0 to 0.81.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/anthropic-sdk-typescript/releases"><code>@​anthropic-ai/sdk</code>'s
releases</a>.</em></p>
<blockquote>
<h2>sdk: v0.81.0</h2>
<h2>0.81.0 (2026-03-31)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.80.0...sdk-v0.81.0">sdk-v0.80.0...sdk-v0.81.0</a></p>
<h3>Features</h3>
<ul>
<li>add .type field to APIError for error kind identification (<a
href="https://redirect.github.com/anthropics/anthropic-sdk-typescript/issues/790">#790</a>)
(<a
href="4bf637d962">4bf637d</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><strong>memory:</strong> append path separator in validatePath
prefix check (<a
href="0ac69b3438">0ac69b3</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><strong>ci:</strong> run builds on CI even if only spec metadata
changed (<a
href="70b657aac1">70b657a</a>)</li>
<li><strong>ci:</strong> skip lint on metadata-only changes (<a
href="69bdc94a16">69bdc94</a>)</li>
<li><strong>internal:</strong> codegen related update (<a
href="7ff7390029">7ff7390</a>)</li>
<li><strong>internal:</strong> update gitignore (<a
href="46d66675d5">46d6667</a>)</li>
<li><strong>internal:</strong> update multipart form array serialization
(<a
href="d55b07d4f7">d55b07d</a>)</li>
<li><strong>tests:</strong> bump steady to v0.19.4 (<a
href="4957a5e65b">4957a5e</a>)</li>
<li><strong>tests:</strong> bump steady to v0.19.5 (<a
href="c511ae0421">c511ae0</a>)</li>
<li><strong>tests:</strong> bump steady to v0.19.6 (<a
href="6d2b4b910a">6d2b4b9</a>)</li>
<li><strong>tests:</strong> bump steady to v0.19.7 (<a
href="d6cff9d2c8">d6cff9d</a>)</li>
<li><strong>tests:</strong> bump steady to v0.20.1 (<a
href="284561fe36">284561f</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"><code>@​anthropic-ai/sdk</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>0.81.0 (2026-03-31)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.80.0...sdk-v0.81.0">sdk-v0.80.0...sdk-v0.81.0</a></p>
<h3>Features</h3>
<ul>
<li>add .type field to APIError for error kind identification (<a
href="https://redirect.github.com/anthropics/anthropic-sdk-typescript/issues/790">#790</a>)
(<a
href="4bf637d962">4bf637d</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><strong>memory:</strong> append path separator in validatePath
prefix check (<a
href="0ac69b3438">0ac69b3</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><strong>ci:</strong> run builds on CI even if only spec metadata
changed (<a
href="70b657aac1">70b657a</a>)</li>
<li><strong>ci:</strong> skip lint on metadata-only changes (<a
href="69bdc94a16">69bdc94</a>)</li>
<li><strong>internal:</strong> codegen related update (<a
href="7ff7390029">7ff7390</a>)</li>
<li><strong>internal:</strong> update gitignore (<a
href="46d66675d5">46d6667</a>)</li>
<li><strong>internal:</strong> update multipart form array serialization
(<a
href="d55b07d4f7">d55b07d</a>)</li>
<li><strong>tests:</strong> bump steady to v0.19.4 (<a
href="4957a5e65b">4957a5e</a>)</li>
<li><strong>tests:</strong> bump steady to v0.19.5 (<a
href="c511ae0421">c511ae0</a>)</li>
<li><strong>tests:</strong> bump steady to v0.19.6 (<a
href="6d2b4b910a">6d2b4b9</a>)</li>
<li><strong>tests:</strong> bump steady to v0.19.7 (<a
href="d6cff9d2c8">d6cff9d</a>)</li>
<li><strong>tests:</strong> bump steady to v0.20.1 (<a
href="284561fe36">284561f</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="bc1a2ff79c"><code>bc1a2ff</code></a>
chore: release main (<a
href="https://redirect.github.com/anthropics/anthropic-sdk-typescript/issues/955">#955</a>)</li>
<li>See full diff in <a
href="https://github.com/anthropics/anthropic-sdk-typescript/compare/sdk-v0.80.0...sdk-v0.81.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@anthropic-ai/sdk&package-manager=npm_and_yarn&previous-version=0.80.0&new-version=0.81.0)](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)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/agentclientprotocol/claude-agent-acp/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-02 07:10:40 +02:00
Tim Visher
d07799d7b3 fix: use current model's context window for usage_update size (#412)
The `usage_update` notification reports `size: 200000` even when the
active model has a 1M context window (e.g. `opus[1m]`), causing clients
to display incorrect context utilization (e.g. `689k/200k (344.3%)`
instead of `689k/1000k (68.9%)`).

Four bugs fixed:

- **Min across all models**: The original code used `Math.min` across
all `modelUsage` entries, so subagent models (Sonnet/Haiku with 200k
windows) dragged down the reported size for the main Opus 1M model. Now
tracks the top-level assistant model and looks up its context window
specifically.
- **Model name mismatch**: The SDK's streaming path keys `modelUsage` by
the requested model alias (e.g. `claude-opus-4-6`) while
`BetaMessage.model` on assistant messages has the resolved API response
model (e.g. `claude-opus-4-6-20250514`). The exact-match lookup always
missed, falling back to the hardcoded 200k default. Now falls back to
prefix matching, preferring the longest/most-specific match.
- **Synthetic messages corrupt model tracking**: `/compact` and similar
commands emit assistant messages with `model: "<synthetic>"`. These were
updating `lastAssistantModel`, causing the next `usage_update` to miss
the `modelUsage` lookup and fall back to the 200k default. Now filters
out `<synthetic>` models.
- **Stale usage after compaction**: No `usage_update` was sent on
`compact_boundary`, so clients kept showing the pre-compaction context
size (e.g. `944k/1m`) right after "Compacting completed" until the next
full turn. Now sends `used: 0` immediately on compaction. This is a
deliberate approximation — the exact post-compaction size isn't known
until the SDK's next API call, which replaces it within seconds. The
alternative (no update) is worse UX: showing a full context bar right
after compaction.

Eight new tests cover: token sum correctness, current-model context
window lookup, model switching, subagent isolation, prefix matching in
both directions, and synthetic message filtering.

Note: `bin/test` (local CI validation script) is cherry-picked from
#353.

Would fix `agent-shell`'s usage indicator which currently has to defend
against this broken math:
https://github.com/xenodium/agent-shell/pull/364

## Testing

- [x] Manual riding with it for a bit.

---------

Co-authored-by: Tim Visher <194828183+timvisher-dd@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Steffen Deusch <steffen@deusch.me>
2026-03-30 14:09:30 +02:00
tbounsiar
7506223cff fix: prevent race conditions in SettingsManager setCwd and debounce (#485)
## Summary

- **Concurrent `setCwd()` calls** could produce duplicate file watchers
because both calls cleared `initialized` before either completed
`initialize()`. Added an `initPromise` guard so concurrent calls await
the same initialization.
- **Debounce timer callback** could fire after `dispose()`, reloading
stale settings and calling `onChange` on a disposed manager. Added a
`disposed` flag checked in the async callback before proceeding.

Follows up on #454 which fixed the missing `dispose()` calls — this PR
hardens the `SettingsManager` lifecycle against race conditions.

## Test plan

- [x] `npm run lint` passes
- [x] All settings tests pass
- [x] Verified `disposed` flag prevents stale callback execution
- [x] Verified `initPromise` deduplicates concurrent `initialize()`
calls
2026-03-27 12:12:19 +00:00
tbounsiar
ae6c388314 fix: log warnings for malformed settings files instead of silent fallback (#486)
## Summary

- `loadSettingsFile()` silently returned `{}` for **all** errors
including malformed JSON, permission errors, and unexpected file content
- Only `ENOENT` (file not found) should be silent since missing settings
files are expected
- Other errors now log a warning via the logger to help diagnose
misconfigured settings (e.g. a typo in `settings.json` was previously
completely invisible)

## Test plan

- [x] `npm run lint` passes
- [x] All settings tests pass
- [x] Missing files still return `{}` silently (ENOENT path unchanged)
- [x] Malformed JSON now produces a logged warning
2026-03-27 12:10:24 +00:00
9 changed files with 2280 additions and 352 deletions

View File

@@ -38,7 +38,8 @@ jobs:
name: Build (${{ matrix.target }})
runs-on: ubuntu-latest
needs: [release-please]
if: ${{ needs.release-please.outputs.release_created }}
# TODO: Re-enable once Bun SDK compatibility is fixed
if: false
permissions:
contents: read
timeout-minutes: 15
@@ -107,7 +108,7 @@ jobs:
publish-npm:
name: Publish to npm
runs-on: ubuntu-latest
needs: [build-binaries, release-please]
needs: [release-please]
if: ${{ needs.release-please.outputs.release_created }}
environment: release # Optional: for enhanced security
permissions:
@@ -129,8 +130,9 @@ jobs:
release:
name: Create Release
runs-on: ubuntu-latest
needs: [build-binaries, publish-npm, release-please]
if: ${{ needs.release-please.outputs.release_created }}
needs: [publish-npm, release-please]
# TODO: Re-enable once Bun SDK compatibility is fixed
if: false
permissions:
contents: write

View File

@@ -1,3 +1,3 @@
{
".": "0.24.2"
".": "0.26.0"
}

View File

@@ -1,5 +1,56 @@
# Changelog
## [0.26.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.25.3...v0.26.0) (2026-04-08)
### Features
* Update claude-agent-sdk to 0.2.96 ([#526](https://github.com/agentclientprotocol/claude-agent-acp/issues/526)) ([c073131](https://github.com/agentclientprotocol/claude-agent-acp/commit/c07313148808a55f27f385c10babbaf7511a7f12))
### Bug Fixes
* Remove bun builds from release ([#525](https://github.com/agentclientprotocol/claude-agent-acp/issues/525)) ([fcf5aaf](https://github.com/agentclientprotocol/claude-agent-acp/commit/fcf5aaf06dfe9f7d1b285b976eeb2d1e20ea8dec))
* Use TUI login for remote environments ([#523](https://github.com/agentclientprotocol/claude-agent-acp/issues/523)) ([cc73e37](https://github.com/agentclientprotocol/claude-agent-acp/commit/cc73e37b41678aa67813c4fbef66ba33ca538743))
## [0.25.3](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.25.2...v0.25.3) (2026-04-06)
### Bug Fixes
* Drop claude-agent-sdk back to 0.2.91 to fix broken import ([#513](https://github.com/agentclientprotocol/claude-agent-acp/issues/513)) ([26f3e8a](https://github.com/agentclientprotocol/claude-agent-acp/commit/26f3e8a5216295985fadb80fb3b977045c0c1b2c))
* Recreate resumed sessions when params change ([#515](https://github.com/agentclientprotocol/claude-agent-acp/issues/515)) ([aa82193](https://github.com/agentclientprotocol/claude-agent-acp/commit/aa82193330026bae132fed8391c47dde777dcf5a))
## [0.25.2](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.25.1...v0.25.2) (2026-04-06)
### Bug Fixes
* prioritize ANTHROPIC_MODEL env var over settings.model in model … ([#505](https://github.com/agentclientprotocol/claude-agent-acp/issues/505)) ([bea1a40](https://github.com/agentclientprotocol/claude-agent-acp/commit/bea1a40e9bfe1e06672b118a727f9339def3be23))
## [0.25.1](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.25.0...v0.25.1) (2026-04-06)
### Bug Fixes
* add `auto` to valid modes in applySessionMode to fix mode cycling ([#507](https://github.com/agentclientprotocol/claude-agent-acp/issues/507)) ([15e91fb](https://github.com/agentclientprotocol/claude-agent-acp/commit/15e91fb5c3449de2600b583cb7a8d36b5b510443))
## [0.25.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.24.2...v0.25.0) (2026-04-03)
### Features
* Add auto permission mode support ([#501](https://github.com/agentclientprotocol/claude-agent-acp/issues/501)) ([a161453](https://github.com/agentclientprotocol/claude-agent-acp/commit/a16145396fe2e6ead8734478961b2de65707e335))
* Add separate Claude and Console terminal logins ([#502](https://github.com/agentclientprotocol/claude-agent-acp/issues/502)) ([063cd35](https://github.com/agentclientprotocol/claude-agent-acp/commit/063cd353809df8f3dda9e57d8ea848c0a6d44257))
* Update to claude-agent-sdk 0.2.91 ([#500](https://github.com/agentclientprotocol/claude-agent-acp/issues/500)) ([65a2230](https://github.com/agentclientprotocol/claude-agent-acp/commit/65a223038576d72b74e1483fed10e982a1f842bd))
### Bug Fixes
* log warnings for malformed settings files instead of silent fallback ([#486](https://github.com/agentclientprotocol/claude-agent-acp/issues/486)) ([ae6c388](https://github.com/agentclientprotocol/claude-agent-acp/commit/ae6c38831415f9fc1de2d3dd1d4a247becbbd32f))
* prevent race conditions in SettingsManager setCwd and debounce ([#485](https://github.com/agentclientprotocol/claude-agent-acp/issues/485)) ([7506223](https://github.com/agentclientprotocol/claude-agent-acp/commit/7506223cffb1aba4b4560feda11f69a1395a8c9d))
* use current model's context window for usage_update size ([#412](https://github.com/agentclientprotocol/claude-agent-acp/issues/412)) ([d07799d](https://github.com/agentclientprotocol/claude-agent-acp/commit/d07799d7b3b4e438c8b158266c79723a0b592c07))
## [0.24.2](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.24.1...v0.24.2) (2026-03-27)

1602
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.24.2",
"version": "0.26.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.17.0",
"@anthropic-ai/claude-agent-sdk": "0.2.84",
"@agentclientprotocol/sdk": "0.18.1",
"@anthropic-ai/claude-agent-sdk": "0.2.96",
"zod": "^3.25.0 || ^4.0.0"
},
"devDependencies": {
"@anthropic-ai/sdk": "0.80.0",
"@anthropic-ai/sdk": "0.85.0",
"@eslint/js": "10.0.1",
"@types/node": "25.5.0",
"@typescript-eslint/eslint-plugin": "8.57.2",
"@typescript-eslint/parser": "8.57.2",
"eslint": "10.1.0",
"@types/node": "25.5.2",
"@typescript-eslint/eslint-plugin": "8.58.1",
"@typescript-eslint/parser": "8.58.1",
"eslint": "10.2.0",
"eslint-config-prettier": "10.1.8",
"globals": "17.4.0",
"prettier": "3.8.1",
"ts-node": "10.9.2",
"typescript": "5.9.3",
"vitest": "4.1.1"
"typescript": "6.0.2",
"vitest": "4.1.3"
}
}

View File

@@ -48,6 +48,7 @@ import {
listSessions,
McpServerConfig,
ModelInfo,
ModelUsage,
Options,
PermissionMode,
Query,
@@ -113,6 +114,9 @@ type Session = {
input: Pushable<SDKUserMessage>;
cancelled: boolean;
cwd: string;
/** Serialized snapshot of session-defining params (cwd, mcpServers) used to
* detect when loadSession/resumeSession is called with changed values. */
sessionFingerprint: string;
settingsManager: SettingsManager;
accumulatedUsage: AccumulatedUsage;
modes: SessionModeState;
@@ -124,6 +128,18 @@ type Session = {
abortController: AbortController;
};
/** Compute a stable fingerprint of the session-defining params so we can
* detect when a loadSession/resumeSession call requires tearing down and
* recreating the underlying Query process. MCP servers are sorted by name
* so that ordering differences don't trigger unnecessary recreations. */
function computeSessionFingerprint(params: {
cwd: string;
mcpServers?: NewSessionRequest["mcpServers"];
}): string {
const servers = [...(params.mcpServers ?? [])].sort((a, b) => a.name.localeCompare(b.name));
return JSON.stringify({ cwd: params.cwd, mcpServers: servers });
}
type BackgroundTerminal =
| {
handle: TerminalHandle;
@@ -233,6 +249,7 @@ const ALLOW_BYPASS = !IS_ROOT || !!process.env.IS_SANDBOX;
const LOCAL_ONLY_COMMANDS = new Set(["/context", "/heapdump", "/extra-usage"]);
const PERMISSION_MODE_ALIASES: Record<string, PermissionMode> = {
auto: "auto",
default: "default",
acceptedits: "acceptEdits",
dontask: "dontAsk",
@@ -306,25 +323,77 @@ export class ClaudeAcpAgent implements Agent {
},
};
const terminalAuthMethod: any = {
description: "Run `claude /login` in the terminal",
name: "Log in with Claude",
id: "claude-login",
type: "terminal",
args: ["--cli"],
};
const supportsTerminalAuth = request.clientCapabilities?.auth?.terminal === true;
// If client supports terminal-auth capability, use that instead.
const supportsMetaTerminalAuth = request.clientCapabilities?._meta?.["terminal-auth"] === true;
if (supportsMetaTerminalAuth) {
terminalAuthMethod._meta = {
"terminal-auth": {
command: process.execPath,
args: [...process.argv.slice(1), "--cli"],
label: "Claude Login",
},
const noBrowser = !!process.env.NO_BROWSER;
// When NO_BROWSER is set (e.g. remote environments), fall back to the single
// terminal-only login that doesn't try to open a browser.
const terminalAuthMethods: AuthMethod[] = [];
if (noBrowser) {
const remoteLoginMethod: AuthMethod = {
description: "Run `claude /login` in the terminal",
name: "Log in with Claude",
id: "claude-login",
type: "terminal",
args: ["--cli"],
};
if (supportsMetaTerminalAuth) {
remoteLoginMethod._meta = {
"terminal-auth": {
command: process.execPath,
args: [...process.argv.slice(1), "--cli"],
label: "Claude Login",
},
};
}
if (!shouldHideClaudeAuth() && (supportsTerminalAuth || supportsMetaTerminalAuth)) {
terminalAuthMethods.push(remoteLoginMethod);
}
} else {
const claudeLoginMethod: AuthMethod = {
description: "Use Claude subscription ",
name: "Claude Subscription",
id: "claude-ai-login",
type: "terminal",
args: ["--cli", "auth", "login", "--claudeai"],
};
const consoleLoginMethod: AuthMethod = {
description: "Use Anthropic Console (API usage billing)",
name: "Anthropic Console",
id: "console-login",
type: "terminal",
args: ["--cli", "auth", "login", "--console"],
};
if (supportsMetaTerminalAuth) {
const baseArgs = process.argv.slice(1);
claudeLoginMethod._meta = {
"terminal-auth": {
command: process.execPath,
args: [...baseArgs, "--cli", "auth", "login", "--claudeai"],
label: "Claude Login",
},
};
consoleLoginMethod._meta = {
"terminal-auth": {
command: process.execPath,
args: [...baseArgs, "--cli", "auth", "login", "--console"],
label: "Anthropic Console Login",
},
};
}
if (!shouldHideClaudeAuth() && (supportsTerminalAuth || supportsMetaTerminalAuth)) {
terminalAuthMethods.push(claudeLoginMethod);
}
if (supportsTerminalAuth || supportsMetaTerminalAuth) {
terminalAuthMethods.push(consoleLoginMethod);
}
}
return {
@@ -356,12 +425,7 @@ export class ClaudeAcpAgent implements Agent {
title: "Claude Agent",
version: packageJson.version,
},
authMethods: [
...(!shouldHideClaudeAuth() && (supportsTerminalAuth || supportsMetaTerminalAuth)
? [terminalAuthMethod]
: []),
...(supportsGatewayAuth ? [gatewayAuthMethod] : []),
],
authMethods: [...terminalAuthMethods, ...(supportsGatewayAuth ? [gatewayAuthMethod] : [])],
};
}
@@ -468,6 +532,8 @@ export class ClaudeAcpAgent implements Agent {
};
let lastAssistantTotalUsage: number | null = null;
let lastAssistantModel: string | null = null;
let lastContextWindowSize: number = 200000;
const userMessage = promptToClaude(params);
@@ -527,9 +593,26 @@ export class ClaudeAcpAgent implements Agent {
break;
}
case "compact_boundary": {
// We don't know the exact size, but since we compacted,
// we set it to zero. The client gets the exact size on the next message.
// Send used:0 immediately so the client doesn't keep showing
// the stale pre-compaction context size until the next turn.
//
// This is a deliberate approximation: we don't know the exact
// post-compaction token count (only the SDK's next API call
// reveals that). But used:0 is directionally correct — context
// just dropped dramatically — and the real value replaces it
// within seconds when the next result message arrives.
// The alternative (no update) leaves the client showing e.g.
// "944k/1m" right after the user sees "Compacting completed",
// which is confusing and wrong.
lastAssistantTotalUsage = 0;
await this.client.sessionUpdate({
sessionId: message.session_id,
update: {
sessionUpdate: "usage_update",
used: 0,
size: lastContextWindowSize,
},
});
await this.client.sessionUpdate({
sessionId: message.session_id,
update: {
@@ -578,10 +661,11 @@ export class ClaudeAcpAgent implements Agent {
session.accumulatedUsage.cachedReadTokens += message.usage.cache_read_input_tokens;
session.accumulatedUsage.cachedWriteTokens += message.usage.cache_creation_input_tokens;
// Calculate context window size from modelUsage (minimum across all models used)
const contextWindows = Object.values(message.modelUsage).map((m) => m.contextWindow);
const contextWindowSize =
contextWindows.length > 0 ? Math.min(...contextWindows) : 200000;
const matchingModelUsage = lastAssistantModel
? getMatchingModelUsage(message.modelUsage, lastAssistantModel)
: null;
const contextWindowSize = matchingModelUsage?.contextWindow ?? 200000;
lastContextWindowSize = contextWindowSize;
// Send usage_update notification
if (lastAssistantTotalUsage !== null) {
@@ -707,6 +791,11 @@ export class ClaudeAcpAgent implements Agent {
}
// Store latest assistant usage (excluding subagents)
// Sum all token types as a proxy for post-turn context occupancy:
// current turn's output will become next turn's input.
// Note: per the Anthropic API, input_tokens excludes cache tokens —
// cache_read and cache_creation are reported separately, so summing
// all four fields is not double-counting.
if ((message.message as any).usage && message.parent_tool_use_id === null) {
const messageWithUsage = message.message as unknown as SDKResultMessage;
lastAssistantTotalUsage =
@@ -715,6 +804,16 @@ export class ClaudeAcpAgent implements Agent {
messageWithUsage.usage.cache_read_input_tokens +
messageWithUsage.usage.cache_creation_input_tokens;
}
// Track the current top-level model for context window size lookup
// (exclude subagent messages to stay in sync with lastAssistantTotalUsage)
if (
message.type === "assistant" &&
message.parent_tool_use_id === null &&
message.message.model &&
message.message.model !== "<synthetic>"
) {
lastAssistantModel = message.message.model;
}
// Slash commands like /compact can generate invalid output... doesn't match
// their own docs: https://docs.anthropic.com/en/docs/claude-code/sdk/sdk-slash-commands#%2Fcompact-compact-conversation-history
@@ -846,17 +945,24 @@ export class ClaudeAcpAgent implements Agent {
await session.query.interrupt();
}
async unstable_closeSession(params: CloseSessionRequest): Promise<CloseSessionResponse> {
const session = this.sessions[params.sessionId];
/** Cleanly tear down a session: cancel in-flight work, dispose resources,
* and remove it from the session map. */
private async teardownSession(sessionId: string): Promise<void> {
const session = this.sessions[sessionId];
if (!session) {
throw new Error("Session not found");
return;
}
await this.cancel({ sessionId: params.sessionId });
await this.cancel({ sessionId });
session.settingsManager.dispose();
session.abortController.abort();
delete this.sessions[params.sessionId];
delete this.sessions[sessionId];
}
async unstable_closeSession(params: CloseSessionRequest): Promise<CloseSessionResponse> {
if (!this.sessions[params.sessionId]) {
throw new Error("Session not found");
}
await this.teardownSession(params.sessionId);
return {};
}
@@ -951,6 +1057,7 @@ export class ClaudeAcpAgent implements Agent {
private async applySessionMode(sessionId: string, modeId: string): Promise<void> {
switch (modeId) {
case "auto":
case "default":
case "acceptEdits":
case "bypassPermissions":
@@ -1204,12 +1311,20 @@ export class ClaudeAcpAgent implements Agent {
}): Promise<NewSessionResponse> {
const existingSession = this.sessions[params.sessionId];
if (existingSession) {
return {
sessionId: params.sessionId,
modes: existingSession.modes,
models: existingSession.models,
configOptions: existingSession.configOptions,
};
const fingerprint = computeSessionFingerprint(params);
if (fingerprint === existingSession.sessionFingerprint) {
return {
sessionId: params.sessionId,
modes: existingSession.modes,
models: existingSession.models,
configOptions: existingSession.configOptions,
};
}
// Session-defining params changed (e.g. cwd pointed at a git worktree,
// or MCP servers reconfigured). Tear down the existing session and
// recreate it so the underlying Query process picks up the new values.
await this.teardownSession(params.sessionId);
}
const response = await this.createSession(
@@ -1428,6 +1543,11 @@ export class ClaudeAcpAgent implements Agent {
const models = await getAvailableModels(q, initializationResult.models, settingsManager);
const availableModes = [
{
id: "auto",
name: "Auto",
decription: "Use a model classifier to approve/deny permission prompts.",
},
{
id: "default",
name: "Default",
@@ -1470,6 +1590,7 @@ export class ClaudeAcpAgent implements Agent {
input: input,
cancelled: false,
cwd: params.cwd,
sessionFingerprint: computeSessionFingerprint(params),
settingsManager,
accumulatedUsage: {
inputTokens: 0,
@@ -1638,7 +1759,16 @@ async function getAvailableModels(
let currentModel = models[0];
if (settings.model) {
// Model priority (highest to lowest):
// 1. ANTHROPIC_MODEL environment variable
// 2. settings.model (user configuration)
// 3. models[0] (default first model)
if (process.env.ANTHROPIC_MODEL) {
const match = resolveModelPreference(models, process.env.ANTHROPIC_MODEL);
if (match) {
currentModel = match;
}
} else if (settings.model) {
const match = resolveModelPreference(models, settings.model);
if (match) {
currentModel = match;
@@ -2109,3 +2239,28 @@ export function runAcp() {
const stream = ndJsonStream(input, output);
new AgentSideConnection((client) => new ClaudeAcpAgent(client), stream);
}
function commonPrefixLength(a: string, b: string) {
let i = 0;
while (i < a.length && i < b.length && a[i] === b[i]) {
i++;
}
return i;
}
function getMatchingModelUsage(modelUsage: Record<string, ModelUsage>, currentModel: string) {
let bestKey: string | null = null;
let bestLen = 0;
for (const key of Object.keys(modelUsage)) {
const len = commonPrefixLength(key, currentModel);
if (len > bestLen) {
bestLen = len;
bestKey = key;
}
}
if (bestKey) {
return modelUsage[bestKey];
}
}

View File

@@ -25,9 +25,14 @@ export interface ClaudeCodeSettings {
}
/**
* Reads and parses a JSON settings file, returning an empty object if not found or invalid
* Reads and parses a JSON settings file, returning an empty object if not found or invalid.
* Silently ignores missing files (ENOENT) but logs warnings for other errors
* (malformed JSON, permission errors, etc.) to aid debugging.
*/
async function loadSettingsFile(filePath: string | null): Promise<ClaudeCodeSettings> {
async function loadSettingsFile(
filePath: string | null,
logger?: { error: (...args: any[]) => void },
): Promise<ClaudeCodeSettings> {
if (!filePath) {
return {};
}
@@ -35,7 +40,11 @@ async function loadSettingsFile(filePath: string | null): Promise<ClaudeCodeSett
try {
const content = await fs.promises.readFile(filePath, "utf-8");
return JSON.parse(content) as ClaudeCodeSettings;
} catch {
} catch (error) {
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
return {};
}
logger?.error(`Failed to load settings from ${filePath}:`, error);
return {};
}
}
@@ -83,7 +92,9 @@ export class SettingsManager {
private onChange?: () => void;
private logger: { log: (...args: any[]) => void; error: (...args: any[]) => void };
private initialized = false;
private disposed = false;
private debounceTimer: ReturnType<typeof setTimeout> | null = null;
private initPromise: Promise<void> | null = null;
constructor(cwd: string, options?: SettingsManagerOptions) {
this.cwd = cwd;
@@ -98,10 +109,19 @@ export class SettingsManager {
if (this.initialized) {
return;
}
if (this.initPromise) {
return this.initPromise;
}
await this.loadAllSettings();
this.setupWatchers();
this.initialized = true;
this.disposed = false;
this.initPromise = this.loadAllSettings().then(() => {
if (!this.disposed) {
this.setupWatchers();
this.initialized = true;
}
this.initPromise = null;
});
return this.initPromise;
}
/**
@@ -130,10 +150,10 @@ export class SettingsManager {
*/
private async loadAllSettings(): Promise<void> {
const [userSettings, projectSettings, localSettings, enterpriseSettings] = await Promise.all([
loadSettingsFile(this.getUserSettingsPath()),
loadSettingsFile(this.getProjectSettingsPath()),
loadSettingsFile(this.getLocalSettingsPath()),
loadSettingsFile(getManagedSettingsPath()),
loadSettingsFile(this.getUserSettingsPath(), this.logger),
loadSettingsFile(this.getProjectSettingsPath(), this.logger),
loadSettingsFile(this.getLocalSettingsPath(), this.logger),
loadSettingsFile(getManagedSettingsPath(), this.logger),
]);
this.userSettings = userSettings;
@@ -226,9 +246,14 @@ export class SettingsManager {
this.debounceTimer = setTimeout(async () => {
this.debounceTimer = null;
if (this.disposed) {
return;
}
try {
await this.loadAllSettings();
this.onChange?.();
if (!this.disposed) {
this.onChange?.();
}
} catch (error) {
this.logger.error("Failed to reload settings:", error);
}
@@ -259,7 +284,6 @@ export class SettingsManager {
this.dispose();
this.cwd = cwd;
this.initialized = false;
await this.initialize();
}
@@ -267,6 +291,10 @@ export class SettingsManager {
* Disposes of file watchers and cleans up resources
*/
dispose(): void {
this.disposed = true;
this.initialized = false;
this.initPromise = null;
if (this.debounceTimer) {
clearTimeout(this.debounceTimer);
this.debounceTimer = null;
@@ -276,6 +304,5 @@ export class SettingsManager {
watcher.close();
}
this.watchers = [];
this.initialized = false;
}
}

View File

@@ -1328,6 +1328,7 @@ describe("stop reason propagation", () => {
input,
cancelled: false,
cwd: "/test",
sessionFingerprint: JSON.stringify({ cwd: "/test", mcpServers: [] }),
modes: {
currentModeId: "default",
availableModes: [],
@@ -1466,6 +1467,7 @@ describe("stop reason propagation", () => {
query: messageGenerator() as any,
input,
cwd: "/tmp/test",
sessionFingerprint: JSON.stringify({ cwd: "/tmp/test", mcpServers: [] }),
cancelled: false,
modes: {
currentModeId: "default",
@@ -1540,6 +1542,7 @@ describe("session/close", () => {
input: new Pushable(),
cancelled: false,
cwd: "/test",
sessionFingerprint: JSON.stringify({ cwd: "/test", mcpServers: [] }),
modes: {
currentModeId: "default",
availableModes: [],
@@ -1608,3 +1611,582 @@ describe("session/close", () => {
expect(agent.sessions["session-b"]).toBeDefined();
});
});
describe("getOrCreateSession param change detection", () => {
function createMockAgent() {
const mockClient = {
sessionUpdate: async () => {},
} as unknown as AgentSideConnection;
return new ClaudeAcpAgent(mockClient, { log: () => {}, error: () => {} });
}
function injectSession(
agent: ClaudeAcpAgent,
sessionId: string,
opts: { cwd?: string; mcpServers?: { name: string }[] } = {},
) {
const cwd = opts.cwd ?? "/test";
const mcpServers = (opts.mcpServers ?? []) as any[];
function* empty() {}
const gen = Object.assign(empty(), {
interrupt: vi.fn(),
supportedCommands: vi.fn().mockResolvedValue([]),
});
agent.sessions[sessionId] = {
query: gen as any,
input: new Pushable(),
cancelled: false,
cwd,
sessionFingerprint: JSON.stringify({
cwd,
mcpServers: [...mcpServers].sort((a: any, b: any) => a.name.localeCompare(b.name)),
}),
modes: { currentModeId: "default", availableModes: [] },
models: { currentModelId: "default", availableModels: [] },
settingsManager: { dispose: vi.fn() } as any,
accumulatedUsage: {
inputTokens: 0,
outputTokens: 0,
cachedReadTokens: 0,
cachedWriteTokens: 0,
},
configOptions: [],
promptRunning: false,
pendingMessages: new Map(),
nextPendingOrder: 0,
abortController: new AbortController(),
};
return agent.sessions[sessionId]!;
}
it("returns cached session when params are unchanged", async () => {
const agent = createMockAgent();
const session = injectSession(agent, "s1", { cwd: "/project" });
await agent.unstable_resumeSession({
sessionId: "s1",
cwd: "/project",
mcpServers: [],
});
// Session object should be the exact same reference (not recreated)
expect(agent.sessions["s1"]).toBe(session);
expect(session.settingsManager.dispose).not.toHaveBeenCalled();
});
it("tears down existing session when cwd changes", async () => {
const agent = createMockAgent();
const session = injectSession(agent, "s1", { cwd: "/old" });
// Mock createSession to avoid spawning a real process.
// It will throw, but we can catch that — we only need to verify
// the old session was torn down before createSession was attempted.
const createSessionSpy = vi
.spyOn(agent as any, "createSession")
.mockRejectedValue(new Error("mock"));
await expect(
agent.unstable_resumeSession({ sessionId: "s1", cwd: "/new", mcpServers: [] }),
).rejects.toThrow("mock");
// Old session should have been fully torn down
expect(session.settingsManager.dispose).toHaveBeenCalled();
expect(session.abortController.signal.aborted).toBe(true);
expect(session.query.interrupt).toHaveBeenCalled();
expect(agent.sessions["s1"]).toBeUndefined();
// createSession should have been called with the new cwd
expect(createSessionSpy).toHaveBeenCalledWith(
expect.objectContaining({ cwd: "/new" }),
expect.objectContaining({ resume: "s1" }),
);
});
it("tears down existing session when mcpServers change", async () => {
const agent = createMockAgent();
const session = injectSession(agent, "s1", { cwd: "/project" });
const createSessionSpy = vi
.spyOn(agent as any, "createSession")
.mockRejectedValue(new Error("mock"));
await expect(
agent.unstable_resumeSession({
sessionId: "s1",
cwd: "/project",
mcpServers: [{ name: "new-server", command: "node", args: ["server.js"], env: [] }],
}),
).rejects.toThrow("mock");
expect(session.settingsManager.dispose).toHaveBeenCalled();
expect(session.abortController.signal.aborted).toBe(true);
expect(agent.sessions["s1"]).toBeUndefined();
expect(createSessionSpy).toHaveBeenCalled();
});
it("treats mcpServers in different order as unchanged", async () => {
const agent = createMockAgent();
const servers = [
{ name: "b-server", command: "node", args: ["b.js"], env: [] },
{ name: "a-server", command: "node", args: ["a.js"], env: [] },
] as const;
const session = injectSession(agent, "s1", {
cwd: "/project",
mcpServers: servers as any,
});
// Same servers but reversed order — should NOT trigger teardown
await agent.unstable_resumeSession({
sessionId: "s1",
cwd: "/project",
mcpServers: [...servers].reverse() as any,
});
expect(agent.sessions["s1"]).toBe(session);
expect(session.settingsManager.dispose).not.toHaveBeenCalled();
});
});
describe("usage_update computation", () => {
function createAssistantMessage(overrides: {
model: string;
usage?: {
input_tokens: number;
output_tokens: number;
cache_read_input_tokens: number;
cache_creation_input_tokens: number;
};
}) {
return {
type: "assistant" as const,
parent_tool_use_id: null,
uuid: randomUUID(),
session_id: "test-session",
message: {
model: overrides.model,
content: [{ type: "text", text: "hello" }],
usage: overrides.usage ?? {
input_tokens: 100,
output_tokens: 50,
cache_read_input_tokens: 20,
cache_creation_input_tokens: 10,
},
},
};
}
function createResultMessageWithModel(overrides: {
modelUsage: Record<
string,
{
inputTokens: number;
outputTokens: number;
cacheReadInputTokens: number;
cacheCreationInputTokens: number;
webSearchRequests: number;
costUSD: number;
contextWindow: number;
maxOutputTokens: number;
}
>;
}) {
return {
type: "result" as const,
subtype: "success" as const,
stop_reason: "end_turn",
is_error: false,
result: "",
errors: [],
duration_ms: 0,
duration_api_ms: 0,
num_turns: 1,
total_cost_usd: 0.01,
usage: {
input_tokens: 10,
output_tokens: 5,
cache_read_input_tokens: 0,
cache_creation_input_tokens: 0,
},
modelUsage: overrides.modelUsage,
permission_denials: [],
uuid: randomUUID(),
session_id: "test-session",
};
}
function createMockAgentWithCapture() {
const updates: any[] = [];
const mockClient = {
sessionUpdate: async (notification: any) => {
updates.push(notification);
},
} as unknown as AgentSideConnection;
const agent = new ClaudeAcpAgent(mockClient, { log: () => {}, error: () => {} });
return { agent, updates };
}
function injectSession(agent: ClaudeAcpAgent, messages: any[]) {
const input = new Pushable<any>();
async function* messageGenerator() {
// Wait for the prompt to push its user message so we can replay it
const iter = input[Symbol.asyncIterator]();
const { value: userMessage, done } = await iter.next();
if (!done && userMessage) {
yield {
type: "user",
message: userMessage.message,
parent_tool_use_id: null,
uuid: userMessage.uuid,
session_id: "test-session",
isReplay: true,
};
}
yield* messages;
}
agent.sessions["test-session"] = {
query: messageGenerator() as any,
input,
cancelled: false,
cwd: "/test",
sessionFingerprint: JSON.stringify({ cwd: "/test", mcpServers: [] }),
modes: {
currentModeId: "default",
availableModes: [],
},
models: {
currentModelId: "default",
availableModels: [],
},
settingsManager: {} as any,
accumulatedUsage: {
inputTokens: 0,
outputTokens: 0,
cachedReadTokens: 0,
cachedWriteTokens: 0,
},
configOptions: [],
promptRunning: false,
pendingMessages: new Map(),
nextPendingOrder: 0,
abortController: new AbortController(),
};
}
it("used sums all token types as post-turn context occupancy proxy", async () => {
const { agent, updates } = createMockAgentWithCapture();
injectSession(agent, [
createAssistantMessage({
model: "claude-opus-4-20250514",
usage: {
input_tokens: 1000,
output_tokens: 500,
cache_read_input_tokens: 200,
cache_creation_input_tokens: 100,
},
}),
createResultMessageWithModel({
modelUsage: {
"claude-opus-4-20250514": {
inputTokens: 1000,
outputTokens: 500,
cacheReadInputTokens: 200,
cacheCreationInputTokens: 100,
webSearchRequests: 0,
costUSD: 0.01,
contextWindow: 1000000,
maxOutputTokens: 16384,
},
},
}),
{ type: "system", subtype: "session_state_changed", state: "idle" },
]);
await agent.prompt({ sessionId: "test-session", prompt: [{ type: "text", text: "test" }] });
const usageUpdate = updates.find((u: any) => u.update?.sessionUpdate === "usage_update");
expect(usageUpdate).toBeDefined();
// used = input(1000) + output(500) + cache_read(200) + cache_creation(100) = 1800
expect(usageUpdate.update.used).toBe(1800);
});
it("size reflects the current model's context window, not min across all", async () => {
const { agent, updates } = createMockAgentWithCapture();
injectSession(agent, [
createAssistantMessage({ model: "claude-opus-4-20250514" }),
createResultMessageWithModel({
modelUsage: {
"claude-opus-4-20250514": {
inputTokens: 100,
outputTokens: 50,
cacheReadInputTokens: 20,
cacheCreationInputTokens: 10,
webSearchRequests: 0,
costUSD: 0.01,
contextWindow: 1000000,
maxOutputTokens: 16384,
},
"claude-sonnet-4-20250514": {
inputTokens: 50,
outputTokens: 25,
cacheReadInputTokens: 10,
cacheCreationInputTokens: 5,
webSearchRequests: 0,
costUSD: 0.005,
contextWindow: 200000,
maxOutputTokens: 16384,
},
},
}),
{ type: "system", subtype: "session_state_changed", state: "idle" },
]);
await agent.prompt({ sessionId: "test-session", prompt: [{ type: "text", text: "test" }] });
const usageUpdate = updates.find((u: any) => u.update?.sessionUpdate === "usage_update");
expect(usageUpdate).toBeDefined();
// size should be 1000000 (Opus), not 200000 (min of both)
expect(usageUpdate.update.size).toBe(1000000);
});
it("after model switch, size updates to the new model's window", async () => {
const { agent, updates } = createMockAgentWithCapture();
// Simulate: assistant on Sonnet with both models in modelUsage
injectSession(agent, [
createAssistantMessage({ model: "claude-sonnet-4-20250514" }),
createResultMessageWithModel({
modelUsage: {
"claude-opus-4-20250514": {
inputTokens: 100,
outputTokens: 50,
cacheReadInputTokens: 20,
cacheCreationInputTokens: 10,
webSearchRequests: 0,
costUSD: 0.01,
contextWindow: 1000000,
maxOutputTokens: 16384,
},
"claude-sonnet-4-20250514": {
inputTokens: 50,
outputTokens: 25,
cacheReadInputTokens: 10,
cacheCreationInputTokens: 5,
webSearchRequests: 0,
costUSD: 0.005,
contextWindow: 200000,
maxOutputTokens: 16384,
},
},
}),
{ type: "system", subtype: "session_state_changed", state: "idle" },
]);
await agent.prompt({ sessionId: "test-session", prompt: [{ type: "text", text: "test" }] });
const usageUpdate = updates.find((u: any) => u.update?.sessionUpdate === "usage_update");
expect(usageUpdate).toBeDefined();
// size should be 200000 (Sonnet - the current model)
expect(usageUpdate.update.size).toBe(200000);
});
it("after switching back to original model, size returns to original window", async () => {
const { agent, updates } = createMockAgentWithCapture();
// Last assistant message is Opus again
injectSession(agent, [
createAssistantMessage({ model: "claude-sonnet-4-20250514" }),
createAssistantMessage({ model: "claude-opus-4-20250514" }),
createResultMessageWithModel({
modelUsage: {
"claude-opus-4-20250514": {
inputTokens: 200,
outputTokens: 100,
cacheReadInputTokens: 40,
cacheCreationInputTokens: 20,
webSearchRequests: 0,
costUSD: 0.02,
contextWindow: 1000000,
maxOutputTokens: 16384,
},
"claude-sonnet-4-20250514": {
inputTokens: 50,
outputTokens: 25,
cacheReadInputTokens: 10,
cacheCreationInputTokens: 5,
webSearchRequests: 0,
costUSD: 0.005,
contextWindow: 200000,
maxOutputTokens: 16384,
},
},
}),
{ type: "system", subtype: "session_state_changed", state: "idle" },
]);
await agent.prompt({ sessionId: "test-session", prompt: [{ type: "text", text: "test" }] });
const usageUpdate = updates.find((u: any) => u.update?.sessionUpdate === "usage_update");
expect(usageUpdate).toBeDefined();
// size should be 1000000 (Opus - switched back)
expect(usageUpdate.update.size).toBe(1000000);
});
it("subagent assistant messages do not affect size (top-level model is used)", async () => {
const { agent, updates } = createMockAgentWithCapture();
// Top-level assistant on Opus, then subagent on Haiku (parent_tool_use_id set)
injectSession(agent, [
createAssistantMessage({ model: "claude-opus-4-20250514" }),
{
type: "assistant" as const,
parent_tool_use_id: "tool_use_123",
uuid: randomUUID(),
session_id: "test-session",
message: {
model: "claude-haiku-4-5-20251001",
content: [{ type: "text", text: "subagent response" }],
usage: {
input_tokens: 50,
output_tokens: 25,
cache_read_input_tokens: 0,
cache_creation_input_tokens: 0,
},
},
},
createResultMessageWithModel({
modelUsage: {
"claude-opus-4-20250514": {
inputTokens: 100,
outputTokens: 50,
cacheReadInputTokens: 20,
cacheCreationInputTokens: 10,
webSearchRequests: 0,
costUSD: 0.01,
contextWindow: 1000000,
maxOutputTokens: 16384,
},
"claude-haiku-4-5-20251001": {
inputTokens: 50,
outputTokens: 25,
cacheReadInputTokens: 0,
cacheCreationInputTokens: 0,
webSearchRequests: 0,
costUSD: 0.001,
contextWindow: 200000,
maxOutputTokens: 8192,
},
},
}),
{ type: "system", subtype: "session_state_changed", state: "idle" },
]);
await agent.prompt({ sessionId: "test-session", prompt: [{ type: "text", text: "test" }] });
const usageUpdate = updates.find((u: any) => u.update?.sessionUpdate === "usage_update");
expect(usageUpdate).toBeDefined();
// size should be 1000000 (Opus - the top-level model), NOT 200000 (Haiku subagent)
expect(usageUpdate.update.size).toBe(1000000);
});
it("prefix-matches when assistant model has date suffix but modelUsage key does not", async () => {
const { agent, updates } = createMockAgentWithCapture();
// The API response has the full versioned model ID on assistant messages,
// but the SDK's streaming path may key modelUsage by the shorter alias.
injectSession(agent, [
createAssistantMessage({ model: "claude-opus-4-6-20250514" }),
createResultMessageWithModel({
modelUsage: {
"claude-opus-4-6": {
inputTokens: 100,
outputTokens: 50,
cacheReadInputTokens: 20,
cacheCreationInputTokens: 10,
webSearchRequests: 0,
costUSD: 0.01,
contextWindow: 1000000,
maxOutputTokens: 16384,
},
},
}),
{ type: "system", subtype: "session_state_changed", state: "idle" },
]);
await agent.prompt({ sessionId: "test-session", prompt: [{ type: "text", text: "test" }] });
const usageUpdate = updates.find((u: any) => u.update?.sessionUpdate === "usage_update");
expect(usageUpdate).toBeDefined();
// Should match via prefix: "claude-opus-4-6-20250514".startsWith("claude-opus-4-6")
expect(usageUpdate.update.size).toBe(1000000);
});
it("prefix-matches when modelUsage key has date suffix but assistant model does not", async () => {
const { agent, updates } = createMockAgentWithCapture();
injectSession(agent, [
createAssistantMessage({ model: "claude-opus-4-6" }),
createResultMessageWithModel({
modelUsage: {
"claude-opus-4-6-20250514": {
inputTokens: 100,
outputTokens: 50,
cacheReadInputTokens: 20,
cacheCreationInputTokens: 10,
webSearchRequests: 0,
costUSD: 0.01,
contextWindow: 1000000,
maxOutputTokens: 16384,
},
},
}),
{ type: "system", subtype: "session_state_changed", state: "idle" },
]);
await agent.prompt({ sessionId: "test-session", prompt: [{ type: "text", text: "test" }] });
const usageUpdate = updates.find((u: any) => u.update?.sessionUpdate === "usage_update");
expect(usageUpdate).toBeDefined();
expect(usageUpdate.update.size).toBe(1000000);
});
it("synthetic assistant messages do not override lastAssistantModel", async () => {
const { agent, updates } = createMockAgentWithCapture();
// Real assistant on Opus, then a synthetic message (e.g. from /compact)
injectSession(agent, [
createAssistantMessage({ model: "claude-opus-4-20250514" }),
{
type: "assistant" as const,
parent_tool_use_id: null,
uuid: randomUUID(),
session_id: "test-session",
message: {
model: "<synthetic>",
content: [{ type: "text", text: "compacted" }],
usage: {
input_tokens: 0,
output_tokens: 0,
cache_read_input_tokens: 0,
cache_creation_input_tokens: 0,
},
},
},
createResultMessageWithModel({
modelUsage: {
"claude-opus-4-20250514": {
inputTokens: 100,
outputTokens: 50,
cacheReadInputTokens: 20,
cacheCreationInputTokens: 10,
webSearchRequests: 0,
costUSD: 0.01,
contextWindow: 1000000,
maxOutputTokens: 16384,
},
},
}),
{ type: "system", subtype: "session_state_changed", state: "idle" },
]);
await agent.prompt({ sessionId: "test-session", prompt: [{ type: "text", text: "test" }] });
const usageUpdate = updates.find((u: any) => u.update?.sessionUpdate === "usage_update");
expect(usageUpdate).toBeDefined();
// size should be 1000000 (Opus), not 200000 (the fallback if <synthetic> overrode the model)
expect(usageUpdate.update.size).toBe(1000000);
});
});

View File

@@ -123,14 +123,17 @@ describe("authorization", () => {
} as any,
});
expect(initializeResponse.authMethods).not.toContainEqual(
expect.objectContaining({ id: "claude-login" }),
expect.objectContaining({ id: "claude-ai-login" }),
);
expect(initializeResponse.authMethods).not.toContainEqual(
expect.objectContaining({ id: "console-login" }),
);
expect(initializeResponse.authMethods).toContainEqual(
expect.objectContaining({ id: "gateway" }),
);
});
it("hide terminal auth even when terminal-auth is set", async () => {
it("hide claude auth but still show console login when terminal-auth is set", async () => {
const [agent] = await createAgentMock();
vi.stubGlobal("process", { ...process, argv: ["--hide-claude-auth"] });
@@ -140,7 +143,68 @@ describe("authorization", () => {
_meta: { "terminal-auth": true },
},
});
expect(initializeResponse.authMethods).toStrictEqual([]);
expect(initializeResponse.authMethods).not.toContainEqual(
expect.objectContaining({ id: "claude-ai-login" }),
);
expect(initializeResponse.authMethods).toContainEqual(
expect.objectContaining({ id: "console-login" }),
);
});
it("hide claude auth but still show console login with terminal capability", async () => {
const [agent] = await createAgentMock();
vi.stubGlobal("process", { ...process, argv: ["--hide-claude-auth"] });
const initializeResponse = await agent.initialize({
protocolVersion: 1,
clientCapabilities: {
auth: { terminal: true },
},
});
expect(initializeResponse.authMethods).not.toContainEqual(
expect.objectContaining({ id: "claude-ai-login" }),
);
expect(initializeResponse.authMethods).toContainEqual(
expect.objectContaining({ id: "console-login" }),
);
});
it("NO_BROWSER falls back to single legacy login method", async () => {
const [agent] = await createAgentMock();
vi.stubGlobal("process", { ...process, env: { ...process.env, NO_BROWSER: "1" } });
const initializeResponse = await agent.initialize({
protocolVersion: 1,
clientCapabilities: { auth: { terminal: true } },
});
expect(initializeResponse.authMethods).toContainEqual(
expect.objectContaining({ id: "claude-login" }),
);
expect(initializeResponse.authMethods).not.toContainEqual(
expect.objectContaining({ id: "claude-ai-login" }),
);
expect(initializeResponse.authMethods).not.toContainEqual(
expect.objectContaining({ id: "console-login" }),
);
});
it("NO_BROWSER respects hide-claude-auth", async () => {
const [agent] = await createAgentMock();
vi.stubGlobal("process", {
...process,
argv: ["--hide-claude-auth"],
env: { ...process.env, NO_BROWSER: "1" },
});
const initializeResponse = await agent.initialize({
protocolVersion: 1,
clientCapabilities: { auth: { terminal: true } },
});
expect(initializeResponse.authMethods).not.toContainEqual(
expect.objectContaining({ id: "claude-login" }),
);
});
it("show claude authentication", async () => {
@@ -152,7 +216,10 @@ describe("authorization", () => {
});
expect(initializeResponse.authMethods).toContainEqual(
expect.objectContaining({ id: "claude-login" }),
expect.objectContaining({ id: "claude-ai-login" }),
);
expect(initializeResponse.authMethods).toContainEqual(
expect.objectContaining({ id: "console-login" }),
);
});
});