mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-11-08 18:32:08 +00:00
Compare commits
2 Commits
sd-can-use
...
v0.52.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9163f8553 | ||
|
|
61272acb30 |
@@ -1,3 +1,3 @@
|
||||
{
|
||||
".": "0.51.0"
|
||||
".": "0.52.0"
|
||||
}
|
||||
|
||||
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,5 +1,15 @@
|
||||
# Changelog
|
||||
|
||||
## [0.52.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.51.0...v0.52.0) (2026-06-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add version flag handling ([#813](https://github.com/agentclientprotocol/claude-agent-acp/issues/813)) ([9616bda](https://github.com/agentclientprotocol/claude-agent-acp/commit/9616bdac47505e4a14c36d667fcffc9ae97e1f2a)), closes [#809](https://github.com/agentclientprotocol/claude-agent-acp/issues/809)
|
||||
* **deps-dev:** bump expect-type from 1.3.0 to 1.4.0 in the minor group ([#814](https://github.com/agentclientprotocol/claude-agent-acp/issues/814)) ([61272ac](https://github.com/agentclientprotocol/claude-agent-acp/commit/61272acb30dcafaa2455d334b11ce2ad97339707))
|
||||
* **deps:** Update @anthropic-ai/claude-agent-sdk to 0.3.191 ([#810](https://github.com/agentclientprotocol/claude-agent-acp/issues/810)) ([228f02e](https://github.com/agentclientprotocol/claude-agent-acp/commit/228f02ecfb23be16e59e121c6b42c0f2b2f40a4e))
|
||||
* Push session title updates at turn end ([#812](https://github.com/agentclientprotocol/claude-agent-acp/issues/812)) ([1fe7ec0](https://github.com/agentclientprotocol/claude-agent-acp/commit/1fe7ec09a3a7bcb7501231dae4b0ffe6ef9b70a4))
|
||||
|
||||
## [0.51.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.50.0...v0.51.0) (2026-06-24)
|
||||
|
||||
|
||||
|
||||
10
package-lock.json
generated
10
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@agentclientprotocol/claude-agent-acp",
|
||||
"version": "0.51.0",
|
||||
"version": "0.52.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@agentclientprotocol/claude-agent-acp",
|
||||
"version": "0.51.0",
|
||||
"version": "0.52.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "1.0.0",
|
||||
@@ -2015,9 +2015,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/expect-type": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
|
||||
"integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==",
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz",
|
||||
"integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"version": "0.51.0",
|
||||
"version": "0.52.0",
|
||||
"description": "An ACP-compatible coding agent powered by the Claude Agent SDK (TypeScript)",
|
||||
"main": "dist/lib.js",
|
||||
"types": "dist/lib.d.ts",
|
||||
|
||||
@@ -275,11 +275,6 @@ type Session = {
|
||||
* `tool_result` time so a long-running session doesn't accumulate every
|
||||
* tool call for its whole lifetime. */
|
||||
toolUseCache: ToolUseCache;
|
||||
/**
|
||||
* This lets canUseTool wait for the first tool call message from the SDK
|
||||
* to ensure it emits a tool_call_update only after the first tool_call message.
|
||||
*/
|
||||
waitingForToolCall: WaitingForToolCall;
|
||||
/** Maps the ACP `messageId` we expose to clients (see `messageIdForGrouping`)
|
||||
* to the SDK message uuid that the Agent SDK's rewind/resume APIs key on
|
||||
* (`Query.rewindFiles` takes a user-message uuid; `resumeSessionAt` takes an
|
||||
@@ -394,8 +389,6 @@ export type ToolUpdateMeta = {
|
||||
};
|
||||
};
|
||||
|
||||
export type WaitingForToolCall = Map<string, () => void>;
|
||||
|
||||
export type ToolUseCache = {
|
||||
[key: string]: {
|
||||
type: "tool_use" | "server_tool_use" | "mcp_tool_use";
|
||||
@@ -1696,7 +1689,6 @@ export class ClaudeAcpAgent {
|
||||
"assistant",
|
||||
params.sessionId,
|
||||
session.toolUseCache,
|
||||
session.waitingForToolCall,
|
||||
this.client,
|
||||
this.logger,
|
||||
)) {
|
||||
@@ -1867,7 +1859,6 @@ export class ClaudeAcpAgent {
|
||||
message,
|
||||
params.sessionId,
|
||||
session.toolUseCache,
|
||||
session.waitingForToolCall,
|
||||
this.client,
|
||||
this.logger,
|
||||
{
|
||||
@@ -1968,7 +1959,6 @@ export class ClaudeAcpAgent {
|
||||
message.message.role,
|
||||
params.sessionId,
|
||||
session.toolUseCache,
|
||||
session.waitingForToolCall,
|
||||
this.client,
|
||||
this.logger,
|
||||
{
|
||||
@@ -2099,7 +2089,6 @@ export class ClaudeAcpAgent {
|
||||
message.message.role,
|
||||
params.sessionId,
|
||||
session.toolUseCache,
|
||||
session.waitingForToolCall,
|
||||
this.client,
|
||||
this.logger,
|
||||
{
|
||||
@@ -2467,7 +2456,6 @@ export class ClaudeAcpAgent {
|
||||
|
||||
private async replaySessionHistory(sessionId: string): Promise<void> {
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
const messages = await getSessionMessages(sessionId);
|
||||
|
||||
for (const message of messages) {
|
||||
@@ -2496,7 +2484,6 @@ export class ClaudeAcpAgent {
|
||||
message.message.role,
|
||||
sessionId,
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
this.client,
|
||||
this.logger,
|
||||
{
|
||||
@@ -2545,6 +2532,8 @@ export class ClaudeAcpAgent {
|
||||
|
||||
canUseTool(sessionId: string): CanUseTool {
|
||||
return async (toolName, toolInput, { signal, suggestions, toolUseID }) => {
|
||||
const alwaysAllowLabel = describeAlwaysAllow(suggestions, toolName);
|
||||
const supportsTerminalOutput = this.clientCapabilities?._meta?.["terminal_output"] === true;
|
||||
const session = this.sessions[sessionId];
|
||||
if (!session) {
|
||||
return {
|
||||
@@ -2552,13 +2541,6 @@ export class ClaudeAcpAgent {
|
||||
message: "Session not found",
|
||||
};
|
||||
}
|
||||
if (!session.toolUseCache[toolUseID]) {
|
||||
const { promise, resolve } = Promise.withResolvers<void>();
|
||||
session.waitingForToolCall.set(toolUseID, resolve);
|
||||
await promise;
|
||||
}
|
||||
const alwaysAllowLabel = describeAlwaysAllow(suggestions, toolName);
|
||||
const supportsTerminalOutput = this.clientCapabilities?._meta?.["terminal_output"] === true;
|
||||
|
||||
// AskUserQuestion is surfaced to us as a normal permission check (the SDK
|
||||
// routes it through canUseTool whenever a callback is registered, rather
|
||||
@@ -3419,7 +3401,6 @@ export class ClaudeAcpAgent {
|
||||
) ?? DEFAULT_CONTEXT_WINDOW,
|
||||
taskState,
|
||||
toolUseCache: {},
|
||||
waitingForToolCall: new Map(),
|
||||
messageIdToUuid: new Map(),
|
||||
};
|
||||
|
||||
@@ -4145,7 +4126,6 @@ export function toAcpNotifications(
|
||||
role: "assistant" | "user",
|
||||
sessionId: string,
|
||||
toolUseCache: ToolUseCache,
|
||||
waitingForToolCall: WaitingForToolCall,
|
||||
client: AcpClient,
|
||||
logger: Logger,
|
||||
options?: {
|
||||
@@ -4315,13 +4295,6 @@ export function toAcpNotifications(
|
||||
...toolInfoFromToolUse(chunk, supportsTerminalOutput, options?.cwd),
|
||||
};
|
||||
} else {
|
||||
if (waitingForToolCall.has(chunk.id)) {
|
||||
// If a canUseTool is waiting for the first tool_use chunk,
|
||||
// we can resolve it now.
|
||||
const resolve = waitingForToolCall.get(chunk.id)!;
|
||||
resolve();
|
||||
waitingForToolCall.delete(chunk.id);
|
||||
}
|
||||
// First encounter (streaming content_block_start or replay) —
|
||||
// send as tool_call with terminal_info for Bash tools.
|
||||
update = {
|
||||
@@ -4479,7 +4452,6 @@ export function streamEventToAcpNotifications(
|
||||
message: SDKPartialAssistantMessage,
|
||||
sessionId: string,
|
||||
toolUseCache: ToolUseCache,
|
||||
waitingForToolCall: WaitingForToolCall,
|
||||
client: AcpClient,
|
||||
logger: Logger,
|
||||
options?: {
|
||||
@@ -4497,7 +4469,6 @@ export function streamEventToAcpNotifications(
|
||||
"assistant",
|
||||
sessionId,
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
client,
|
||||
logger,
|
||||
{
|
||||
@@ -4514,7 +4485,6 @@ export function streamEventToAcpNotifications(
|
||||
"assistant",
|
||||
sessionId,
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
client,
|
||||
logger,
|
||||
{
|
||||
|
||||
@@ -118,7 +118,6 @@ function mockSessionState(overrides: Record<string, any> = {}) {
|
||||
contextWindowSize: 200000,
|
||||
taskState: new Map(),
|
||||
toolUseCache: {},
|
||||
waitingForToolCall: new Map(),
|
||||
messageIdToUuid: new Map(),
|
||||
...overrides,
|
||||
} as any;
|
||||
@@ -873,7 +872,6 @@ describe("tool conversions", () => {
|
||||
received.message.role,
|
||||
"test",
|
||||
{},
|
||||
new Map(),
|
||||
{} as AcpClient,
|
||||
console,
|
||||
),
|
||||
@@ -1816,51 +1814,11 @@ describe("permission request cancellation", () => {
|
||||
contextWindowSize: 200000,
|
||||
taskState: new Map(),
|
||||
toolUseCache: {},
|
||||
waitingForToolCall: new Map(),
|
||||
messageIdToUuid: new Map(),
|
||||
} as any;
|
||||
return agent.sessions[sessionId]!;
|
||||
}
|
||||
|
||||
it("waits for the first tool_call before requesting permission", async () => {
|
||||
const requestPermission = vi.fn(async () => ({
|
||||
outcome: { outcome: "selected", optionId: "allow" },
|
||||
}));
|
||||
const mockClient = {
|
||||
sessionUpdate: async () => {},
|
||||
requestPermission,
|
||||
} as unknown as AcpClient;
|
||||
const agent = new ClaudeAcpAgent(mockClient, { log: () => {}, error: () => {} });
|
||||
const session = injectSession(agent, "session-1");
|
||||
|
||||
const pending = agent.canUseTool("session-1")("Bash", { command: "echo hello" }, {
|
||||
signal: new AbortController().signal,
|
||||
suggestions: [],
|
||||
toolUseID: "tool-1",
|
||||
} as any);
|
||||
|
||||
await Promise.resolve();
|
||||
expect(requestPermission).not.toHaveBeenCalled();
|
||||
expect(session.waitingForToolCall.has("tool-1")).toBe(true);
|
||||
|
||||
const notifications = toAcpNotifications(
|
||||
[{ type: "tool_use", id: "tool-1", name: "Bash", input: { command: "echo hello" } }],
|
||||
"assistant",
|
||||
"session-1",
|
||||
session.toolUseCache,
|
||||
session.waitingForToolCall,
|
||||
mockClient,
|
||||
console,
|
||||
);
|
||||
|
||||
expect(notifications[0].update.sessionUpdate).toBe("tool_call");
|
||||
expect(requestPermission).not.toHaveBeenCalled();
|
||||
|
||||
await expect(pending).resolves.toMatchObject({ behavior: "allow" });
|
||||
expect(requestPermission).toHaveBeenCalledTimes(1);
|
||||
expect(session.waitingForToolCall.has("tool-1")).toBe(false);
|
||||
});
|
||||
|
||||
it("forwards the tool-call signal so a pending permission request is cancelled on abort", async () => {
|
||||
let receivedSignal: AbortSignal | undefined;
|
||||
const mockClient = {
|
||||
@@ -1877,13 +1835,7 @@ describe("permission request cancellation", () => {
|
||||
},
|
||||
} as unknown as AcpClient;
|
||||
const agent = new ClaudeAcpAgent(mockClient, { log: () => {}, error: () => {} });
|
||||
const session = injectSession(agent, "session-1");
|
||||
session.toolUseCache["tool-1"] = {
|
||||
type: "tool_use",
|
||||
id: "tool-1",
|
||||
name: "Bash",
|
||||
input: { command: "ls" },
|
||||
};
|
||||
injectSession(agent, "session-1");
|
||||
|
||||
const controller = new AbortController();
|
||||
const pending = agent.canUseTool("session-1")("Bash", { command: "ls" }, {
|
||||
@@ -1908,13 +1860,7 @@ describe("permission request cancellation", () => {
|
||||
requestPermission: async () => ({ outcome: { outcome: "cancelled" } }),
|
||||
} as unknown as AcpClient;
|
||||
const agent = new ClaudeAcpAgent(mockClient, { log: () => {}, error: () => {} });
|
||||
const session = injectSession(agent, "session-1");
|
||||
session.toolUseCache["tool-1"] = {
|
||||
type: "tool_use",
|
||||
id: "tool-1",
|
||||
name: "Bash",
|
||||
input: { command: "ls" },
|
||||
};
|
||||
injectSession(agent, "session-1");
|
||||
|
||||
await expect(
|
||||
agent.canUseTool("session-1")("Bash", { command: "ls" }, {
|
||||
@@ -2618,7 +2564,6 @@ describe("session/close", () => {
|
||||
contextWindowSize: 200000,
|
||||
taskState: new Map(),
|
||||
toolUseCache: {},
|
||||
waitingForToolCall: new Map(),
|
||||
messageIdToUuid: new Map(),
|
||||
};
|
||||
return agent.sessions[sessionId]!;
|
||||
@@ -2704,7 +2649,6 @@ describe("session/delete", () => {
|
||||
contextWindowSize: 200000,
|
||||
taskState: new Map(),
|
||||
toolUseCache: {},
|
||||
waitingForToolCall: new Map(),
|
||||
messageIdToUuid: new Map(),
|
||||
};
|
||||
return agent.sessions[sessionId]!;
|
||||
@@ -2807,7 +2751,6 @@ describe("getOrCreateSession param change detection", () => {
|
||||
contextWindowSize: 200000,
|
||||
taskState: new Map(),
|
||||
toolUseCache: {},
|
||||
waitingForToolCall: new Map(),
|
||||
messageIdToUuid: new Map(),
|
||||
};
|
||||
return agent.sessions[sessionId]!;
|
||||
@@ -5022,7 +4965,6 @@ describe("post-error recovery", () => {
|
||||
contextWindowSize: 200000,
|
||||
taskState: new Map(),
|
||||
toolUseCache: {},
|
||||
waitingForToolCall: new Map(),
|
||||
messageIdToUuid: new Map(),
|
||||
};
|
||||
return { interrupt };
|
||||
@@ -5593,7 +5535,6 @@ describe("session/cancel wedge recovery (issue #680)", () => {
|
||||
contextWindowSize: 200000,
|
||||
taskState: new Map(),
|
||||
toolUseCache: {},
|
||||
waitingForToolCall: new Map(),
|
||||
messageIdToUuid: new Map(),
|
||||
};
|
||||
return { interrupt };
|
||||
@@ -5725,8 +5666,9 @@ describe("streamEventToAcpNotifications", () => {
|
||||
pingMessage,
|
||||
"test-session",
|
||||
{},
|
||||
new Map(),
|
||||
{ sessionUpdate: async () => {} } as unknown as AcpClient,
|
||||
{ sessionUpdate: async () => {} } as unknown as Parameters<
|
||||
typeof streamEventToAcpNotifications
|
||||
>[3],
|
||||
logger,
|
||||
);
|
||||
|
||||
@@ -5748,17 +5690,9 @@ describe("streamEventToAcpNotifications", () => {
|
||||
},
|
||||
} as Parameters<typeof streamEventToAcpNotifications>[0];
|
||||
|
||||
const result = streamEventToAcpNotifications(
|
||||
message,
|
||||
"test",
|
||||
{},
|
||||
new Map(),
|
||||
{} as AcpClient,
|
||||
console,
|
||||
{
|
||||
messageId,
|
||||
},
|
||||
);
|
||||
const result = streamEventToAcpNotifications(message, "test", {}, {} as AcpClient, console, {
|
||||
messageId,
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
{
|
||||
@@ -5782,7 +5716,6 @@ describe("toAcpNotifications messageId", () => {
|
||||
"assistant",
|
||||
"test",
|
||||
{},
|
||||
new Map(),
|
||||
{} as AcpClient,
|
||||
console,
|
||||
{ messageId },
|
||||
@@ -5806,7 +5739,6 @@ describe("toAcpNotifications messageId", () => {
|
||||
"user",
|
||||
"test",
|
||||
{},
|
||||
new Map(),
|
||||
{} as AcpClient,
|
||||
console,
|
||||
{ messageId },
|
||||
@@ -5821,7 +5753,6 @@ describe("toAcpNotifications messageId", () => {
|
||||
"assistant",
|
||||
"test",
|
||||
{},
|
||||
new Map(),
|
||||
{} as AcpClient,
|
||||
console,
|
||||
{ messageId },
|
||||
@@ -5833,15 +5764,7 @@ describe("toAcpNotifications messageId", () => {
|
||||
});
|
||||
|
||||
it("omits messageId when none is supplied", () => {
|
||||
const result = toAcpNotifications(
|
||||
"hello",
|
||||
"assistant",
|
||||
"test",
|
||||
{},
|
||||
new Map(),
|
||||
{} as AcpClient,
|
||||
console,
|
||||
);
|
||||
const result = toAcpNotifications("hello", "assistant", "test", {}, {} as AcpClient, console);
|
||||
expect(result[0].update).not.toHaveProperty("messageId");
|
||||
});
|
||||
|
||||
@@ -5858,7 +5781,6 @@ describe("toAcpNotifications messageId", () => {
|
||||
"assistant",
|
||||
"test",
|
||||
{},
|
||||
new Map(),
|
||||
{} as AcpClient,
|
||||
console,
|
||||
{ messageId, registerHooks: false },
|
||||
@@ -5875,7 +5797,6 @@ describe("toAcpNotifications thinking chunks", () => {
|
||||
"assistant",
|
||||
"test",
|
||||
{},
|
||||
new Map(),
|
||||
{} as AcpClient,
|
||||
console,
|
||||
);
|
||||
@@ -5897,7 +5818,6 @@ describe("toAcpNotifications thinking chunks", () => {
|
||||
"assistant",
|
||||
"test",
|
||||
{},
|
||||
new Map(),
|
||||
{} as AcpClient,
|
||||
console,
|
||||
);
|
||||
@@ -5911,7 +5831,6 @@ describe("toAcpNotifications thinking chunks", () => {
|
||||
"assistant",
|
||||
"test",
|
||||
{},
|
||||
new Map(),
|
||||
{} as AcpClient,
|
||||
console,
|
||||
);
|
||||
@@ -6069,7 +5988,6 @@ describe("agent selection config option", () => {
|
||||
contextWindowSize: 200000,
|
||||
taskState: new Map(),
|
||||
toolUseCache: {},
|
||||
waitingForToolCall: new Map(),
|
||||
messageIdToUuid: new Map(),
|
||||
};
|
||||
return { session: agent.sessions[sessionId]!, applyFlagSettings };
|
||||
|
||||
@@ -124,8 +124,6 @@ describe("session config options", () => {
|
||||
),
|
||||
configOptions: structuredClone(MOCK_CONFIG_OPTIONS),
|
||||
contextWindowSize: 200000,
|
||||
toolUseCache: {},
|
||||
waitingForToolCall: new Map(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1114,12 +1112,6 @@ describe("session config options", () => {
|
||||
{ id: "dontAsk", name: "Don't Ask", description: "Deny if not pre-approved" },
|
||||
],
|
||||
};
|
||||
session.toolUseCache["toolu_1"] = {
|
||||
type: "tool_use",
|
||||
id: "toolu_1",
|
||||
name: "ExitPlanMode",
|
||||
input: { plan: "do stuff" },
|
||||
};
|
||||
|
||||
const canUseTool = (agent as any).canUseTool(SESSION_ID);
|
||||
const signal = new AbortController().signal;
|
||||
@@ -1152,12 +1144,6 @@ describe("session config options", () => {
|
||||
],
|
||||
};
|
||||
permissionResponse = { outcome: { outcome: "selected", optionId: "auto" } };
|
||||
session.toolUseCache["toolu_2"] = {
|
||||
type: "tool_use",
|
||||
id: "toolu_2",
|
||||
name: "ExitPlanMode",
|
||||
input: { plan: "do stuff" },
|
||||
};
|
||||
|
||||
const canUseTool = (agent as any).canUseTool(SESSION_ID);
|
||||
const result = await canUseTool(
|
||||
@@ -1185,12 +1171,6 @@ describe("session config options", () => {
|
||||
{ id: "dontAsk", name: "Don't Ask", description: "Deny if not pre-approved" },
|
||||
],
|
||||
};
|
||||
session.toolUseCache["toolu_3"] = {
|
||||
type: "tool_use",
|
||||
id: "toolu_3",
|
||||
name: "ExitPlanMode",
|
||||
input: { plan: "do stuff" },
|
||||
};
|
||||
|
||||
const canUseTool = (agent as any).canUseTool(SESSION_ID);
|
||||
const signal = new AbortController().signal;
|
||||
|
||||
@@ -10,13 +10,7 @@ import {
|
||||
BetaBashCodeExecutionResultBlock,
|
||||
BetaBashCodeExecutionToolResultBlockParam,
|
||||
} from "@anthropic-ai/sdk/resources/beta.mjs";
|
||||
import {
|
||||
AcpClient,
|
||||
toAcpNotifications,
|
||||
ToolUseCache,
|
||||
Logger,
|
||||
WaitingForToolCall,
|
||||
} from "../acp-agent.js";
|
||||
import { AcpClient, toAcpNotifications, ToolUseCache, Logger } from "../acp-agent.js";
|
||||
import {
|
||||
toolUpdateFromToolResult,
|
||||
createPostToolUseHook,
|
||||
@@ -43,7 +37,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
input: { command: "echo hello" },
|
||||
},
|
||||
};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
const toolResult: ToolResultBlockParam = {
|
||||
type: "tool_result",
|
||||
@@ -57,7 +50,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -80,7 +72,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
input: { file_path: "/test/file.txt" },
|
||||
},
|
||||
};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
// ToolResultBlockParam content can be string or array of TextBlockParam
|
||||
const toolResult: ToolResultBlockParam = {
|
||||
@@ -95,7 +86,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -118,7 +108,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
input: { query: "test" },
|
||||
},
|
||||
};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
// BetaMCPToolResultBlock content can be string or Array<BetaTextBlock>
|
||||
const toolResult: BetaMCPToolResultBlock = {
|
||||
@@ -133,7 +122,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -156,7 +144,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
input: { term: "test" },
|
||||
},
|
||||
};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
// BetaTextBlock requires citations field
|
||||
const arrayContent: BetaTextBlock[] = [
|
||||
@@ -176,7 +163,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -199,7 +185,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
input: { query: "test search" },
|
||||
},
|
||||
};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
// BetaWebSearchResultBlock from SDK
|
||||
const searchResults: BetaWebSearchResultBlock[] = [
|
||||
@@ -223,7 +208,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -246,7 +230,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
input: { command: "ls -la" },
|
||||
},
|
||||
};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
// BetaBashCodeExecutionResultBlock from SDK
|
||||
const bashResult: BetaBashCodeExecutionResultBlock = {
|
||||
@@ -268,7 +251,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -291,7 +273,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
input: { command: "invalid_command" },
|
||||
},
|
||||
};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
const toolResult: ToolResultBlockParam = {
|
||||
type: "tool_result",
|
||||
@@ -305,7 +286,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -328,7 +308,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
input: { todos: [{ content: "Test task", status: "pending" }] },
|
||||
},
|
||||
};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
const toolResult: ToolResultBlockParam = {
|
||||
type: "tool_result",
|
||||
@@ -342,7 +321,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -373,14 +351,11 @@ describe("rawOutput in tool call updates", () => {
|
||||
is_error: false,
|
||||
};
|
||||
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
const notifications = toAcpNotifications(
|
||||
[toolResult],
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -408,7 +383,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
input: { file_path: "/test/image.png" },
|
||||
},
|
||||
};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
const imageBlock: ImageBlockParam = {
|
||||
type: "image",
|
||||
@@ -427,7 +401,6 @@ describe("rawOutput in tool call updates", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -806,7 +779,6 @@ describe("Bash terminal output", () => {
|
||||
// Reset before each test: toAcpNotifications prunes the cache entry once it
|
||||
// maps the tool_result, so a shared object would be empty by the 2nd test.
|
||||
let toolUseCache: ToolUseCache;
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
beforeEach(() => {
|
||||
toolUseCache = {
|
||||
toolu_bash: {
|
||||
@@ -842,7 +814,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
{ clientCapabilities },
|
||||
@@ -883,7 +854,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -910,7 +880,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
{ clientCapabilities },
|
||||
@@ -926,7 +895,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
{ clientCapabilities: { _meta: { terminal_output: true } } },
|
||||
@@ -947,7 +915,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCacheWithoutSupport,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -980,7 +947,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
{ clientCapabilities },
|
||||
@@ -1003,7 +969,6 @@ describe("Bash terminal output", () => {
|
||||
describe("toolUseCache pruning", () => {
|
||||
it("retains the tool_use entry until its result, then prunes it", () => {
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
const toolUse = {
|
||||
type: "tool_use" as const,
|
||||
id: "toolu_read",
|
||||
@@ -1012,15 +977,7 @@ describe("Bash terminal output", () => {
|
||||
};
|
||||
|
||||
// tool_use is cached and kept (the matching result hasn't arrived yet).
|
||||
toAcpNotifications(
|
||||
[toolUse],
|
||||
"assistant",
|
||||
"s",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
toAcpNotifications([toolUse], "assistant", "s", toolUseCache, mockClient, mockLogger);
|
||||
expect(toolUseCache.toolu_read).toBeDefined();
|
||||
|
||||
// tool_result resolves it, so the entry is pruned to bound memory.
|
||||
@@ -1029,15 +986,7 @@ describe("Bash terminal output", () => {
|
||||
tool_use_id: "toolu_read",
|
||||
content: [{ type: "text", text: "hello" }],
|
||||
};
|
||||
toAcpNotifications(
|
||||
[toolResult],
|
||||
"assistant",
|
||||
"s",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
toAcpNotifications([toolResult], "assistant", "s", toolUseCache, mockClient, mockLogger);
|
||||
expect(toolUseCache.toolu_read).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -1045,7 +994,6 @@ describe("Bash terminal output", () => {
|
||||
describe("post-tool-use hook sends diff content for Edit tool", () => {
|
||||
it("should include content and locations from structuredPatch in hook update", async () => {
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
const hookUpdates: any[] = [];
|
||||
const mockClientWithUpdate = {
|
||||
@@ -1071,7 +1019,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClientWithUpdate,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -1126,7 +1073,6 @@ describe("Bash terminal output", () => {
|
||||
|
||||
it("should include multiple diff blocks for replaceAll with multiple hunks", async () => {
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
const hookUpdates: any[] = [];
|
||||
const mockClientWithUpdate = {
|
||||
@@ -1152,7 +1098,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClientWithUpdate,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -1213,7 +1158,6 @@ describe("Bash terminal output", () => {
|
||||
|
||||
it("should not include content/locations for non-Edit tools", async () => {
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
const hookUpdates: any[] = [];
|
||||
const mockClientWithUpdate = {
|
||||
@@ -1234,7 +1178,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClientWithUpdate,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -1270,7 +1213,6 @@ describe("Bash terminal output", () => {
|
||||
// tool_use time and was never corrected after the tool ran.
|
||||
it("should emit a real diff for Write of an existing file (type: update)", async () => {
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
const hookUpdates: any[] = [];
|
||||
const mockClientWithUpdate = {
|
||||
sessionUpdate: async (notification: any) => {
|
||||
@@ -1293,7 +1235,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClientWithUpdate,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -1348,7 +1289,6 @@ describe("Bash terminal output", () => {
|
||||
|
||||
it("should still emit a sensible diff for Write of a brand-new file (type: create)", async () => {
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
const hookUpdates: any[] = [];
|
||||
const mockClientWithUpdate = {
|
||||
sessionUpdate: async (notification: any) => {
|
||||
@@ -1371,7 +1311,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClientWithUpdate,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -1429,7 +1368,6 @@ describe("Bash terminal output", () => {
|
||||
};
|
||||
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
// Capture session updates sent by the hook callback
|
||||
const hookUpdates: any[] = [];
|
||||
@@ -1451,7 +1389,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClientWithUpdate,
|
||||
mockLogger,
|
||||
{ clientCapabilities },
|
||||
@@ -1481,7 +1418,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClientWithUpdate,
|
||||
mockLogger,
|
||||
{ clientCapabilities },
|
||||
@@ -1533,7 +1469,6 @@ describe("Bash terminal output", () => {
|
||||
|
||||
it("should not include terminal _meta in hook update when client lacks terminal_output support", async () => {
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
const hookUpdates: any[] = [];
|
||||
const mockClientWithUpdate = {
|
||||
@@ -1555,7 +1490,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClientWithUpdate,
|
||||
mockLogger,
|
||||
// No clientCapabilities — terminal_output not supported
|
||||
@@ -1580,7 +1514,6 @@ describe("Bash terminal output", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClientWithUpdate,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -1712,7 +1645,6 @@ describe("toAcpNotifications - TodoWrite with undefined input regression", () =>
|
||||
|
||||
it("should not throw when TodoWrite tool_use has undefined input", () => {
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
const notifications = toAcpNotifications(
|
||||
[
|
||||
@@ -1726,7 +1658,6 @@ describe("toAcpNotifications - TodoWrite with undefined input regression", () =>
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -1738,7 +1669,6 @@ describe("toAcpNotifications - TodoWrite with undefined input regression", () =>
|
||||
|
||||
it("should still emit plan update when TodoWrite has valid input", () => {
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
|
||||
const notifications = toAcpNotifications(
|
||||
[
|
||||
@@ -1752,7 +1682,6 @@ describe("toAcpNotifications - TodoWrite with undefined input regression", () =>
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
);
|
||||
@@ -1851,7 +1780,6 @@ describe("toAcpNotifications - Task* tools", () => {
|
||||
|
||||
it("suppresses tool_call for TaskCreate/TaskUpdate/TaskList/TaskGet on tool_use", () => {
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
const taskState: TaskState = new Map();
|
||||
|
||||
const notifications = toAcpNotifications(
|
||||
@@ -1869,7 +1797,6 @@ describe("toAcpNotifications - Task* tools", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
{ taskState },
|
||||
@@ -1881,7 +1808,6 @@ describe("toAcpNotifications - Task* tools", () => {
|
||||
|
||||
it("emits a plan snapshot after a TaskCreate tool_result and accumulates state", () => {
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
const taskState: TaskState = new Map();
|
||||
|
||||
toAcpNotifications(
|
||||
@@ -1896,7 +1822,6 @@ describe("toAcpNotifications - Task* tools", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
{ taskState },
|
||||
@@ -1914,7 +1839,6 @@ describe("toAcpNotifications - Task* tools", () => {
|
||||
"user",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
{ taskState },
|
||||
@@ -1939,7 +1863,6 @@ describe("toAcpNotifications - Task* tools", () => {
|
||||
"assistant",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
{ taskState },
|
||||
@@ -1957,7 +1880,6 @@ describe("toAcpNotifications - Task* tools", () => {
|
||||
"user",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
{ taskState },
|
||||
@@ -1974,7 +1896,6 @@ describe("toAcpNotifications - Task* tools", () => {
|
||||
|
||||
it("emits a plan snapshot reflecting status changes after a TaskUpdate tool_result", () => {
|
||||
const toolUseCache: ToolUseCache = {};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
const taskState: TaskState = new Map([["1", { subject: "First", status: "pending" as const }]]);
|
||||
toolUseCache["update-1"] = {
|
||||
type: "tool_use",
|
||||
@@ -1999,7 +1920,6 @@ describe("toAcpNotifications - Task* tools", () => {
|
||||
"user",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
{ taskState },
|
||||
@@ -2017,7 +1937,6 @@ describe("toAcpNotifications - Task* tools", () => {
|
||||
"list-1": { type: "tool_use", id: "list-1", name: "TaskList", input: {} },
|
||||
"get-1": { type: "tool_use", id: "get-1", name: "TaskGet", input: { taskId: "1" } },
|
||||
};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
const taskState: TaskState = new Map([
|
||||
["1", { subject: "Existing", status: "in_progress" as const }],
|
||||
]);
|
||||
@@ -2030,7 +1949,6 @@ describe("toAcpNotifications - Task* tools", () => {
|
||||
"user",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
{ taskState },
|
||||
@@ -2049,7 +1967,6 @@ describe("toAcpNotifications - Task* tools", () => {
|
||||
input: { subject: "A", description: "" },
|
||||
},
|
||||
};
|
||||
const waitingForToolCall: WaitingForToolCall = new Map();
|
||||
const taskState: TaskState = new Map();
|
||||
|
||||
const notifications = toAcpNotifications(
|
||||
@@ -2064,7 +1981,6 @@ describe("toAcpNotifications - Task* tools", () => {
|
||||
"user",
|
||||
"test-session",
|
||||
toolUseCache,
|
||||
waitingForToolCall,
|
||||
mockClient,
|
||||
mockLogger,
|
||||
{ taskState },
|
||||
|
||||
Reference in New Issue
Block a user