Files
claude-agent-acp/package.json
Ben Brandt ddee24ef8f fix: update to @anthropic-ai/claude-agent-sdk 0.3.323 (#1612)
## Summary

Updates `@anthropic-ai/claude-agent-sdk` from 0.3.322 to 0.3.323, which
bundles Claude Code 2.1.323. The new version needs two adapter fixes,
both included here:

- the session index reads titles by the SDK's new rule;
- the heartbeat of a long-running hook no longer lands on a tool call.

Also bumps these dev dependencies: `@anthropic-ai/sdk` 1.7.0 → 1.8.0,
`@tsconfig/node22` 22.0.6 → 22.0.7 and `prettier` 3.9.10 → 3.10.1.

`npm update` brings the in-range lockfile bumps: `rolldown` 1.2.18 →
1.2.19, `vite` 8.3.7 → 8.3.8, `hono` 4.13.17 → 4.13.18,
`@hono/node-server` 2.1.6 → 2.1.8, and patch releases of
`@babel/runtime`, `brace-expansion`, `encodeurl`,
`@jridgewell/resolve-uri` and `@rolldown/pluginutils`. `rolldown` 1.2.19
lists its wasm32 binding as an optional dependency, so the lockfile
gains `@rolldown/binding-wasm32-wasi`, `@napi-rs/wasm-runtime`,
`@emnapi/core` and `@emnapi/runtime` (2.0.0-beta.2),
`@emnapi/wasi-threads`, `@tybys/wasm-util` and `tslib`. All are dev-only
and optional.

TypeScript stays at 6.0.3: 7.0.2 is out, but `@typescript-eslint/parser`
8.72.2 still requires `typescript <6.1.0`.

## Session titles

`getSessionInfo` and `listSessions` of SDK 0.3.323 read titles
differently, and neither changelog says so. The session index mirrors
the SDK's rule (`sdkTitles` in `src/session-index/transcript-scan.ts`),
so it has to follow.

- Before: the SDK took the last `"customTitle":"…"` text of the tail or
the head, wherever it stood.
- Now: it parses each line that names the field, from the last one back,
and takes the top-level string of the record. For `customTitle` and
`aiTitle` the record must be of type `custom-title` or `ai-title`.
`lastPrompt` and `summary` may be on a record of any type.

What changes for a client:

- A `customTitle` or `lastPrompt` inside a message is no title. A tool
result that shows a transcript no longer renames the session.
- A `custom-title` record that the start of the 64 KB tail window cuts
is not read. The old rule still found its title text.
- A `custom-title` record appended to a line whose write was cut off is
read.

Checked against the real SDK: a differential run of `sdkTitles` against
`getSessionInfo` over 1,800 generated transcripts gave no mismatch. The
old rule mismatched on 371 of 600. The run is not part of this PR; the
tests in `src/tests/v1/session-index.test.ts` compare each case above
with `getSessionInfo`.

## Hook heartbeats

Since Claude Code 2.1.323, a hook that runs long sends a `tool_progress`
beat every 30 seconds. Recorded from the real CLI:

```json
{
  "type": "tool_progress",
  "tool_use_id": "hook-PreToolUse-toolu_01X…-heartbeat-0",
  "tool_name": "PreToolUse",
  "parent_tool_use_id": "toolu_01X…",
  "elapsed_time_seconds": 30,
  "heartbeat": true
}
```

For a PreToolUse or PostToolUse hook, `parent_tool_use_id` is the tool
call. For a UserPromptSubmit or Stop hook it is an id that names no tool
call. The PostToolUse beats come before the tool result.

Both cores send a beat under an unknown id to the call that
`parent_tool_use_id` names. So without a change, a slow PreToolUse or
PostToolUse hook:

- marked the tool call `in_progress` before it ran, on v1 and v2;
- restarted its elapsed time with the hook's (30 → 1 → 2 → 3 → 30 in the
scenario);
- named the call `PreToolUse` in `_meta.claudeCode.toolName` for a plain
or Zed client.

The adapter now drops these beats. This matches how it already ignores
`hook_started`, `hook_progress` and `hook_response`: hooks have no ACP
surface. The rule that picks the tool call of a beat was written twice,
in `src/v1/acp-agent.ts` and `src/v2/stream.ts`. It is now one function,
`progressToolCallId` in `src/tool-calls/renderer.ts`, which holds the
new rule too.

The `tool-progress` scenario carries a PreToolUse and a PostToolUse
beat. Its recordings for the plain, Zed, AIR and v2 clients are
unchanged, and all four fail without the fix.

## Changelog review

Read the SDK changelog for 0.3.323 and the Claude Code changelog for
2.1.323. No other entry needs a code change:

- **Types.** Doc text and new optional members only, plus one new
`SDKStartupFailureReason` (`managed_settings_not_delivered`).
`startupFailureError` treats a reason it does not list as an internal
error with the CLI's message.
- **Context window of an unknown model id**, 200K → 1M. The adapter
reads the window from Claude Code (`getContextUsage`) at session
creation and at every model switch, so it reports the new value. Its own
200K is only the placeholder until that read lands.
- **`canUseTool` suggestions** no longer hold a Bash allow rule for a
write to `.git` or `.claude`. The adapter then offers no "always allow"
option.
- **`init.plugin_errors`** also lists load errors of plugins that
managed settings enable. The adapter only logs them.
- **`forkSession` with `upToMessageId`** and **`getSessionMessages`**
compaction fixes. Picked up as they are: the adapter has no workaround
for the old behavior.
- **A subagent's WebSearch result can carry `tool_use_result`.** The
code reads only fields that this result does not have. One comment in
`src/async-tasks.ts` said that no subagent result carries one; it now
says Bash results.
- **A permission check that fails after a PreToolUse hook allowed the
call** goes to `canUseTool`, which the adapter always provides.

## Not in this PR

Left for follow-ups, because each is its own change:

- The 200K placeholder for the context window. 1M is now the more likely
value, and with it the "1m" text heuristic has nothing left to do.
- `matchDeniedModels()` (alpha). The adapter's own `isDeniedModel`
disagrees with it on 23 of 875 model and entry pairs.
- `supersedes` on the retry of a response whose tool call could not be
parsed. The adapter does not act on `supersedes`.
- `machinePolicy.didNotLoad` (alpha) of `resolveSettings()`.

## Testing

- `npm run build`, `npm run check`, `npm run test:run` (4,121 tests
pass)
- Real CLI: one short session with slow hooks and
`CLAUDE_CODE_HOOK_HEARTBEAT_INTERVAL_MS=1000`, to record the heartbeat
frames and their order
- Real CLI: `getContextUsage` for unknown and known model ids, without a
prompt
2026-11-13 13:56:39 +01:00

93 lines
2.5 KiB
JSON

{
"name": "@agentclientprotocol/claude-agent-acp",
"publishConfig": {
"access": "public"
},
"version": "0.106.0",
"description": "An ACP-compatible coding agent powered by the Claude Agent SDK (TypeScript)",
"main": "dist/lib.js",
"types": "dist/lib.d.ts",
"bin": {
"claude-agent-acp": "dist/index.js"
},
"type": "module",
"exports": {
".": {
"types": "./dist/lib.d.ts",
"import": "./dist/lib.js"
},
"./package.json": "./package.json"
},
"files": [
"dist/",
"!dist/tests/",
"!dist/binary-entry.*",
"README.md",
"LICENSE",
"package.json"
],
"scripts": {
"build": "tsc",
"build:binary": "node scripts/build-binary.mjs",
"smoke:binary": "node scripts/smoke-binary.mjs",
"start": "node dist/index.js",
"dev": "npm run build && npm run start",
"example:simple-client": "node --experimental-strip-types --disable-warning=ExperimentalWarning examples/simple-client.ts",
"lint": "eslint src --ext .ts",
"lint:fix": "eslint src --ext .ts --fix",
"format": "prettier --write .",
"format:check": "prettier --check .",
"check": "npm run lint && npm run format:check",
"release:preflight": "bash scripts/release-preflight.sh",
"test": "vitest",
"test:integration": "RUN_INTEGRATION_TESTS=true vitest run",
"test:run": "vitest run",
"test:coverage": "vitest run --coverage",
"prepublishOnly": "npm run build"
},
"keywords": [
"claude",
"acp",
"agent",
"anthropic",
"typescript",
"sdk",
"code"
],
"homepage": "https://github.com/agentclientprotocol/claude-agent-acp#readme",
"bugs": {
"url": "https://github.com/agentclientprotocol/claude-agent-acp/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/agentclientprotocol/claude-agent-acp.git"
},
"author": "Zed Industries",
"license": "Apache-2.0",
"engines": {
"node": ">=22"
},
"dependencies": {
"@agentclientprotocol/sdk": "2.6.0",
"@anthropic-ai/claude-agent-sdk": "0.3.323",
"diff": "9.0.0",
"zod": "4.6.7"
},
"devDependencies": {
"@anthropic-ai/sdk": "1.8.0",
"@eslint/js": "10.0.1",
"@tsconfig/node22": "22.0.7",
"@types/node": "26.6.6",
"@typescript-eslint/eslint-plugin": "8.72.2",
"@typescript-eslint/parser": "8.72.2",
"ajv": "8.20.0",
"ajv-formats": "3.0.1",
"eslint": "10.14.0",
"eslint-config-prettier": "10.1.8",
"globals": "17.14.0",
"prettier": "3.10.1",
"typescript": "6.0.3",
"vitest": "5.1.0"
}
}