Compare commits

...

2 Commits

Author SHA1 Message Date
acp-release-bot[bot]
a1d83c6031 chore(main): release 0.103.0 (#1559)
🤖 I have created a release *beep* *boop*
---


##
[0.103.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.102.0...v0.103.0)
(2026-11-10)


### ⚠ BREAKING CHANGES

* deep imports of `dist/` files fail with
`ERR_PACKAGE_PATH_NOT_EXPORTED`, and `lib.ts` exports only `serveAcp`,
`AUTH_STATUS_UPDATE_METHOD` and their types.

### Features

* serve ACP v2 with a direct v2 agent and remove the v1 bridge
([#1560](https://github.com/agentclientprotocol/claude-agent-acp/issues/1560))
([cb285cd](cb285cd285))


### Bug Fixes

* give subagent checklists their own plan ID
([#1558](https://github.com/agentclientprotocol/claude-agent-acp/issues/1558))
([2f7e386](2f7e386f36))


### Code Refactoring

* export only lib.ts, with serveAcp and the authStatus wire names
([#1566](https://github.com/agentclientprotocol/claude-agent-acp/issues/1566))
([566e265](566e2652a9))

---
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-11-10 09:35:53 +01:00
Ben Brandt
966aee0f04 refactor: move the test-only tool render and metadata wrappers into src/tests/ (#1569)
`toolInfoFromToolUse` and `toolUpdateFromToolResult` in `src/tools.ts`
and `isLocalCommandMetadata` in `src/message-filters.ts` were public
`lib.ts` exports. #1566 removed them from `lib.ts`, so now only tests
call them. They're thin wrappers: the first two build an
`AcpToolCallRenderer` for one tool use or result, and the third checks
that `stripLocalCommandMetadata` drops everything.

They move unchanged to `src/tests/tool-render.ts`. `tools.test.ts`,
`diff-patch.test.ts` and `v1/acp-agent.test.ts` import them from there.
Production code renders through `AcpToolCallRenderer` directly, as
before. Code changes only: no test changes and no behavior change.

A scan of `src/` for exports finds no export that nothing uses. The only
remaining test-only exports are the deliberate test hooks
`clearDiffMemo` (`diff.ts`) and `sleep` (`utils.ts`).

Test results:
- `npx tsc --noEmit`, `npm run check`, `npm run build`: pass
- `npx vitest run`: 3939 passed / 33 skipped
2026-11-10 08:31:08 +00:00
10 changed files with 97 additions and 72 deletions

View File

@@ -1,3 +1,3 @@
{
".": "0.102.0"
".": "0.103.0"
}

View File

@@ -1,5 +1,26 @@
# Changelog
## [0.103.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.102.0...v0.103.0) (2026-11-10)
### ⚠ BREAKING CHANGES
* deep imports of `dist/` files fail with `ERR_PACKAGE_PATH_NOT_EXPORTED`, and `lib.ts` exports only `serveAcp`, `AUTH_STATUS_UPDATE_METHOD` and their types.
### Features
* serve ACP v2 with a direct v2 agent and remove the v1 bridge ([#1560](https://github.com/agentclientprotocol/claude-agent-acp/issues/1560)) ([cb285cd](https://github.com/agentclientprotocol/claude-agent-acp/commit/cb285cd2857924c07038c129cc836da007e2737f))
### Bug Fixes
* give subagent checklists their own plan ID ([#1558](https://github.com/agentclientprotocol/claude-agent-acp/issues/1558)) ([2f7e386](https://github.com/agentclientprotocol/claude-agent-acp/commit/2f7e386f3600658d905906f3b37301120b07605f))
### Code Refactoring
* export only lib.ts, with serveAcp and the authStatus wire names ([#1566](https://github.com/agentclientprotocol/claude-agent-acp/issues/1566)) ([566e265](https://github.com/agentclientprotocol/claude-agent-acp/commit/566e2652a9da5a31dab57a23ea1b06e9fff2ead8))
## [0.102.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.101.1...v0.102.0) (2026-11-09)

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@agentclientprotocol/claude-agent-acp",
"version": "0.102.0",
"version": "0.103.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@agentclientprotocol/claude-agent-acp",
"version": "0.102.0",
"version": "0.103.0",
"license": "Apache-2.0",
"dependencies": {
"@agentclientprotocol/sdk": "2.5.0",

View File

@@ -3,7 +3,7 @@
"publishConfig": {
"access": "public"
},
"version": "0.102.0",
"version": "0.103.0",
"description": "An ACP-compatible coding agent powered by the Claude Agent SDK (TypeScript)",
"main": "dist/lib.js",
"types": "dist/lib.d.ts",

View File

@@ -139,10 +139,6 @@ export function stripLocalCommandMetadata(content: unknown): unknown | null {
return kept;
}
export function isLocalCommandMetadata(content: unknown): boolean {
return stripLocalCommandMetadata(content) === null;
}
/**
* True for the synthetic assistant message the CLI injects into the transcript
* when a turn fails authentication (e.g. "Not logged in · Please run /login",

View File

@@ -15,8 +15,8 @@ import {
} from "../diff.js";
import { AcpToolCallRenderer } from "../tool-calls/renderer.js";
import { buildClaudePermissionPresentation } from "../permissions/presentation.js";
import { toolInfoFromToolUse } from "../tools.js";
import { WriteReporter } from "../tool-calls/reporters/file-edit.js";
import { toolInfoFromToolUse } from "./tool-render.js";
const tempDirectories: string[] = [];

63
src/tests/tool-render.ts Normal file
View File

@@ -0,0 +1,63 @@
/**
* Test shorthands for the shared tool call renderer: one tool use or tool
* result, rendered for a client with the given capabilities. Production code
* renders through {@link AcpToolCallRenderer} directly.
*/
import type {
ToolCallContent,
ToolCallLocation,
ToolKind,
} from "@agentclientprotocol/sdk/unstable";
import { stripLocalCommandMetadata } from "../message-filters.js";
import { ClientCapabilities } from "../tool-calls/client-capabilities.js";
import type { ToolResultBlock } from "../tool-calls/content.js";
import { AcpToolCallRenderer, type RenderedResult } from "../tool-calls/renderer.js";
/**
* The title, kind, content, and locations of a tool use, for a client with the
* given terminal and patch capabilities. The {@link AcpToolCallRenderer} builds
* them from the facts of the tool reporter.
*/
export function toolInfoFromToolUse(
toolUse: any,
supportsTerminalOutput: boolean = false,
cwd?: string,
supportsDiffPatch: boolean = false,
): {
title: string;
kind: ToolKind;
content: ToolCallContent[];
locations?: ToolCallLocation[];
} {
const renderer = new AcpToolCallRenderer(
new ClientCapabilities(supportsTerminalOutput, false, supportsDiffPatch),
);
return renderer.toolInfo({ id: toolUse?.id, name: toolUse?.name, input: toolUse?.input }, cwd);
}
/**
* The result fields of a tool result, for a client with the given terminal
* capabilities. The {@link AcpToolCallRenderer} builds them from the facts of
* the tool reporter.
*/
export function toolUpdateFromToolResult(
toolResult: ToolResultBlock,
toolUse: any | undefined,
supportsTerminalOutput: boolean = false,
toolUseResult?: unknown,
preferTerminalOutputDelta: boolean = false,
): RenderedResult {
const renderer = new AcpToolCallRenderer(
new ClientCapabilities(supportsTerminalOutput, preferTerminalOutputDelta),
);
return renderer.resultFields(
{ id: toolUse?.id, name: toolUse?.name ?? "", input: toolUse?.input },
toolResult as Parameters<AcpToolCallRenderer["resultFields"]>[1],
toolUseResult,
);
}
/** Whether `content` is only Claude Code's local-command metadata, which the agent drops. */
export function isLocalCommandMetadata(content: unknown): boolean {
return stripLocalCommandMetadata(content) === null;
}

View File

@@ -26,12 +26,10 @@ import { AcpClient } from "../acp-client.js";
import { toAcpNotifications, ToolUseCache } from "../sdk-to-acp.js";
import { Logger } from "../logger.js";
import {
toolUpdateFromToolResult,
createPostToolUseHook,
createTaskHook,
clearHookCallbacks,
registerHookCallback,
toolInfoFromToolUse,
planEntries,
applyTaskCreate,
applyTaskList,
@@ -43,6 +41,7 @@ import {
} from "../tools.js";
import { ClientCapabilities as ToolCallCapabilities } from "../tool-calls/client-capabilities.js";
import { AcpToolCallRenderer } from "../tool-calls/renderer.js";
import { toolInfoFromToolUse, toolUpdateFromToolResult } from "./tool-render.js";
/** An AIR client: it gets the ACP tool call contract (`docs/air-extensions.md`). */
const AIR_CLIENT: ClientCapabilities = {

View File

@@ -25,13 +25,7 @@ import {
import type { AcpSessionNotification } from "../../acp-subagents.js";
import { NativeSubagentRuntime } from "../../native-subagents.js";
import { nodeToWebWritable, nodeToWebReadable } from "../../utils.js";
import {
createPostToolUseHook,
markdownEscape,
toolInfoFromToolUse,
toDisplayPath,
toolUpdateFromToolResult,
} from "../../tools.js";
import { createPostToolUseHook, markdownEscape, toDisplayPath } from "../../tools.js";
import { toolUpdateFromDiffToolResponse } from "../../diff.js";
import { ToolCallFieldTracker } from "../../tool-calls/field-tracker.js";
import {
@@ -50,7 +44,6 @@ import {
} from "../../sdk-to-acp.js";
import { promptToClaude } from "../../prompt-to-claude.js";
import {
isLocalCommandMetadata,
isReplayHiddenMetaMessage,
isSyntheticLoginMessage,
stripLocalCommandMetadata,
@@ -124,6 +117,11 @@ import type {
BetaCodeExecutionToolResultBlockParam,
} from "@anthropic-ai/sdk/resources/beta.mjs";
import { validateRecorded } from "../acp-scenarios/schema.js";
import {
isLocalCommandMetadata,
toolInfoFromToolUse,
toolUpdateFromToolResult,
} from "../tool-render.js";
/** The capabilities of an AIR client. Only AIR gets the AIR extensions of
* `docs/air-extensions.md`. */

View File

@@ -1,9 +1,4 @@
import type {
PlanEntry,
ToolCallContent,
ToolCallLocation,
ToolKind,
} from "@agentclientprotocol/sdk/unstable";
import type { PlanEntry } from "@agentclientprotocol/sdk/unstable";
import { HookCallback } from "@anthropic-ai/claude-agent-sdk";
import type {
TaskCreateInput,
@@ -12,56 +7,9 @@ import type {
TaskUpdateInput,
TaskUpdateOutput,
} from "@anthropic-ai/claude-agent-sdk/sdk-tools.js";
import { ClientCapabilities } from "./tool-calls/client-capabilities.js";
import type { ToolResultBlock } from "./tool-calls/content.js";
import { AcpToolCallRenderer, type RenderedResult } from "./tool-calls/renderer.js";
export { markdownEscape, toDisplayPath } from "./tool-calls/content.js";
/**
* The title, kind, content, and locations of a tool use, for a client with the
* given terminal and patch capabilities. The {@link AcpToolCallRenderer} builds
* them from the facts of the tool reporter.
*/
export function toolInfoFromToolUse(
toolUse: any,
supportsTerminalOutput: boolean = false,
cwd?: string,
supportsDiffPatch: boolean = false,
): {
title: string;
kind: ToolKind;
content: ToolCallContent[];
locations?: ToolCallLocation[];
} {
const renderer = new AcpToolCallRenderer(
new ClientCapabilities(supportsTerminalOutput, false, supportsDiffPatch),
);
return renderer.toolInfo({ id: toolUse?.id, name: toolUse?.name, input: toolUse?.input }, cwd);
}
/**
* The result fields of a tool result, for a client with the given terminal
* capabilities. The {@link AcpToolCallRenderer} builds them from the facts of
* the tool reporter.
*/
export function toolUpdateFromToolResult(
toolResult: ToolResultBlock,
toolUse: any | undefined,
supportsTerminalOutput: boolean = false,
toolUseResult?: unknown,
preferTerminalOutputDelta: boolean = false,
): RenderedResult {
const renderer = new AcpToolCallRenderer(
new ClientCapabilities(supportsTerminalOutput, preferTerminalOutputDelta),
);
return renderer.resultFields(
{ id: toolUse?.id, name: toolUse?.name ?? "", input: toolUse?.input },
toolResult as Parameters<AcpToolCallRenderer["resultFields"]>[1],
toolUseResult,
);
}
export type ClaudePlanEntry = {
content: string;
status: "pending" | "in_progress" | "completed";