mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-10-28 04:51:50 +00:00
Compare commits
4 Commits
v0.97.1-pr
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c90f856c11 | ||
|
|
059d76e14a | ||
|
|
4324dce4be | ||
|
|
c7c80f7b26 |
@@ -1,3 +1,3 @@
|
||||
{
|
||||
".": "0.97.0"
|
||||
".": "0.98.0"
|
||||
}
|
||||
|
||||
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,5 +1,19 @@
|
||||
# Changelog
|
||||
|
||||
## [0.98.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.97.0...v0.98.0) (2026-10-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add batch session metadata lookup ([#1408](https://github.com/agentclientprotocol/claude-agent-acp/issues/1408)) ([0ce42f2](https://github.com/agentclientprotocol/claude-agent-acp/commit/0ce42f2c312d190f78024d8b4b1ae5f00d9e5939))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* publish Monitor async tasks as monitors ([#1452](https://github.com/agentclientprotocol/claude-agent-acp/issues/1452)) ([4324dce](https://github.com/agentclientprotocol/claude-agent-acp/commit/4324dce4be877c55385b3389cebac1c63d08f456))
|
||||
* settle the tool call of a SandboxNetworkAccess permission request ([#1448](https://github.com/agentclientprotocol/claude-agent-acp/issues/1448)) ([8f43ac8](https://github.com/agentclientprotocol/claude-agent-acp/commit/8f43ac808931a3f14719bbed37b9b153c9933139))
|
||||
* **v2:** leave the tool call status out of permission subjects ([#1447](https://github.com/agentclientprotocol/claude-agent-acp/issues/1447)) ([c7c80f7](https://github.com/agentclientprotocol/claude-agent-acp/commit/c7c80f7b26f8d90f7f1c828036db64bc46dddddf))
|
||||
|
||||
## [0.97.0](https://github.com/agentclientprotocol/claude-agent-acp/compare/v0.96.0...v0.97.0) (2026-10-26)
|
||||
|
||||
|
||||
|
||||
10
package-lock.json
generated
10
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@agentclientprotocol/claude-agent-acp",
|
||||
"version": "0.97.0",
|
||||
"version": "0.98.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@agentclientprotocol/claude-agent-acp",
|
||||
"version": "0.97.0",
|
||||
"version": "0.98.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@agentclientprotocol/sdk": "2.0.2",
|
||||
@@ -477,9 +477,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@modelcontextprotocol/sdk": {
|
||||
"version": "1.32.1",
|
||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.32.1.tgz",
|
||||
"integrity": "sha512-2DdE+SJDtzLEEWzY1ZjY7Q+VcPhcV1KisD3zI4u0XZyktsjHum1mwbMI+JaulUBi2OZk+KJAi2uPXzxichPkdw==",
|
||||
"version": "1.32.2",
|
||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.32.2.tgz",
|
||||
"integrity": "sha512-SWsVtH/0vULSQStoZ6xxH2K09Li8fXYTMC64ZeogCdpZ3XSi1eCPOByV1OpuJxuI3OcmHhosDWYyii07tpPsLw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"version": "0.97.0",
|
||||
"version": "0.98.0",
|
||||
"description": "An ACP-compatible coding agent powered by the Claude Agent SDK (TypeScript)",
|
||||
"main": "dist/lib.js",
|
||||
"types": "dist/lib.d.ts",
|
||||
|
||||
@@ -15,6 +15,8 @@ type AsyncTask = {
|
||||
taskType: string;
|
||||
description: string;
|
||||
showInTranscript: boolean;
|
||||
/** A Monitor tool call or an SDK `local_monitor` task: published as a monitor the client cannot stop. */
|
||||
monitor: boolean;
|
||||
outputFilePath?: string;
|
||||
toolCallId?: string;
|
||||
/**
|
||||
@@ -142,7 +144,8 @@ export class AsyncTaskRuntime {
|
||||
* the tasks that a tool call in another session started, for example in
|
||||
* a native subagent session. `toolNameOf`: the name of the tool of a tool
|
||||
* call, or `undefined` when the tool call is unknown. A task that a
|
||||
* `Monitor` tool call started is ignored. */
|
||||
* `Monitor` tool call started is published as a monitor: the SDK reports
|
||||
* it as `local_bash`, so the adapter names it a monitor. */
|
||||
private readonly options: {
|
||||
notices?: boolean;
|
||||
routeOf?: (toolCallId: string) => Route | undefined;
|
||||
@@ -155,7 +158,7 @@ export class AsyncTaskRuntime {
|
||||
const taskId = taskIdOf(message);
|
||||
if (!taskId) return;
|
||||
const task = this.task(taskId);
|
||||
if (isSubagentTask(message) || isMonitorTask(message)) {
|
||||
if (isSubagentTask(message)) {
|
||||
this.ignore(task);
|
||||
return;
|
||||
}
|
||||
@@ -186,7 +189,7 @@ export class AsyncTaskRuntime {
|
||||
const taskId = taskIdOf(message);
|
||||
if (!taskId) return;
|
||||
const task = this.task(taskId);
|
||||
if (isSubagentTask(message) || isMonitorTask(message)) {
|
||||
if (isSubagentTask(message)) {
|
||||
this.ignore(task);
|
||||
return;
|
||||
}
|
||||
@@ -355,7 +358,7 @@ export class AsyncTaskRuntime {
|
||||
const task = this.task(taskId);
|
||||
if (task.ignored || isTerminal(task.state)) continue;
|
||||
const levelTaskType = field(item, "taskType", "task_type");
|
||||
if (levelTaskType === "local_agent" || levelTaskType === "local_monitor") {
|
||||
if (levelTaskType === "local_agent") {
|
||||
this.ignore(task);
|
||||
continue;
|
||||
}
|
||||
@@ -408,7 +411,13 @@ export class AsyncTaskRuntime {
|
||||
|
||||
canStop(taskId: string): boolean {
|
||||
const task = this.tasks.get(taskId);
|
||||
return task?.announced === true && !task.ignored && !task.stopping && !isTerminal(task.state);
|
||||
return (
|
||||
task?.announced === true &&
|
||||
!task.monitor &&
|
||||
!task.ignored &&
|
||||
!task.stopping &&
|
||||
!isTerminal(task.state)
|
||||
);
|
||||
}
|
||||
|
||||
claimStop(taskId: string): boolean {
|
||||
@@ -575,6 +584,7 @@ export class AsyncTaskRuntime {
|
||||
taskType: "task",
|
||||
description: "Background task",
|
||||
showInTranscript: true,
|
||||
monitor: false,
|
||||
announced: false,
|
||||
held: false,
|
||||
deferred: [],
|
||||
@@ -595,6 +605,7 @@ export class AsyncTaskRuntime {
|
||||
task.startedObserved = true;
|
||||
const rawTaskType = field(message, "taskType", "task_type");
|
||||
if (rawTaskType !== undefined) task.taskType = friendlyTaskType(rawTaskType);
|
||||
if (rawTaskType === "local_monitor") task.monitor = true;
|
||||
const description = nonBlankString(message.description);
|
||||
if (description) task.description = description;
|
||||
else if (task.description === "Background task")
|
||||
@@ -652,6 +663,7 @@ export class AsyncTaskRuntime {
|
||||
private mergeLevel(task: AsyncTask, level: BackgroundTaskLevel): void {
|
||||
const rawTaskType = field(level, "taskType", "task_type");
|
||||
if (rawTaskType !== undefined) task.taskType = friendlyTaskType(rawTaskType);
|
||||
if (rawTaskType === "local_monitor") task.monitor = true;
|
||||
const description = nonBlankString(level.description);
|
||||
if (description) {
|
||||
task.description = description;
|
||||
@@ -676,25 +688,29 @@ export class AsyncTaskRuntime {
|
||||
* ends first, or when the prompt result ends the model turn
|
||||
* ({@link releaseHeld}). No guess by the command text binds a task.
|
||||
*
|
||||
* A task that a `Monitor` tool call started is ignored: Monitor streams its
|
||||
* output to the model only, so the task has nothing for the client. The
|
||||
* tool_use streams before the tool runs, so the tool name is known when the
|
||||
* spawn has the tool call id.
|
||||
* A task that a `Monitor` tool call started is published as a monitor. The
|
||||
* SDK reports it as `local_bash`, so the adapter names it a monitor instead of
|
||||
* a shell. It has no transcript card because Monitor streams its output to
|
||||
* the model only, and no Stop because stopping it only ends the agent's wait
|
||||
* (the agent's own TaskStop still works). The tool_use streams before the
|
||||
* tool runs, so the tool name is known when the spawn has the tool call id.
|
||||
*/
|
||||
private async announce(
|
||||
task: AsyncTask,
|
||||
options: { withoutToolCall?: boolean } = {},
|
||||
): Promise<void> {
|
||||
if (task.announced || task.ignored) return;
|
||||
const toolName = task.toolCallId ? this.options.toolNameOf?.(task.toolCallId) : undefined;
|
||||
if (toolName !== undefined && HIDDEN_TASK_TOOLS.has(toolName)) {
|
||||
this.ignore(task);
|
||||
return;
|
||||
}
|
||||
if (!task.toolCallId && !options.withoutToolCall && !isTerminal(task.state)) {
|
||||
task.held = true;
|
||||
return;
|
||||
}
|
||||
if (task.toolCallId && this.options.toolNameOf?.(task.toolCallId) === "Monitor") {
|
||||
task.monitor = true;
|
||||
}
|
||||
if (task.monitor) {
|
||||
task.taskType = "monitor";
|
||||
task.showInTranscript = false;
|
||||
}
|
||||
if (task.toolCallId) task.route ??= this.options.routeOf?.(task.toolCallId);
|
||||
await this.send(task, {
|
||||
sessionUpdate: "async_task_spawned",
|
||||
@@ -703,7 +719,7 @@ export class AsyncTaskRuntime {
|
||||
taskType: task.taskType,
|
||||
description: task.description,
|
||||
showInTranscript: task.showInTranscript,
|
||||
canStop: true,
|
||||
canStop: !task.monitor,
|
||||
...(task.outputFilePath ? { outputFilePath: task.outputFilePath } : {}),
|
||||
...(task.toolCallId ? { toolCallId: task.toolCallId } : {}),
|
||||
});
|
||||
@@ -1051,13 +1067,6 @@ function isBackgroundTask(isBackgrounded: unknown, taskType: unknown): boolean {
|
||||
return taskType !== "local_bash" && taskType !== "local_agent";
|
||||
}
|
||||
|
||||
/** The tools whose async tasks the client never sees. */
|
||||
const HIDDEN_TASK_TOOLS = new Set(["Monitor"]);
|
||||
|
||||
function isMonitorTask(message: AsyncTaskStarted): boolean {
|
||||
return field(message, "taskType", "task_type") === "local_monitor";
|
||||
}
|
||||
|
||||
function isSubagentTask(message: AsyncTaskStarted): boolean {
|
||||
return (
|
||||
field(message, "subagentType", "subagent_type") !== undefined ||
|
||||
|
||||
@@ -2980,7 +2980,16 @@ describe("task notification replay", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("sends nothing for a task that a Monitor tool call started", async () => {
|
||||
/**
|
||||
* Scenario:
|
||||
* 1. A replayed transcript has a Monitor tool call that started a background task.
|
||||
* 2. The task notification completes it.
|
||||
* Expected:
|
||||
* - The task spawn is a monitor with no transcript card and no Stop.
|
||||
* - The task then reaches the completed state.
|
||||
* - The Monitor tool call itself stays in the transcript.
|
||||
*/
|
||||
it("replays a task that a Monitor tool call started as a monitor", async () => {
|
||||
const monitorLaunch = record({
|
||||
...bashLaunch[1],
|
||||
message: {
|
||||
@@ -3002,7 +3011,18 @@ describe("task notification replay", () => {
|
||||
notification("completed"),
|
||||
]);
|
||||
|
||||
expect(asyncTaskUpdates(updates)).toEqual([]);
|
||||
const taskUpdates = asyncTaskUpdates(updates);
|
||||
expect(taskUpdates[0]).toMatchObject({
|
||||
sessionUpdate: "async_task_spawned",
|
||||
taskType: "monitor",
|
||||
showInTranscript: false,
|
||||
canStop: false,
|
||||
toolCallId: "toolu_bash",
|
||||
});
|
||||
expect(taskUpdates.at(-1)).toMatchObject({
|
||||
sessionUpdate: "async_task_state_update",
|
||||
state: "completed",
|
||||
});
|
||||
// The Monitor tool call itself stays in the transcript.
|
||||
expect(
|
||||
updates.some(
|
||||
@@ -9731,7 +9751,18 @@ describe("subagent permission attribution (issue #851)", () => {
|
||||
expect(backgrounded("child-cat")).toBe(false);
|
||||
});
|
||||
|
||||
it("hides the async task of a Monitor tool call and keeps the tool call", async () => {
|
||||
/**
|
||||
* Scenario:
|
||||
* 1. The model calls Monitor twice; the SDK reports both tasks as `local_bash`.
|
||||
* 2. The first task has its tool call id at start, the second only in a later progress.
|
||||
* 3. The first task completes; the client asks to stop the second.
|
||||
* Expected:
|
||||
* - Both tasks are spawned as monitors with no transcript card and no Stop.
|
||||
* - The first task reaches the completed state.
|
||||
* - The stop request returns `stopped: false`.
|
||||
* - Both Monitor tool calls stay in the transcript.
|
||||
*/
|
||||
it("publishes the async task of a Monitor tool call as a monitor and keeps the tool call", async () => {
|
||||
const updates: AcpSessionNotification[] = [];
|
||||
const agent = new ClaudeAcpAgent(
|
||||
{
|
||||
@@ -9835,9 +9866,25 @@ describe("subagent permission attribution (issue #851)", () => {
|
||||
|
||||
await agent.prompt({ sessionId: "test-session", prompt: [{ type: "text", text: "go" }] });
|
||||
|
||||
expect(updates.filter(({ update }) => update.sessionUpdate.startsWith("async_task_"))).toEqual(
|
||||
[],
|
||||
);
|
||||
const taskUpdates = updates
|
||||
.map(({ update }) => update)
|
||||
.filter((update) => update.sessionUpdate.startsWith("async_task_"));
|
||||
const spawns = taskUpdates.filter((update) => update.sessionUpdate === "async_task_spawned");
|
||||
expect(spawns.map((update: any) => [update.asyncTaskId, update.toolCallId])).toEqual([
|
||||
["mon-a", "monitor-a"],
|
||||
["mon-b", "monitor-b"],
|
||||
]);
|
||||
for (const spawn of spawns) {
|
||||
expect(spawn).toMatchObject({ taskType: "monitor", showInTranscript: false, canStop: false });
|
||||
}
|
||||
expect(
|
||||
taskUpdates.some(
|
||||
(update: any) =>
|
||||
update.sessionUpdate === "async_task_state_update" &&
|
||||
update.asyncTaskId === "mon-a" &&
|
||||
update.state === "completed",
|
||||
),
|
||||
).toBe(true);
|
||||
await expect(
|
||||
agent.stopAsyncTask({ sessionId: "test-session", asyncTaskId: "mon-b" }),
|
||||
).resolves.toEqual({ stopped: false });
|
||||
@@ -10020,6 +10067,15 @@ describe("subagent permission attribution (issue #851)", () => {
|
||||
expect(bashUpdate?._meta ?? {}).not.toHaveProperty("jetbrains");
|
||||
});
|
||||
|
||||
/**
|
||||
* Scenario:
|
||||
* 1. A subagent starts Bash tasks and a Monitor task; the root session starts one Bash task.
|
||||
* 2. The client stops a Bash task and the Monitor task.
|
||||
* Expected:
|
||||
* - Subagent tasks, including the monitor, go to the subagent session; the root task stays in the root.
|
||||
* - The monitor is spawned with no transcript card and no Stop.
|
||||
* - Only the Bash task is stopped; the Monitor stop returns `stopped: false`.
|
||||
*/
|
||||
it("sends the background tasks of a subagent to its session and keeps a root task in the root", async () => {
|
||||
const updates: AcpSessionNotification[] = [];
|
||||
const agent = new ClaudeAcpAgent(
|
||||
@@ -10155,7 +10211,7 @@ describe("subagent permission attribution (issue #851)", () => {
|
||||
await expect(
|
||||
agent.stopAsyncTask({ sessionId: "test-session", asyncTaskId: "watch-child" }),
|
||||
).resolves.toEqual({ stopped: true });
|
||||
// The client never sees a Monitor task, so it cannot stop it.
|
||||
// A Monitor task is published with canStop false, so the stop request is refused.
|
||||
await expect(
|
||||
agent.stopAsyncTask({ sessionId: "test-session", asyncTaskId: "monitor-child" }),
|
||||
).resolves.toEqual({ stopped: false });
|
||||
@@ -10172,6 +10228,7 @@ describe("subagent permission attribution (issue #851)", () => {
|
||||
expect(lifecycle).toEqual([
|
||||
["agent-1", "async_task_spawned", "shell-child", undefined],
|
||||
["agent-1", "async_task_spawned", "watch-child", undefined],
|
||||
["agent-1", "async_task_spawned", "monitor-child", undefined],
|
||||
["agent-1", "async_task_spawned", "shell-late", undefined],
|
||||
["test-session", "async_task_spawned", "shell-root", undefined],
|
||||
["agent-1", "async_task_state_update", "shell-child", "completed"],
|
||||
@@ -10181,6 +10238,15 @@ describe("subagent permission attribution (issue #851)", () => {
|
||||
["agent-1", "async_task_spawned", "shell-held", undefined],
|
||||
["agent-1", "async_task_state_update", "shell-held", "completed"],
|
||||
]);
|
||||
const monitorSpawn = updates.find(
|
||||
({ update }) =>
|
||||
update.sessionUpdate === "async_task_spawned" && update.asyncTaskId === "monitor-child",
|
||||
)?.update;
|
||||
expect(monitorSpawn).toMatchObject({
|
||||
taskType: "monitor",
|
||||
showInTranscript: false,
|
||||
canStop: false,
|
||||
});
|
||||
// The stop acknowledgement goes to the transcript that holds the task.
|
||||
const stopAcknowledgement = updates.find(
|
||||
({ update }) =>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"rawInput":{"command":"ls -la","description":"List files"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_bash"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"terminalId":"toolu_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{"command":"ls -la","description":"List files"},"status":"pending","title":"ls -la","toolCallId":"toolu_bash"},"type":"tool_call"},"title":"ls -la"}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"terminalId":"toolu_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{"command":"ls -la","description":"List files"},"title":"ls -la","toolCallId":"toolu_bash"},"type":"tool_call"},"title":"ls -la"}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"output":{"data":"YS50cwpiLnRz"},"sessionUpdate":"terminal_update","terminalId":"toolu_bash"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"exitStatus":{"exitCode":0},"sessionUpdate":"terminal_update","terminalId":"toolu_bash"}}}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"rawInput":{"file_path":"<cwd>/src/app.ts","new_string":"value = 2","old_string":"value = 1"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[{"changes":[{"fileType":"text","operation":"modify","path":"<cwd>/src/app.ts"}],"patch":{"format":"git_patch","text":"diff --git <cwd>/src/app.ts <cwd>/src/app.ts\n--- <cwd>/src/app.ts\n+++ <cwd>/src/app.ts\n@@ -1 +1 @@\n-const value = 1;\n+const value = 2;\n"},"type":"diff"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"changes":[{"fileType":"text","operation":"modify","path":"<cwd>/src/app.ts"}],"patch":{"format":"git_patch","text":"diff --git <cwd>/src/app.ts <cwd>/src/app.ts\n--- <cwd>/src/app.ts\n+++ <cwd>/src/app.ts\n@@ -1 +1 @@\n-const value = 1;\n+const value = 2;\n"},"type":"diff"}],"kind":"edit","locations":[{"path":"<cwd>/src/app.ts"}],"name":"Edit","rawInput":{"file_path":"<cwd>/src/app.ts","new_string":"value = 2","old_string":"value = 1"},"status":"pending","title":"Edit src/app.ts","toolCallId":"toolu_edit"},"type":"tool_call"},"title":"Edit src/app.ts"}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"changes":[{"fileType":"text","operation":"modify","path":"<cwd>/src/app.ts"}],"patch":{"format":"git_patch","text":"diff --git <cwd>/src/app.ts <cwd>/src/app.ts\n--- <cwd>/src/app.ts\n+++ <cwd>/src/app.ts\n@@ -1 +1 @@\n-const value = 1;\n+const value = 2;\n"},"type":"diff"}],"kind":"edit","locations":[{"path":"<cwd>/src/app.ts"}],"name":"Edit","rawInput":{"file_path":"<cwd>/src/app.ts","new_string":"value = 2","old_string":"value = 1"},"title":"Edit src/app.ts","toolCallId":"toolu_edit"},"type":"tool_call"},"title":"Edit src/app.ts"}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[{"content":{"text":"```\nThe user doesn't want to proceed with this tool use. The tool use was rejected.\n```","type":"text"},"type":"content"}],"rawOutput":"The user doesn't want to proceed with this tool use. The tool use was rejected.","sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_edit"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"rawInput":{"file_path":"<cwd>/src/app.ts","new_string":"const value = 2;","old_string":"const value = 1;"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[{"changes":[{"fileType":"text","operation":"modify","path":"<cwd>/src/app.ts"}],"patch":{"format":"git_patch","text":"diff --git <cwd>/src/app.ts <cwd>/src/app.ts\n--- <cwd>/src/app.ts\n+++ <cwd>/src/app.ts\n@@ -1,3 +1,3 @@\n line 1\n-const value = 1;\n+const value = 2;\n line 3\n"},"type":"diff"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"changes":[{"fileType":"text","operation":"modify","path":"<cwd>/src/app.ts"}],"patch":{"format":"git_patch","text":"diff --git <cwd>/src/app.ts <cwd>/src/app.ts\n--- <cwd>/src/app.ts\n+++ <cwd>/src/app.ts\n@@ -1,3 +1,3 @@\n line 1\n-const value = 1;\n+const value = 2;\n line 3\n"},"type":"diff"}],"kind":"edit","locations":[{"path":"<cwd>/src/app.ts"}],"name":"Edit","rawInput":{"file_path":"<cwd>/src/app.ts","new_string":"const value = 2;","old_string":"const value = 1;"},"status":"pending","title":"Edit src/app.ts","toolCallId":"toolu_edit"},"type":"tool_call"},"title":"Edit src/app.ts"}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"changes":[{"fileType":"text","operation":"modify","path":"<cwd>/src/app.ts"}],"patch":{"format":"git_patch","text":"diff --git <cwd>/src/app.ts <cwd>/src/app.ts\n--- <cwd>/src/app.ts\n+++ <cwd>/src/app.ts\n@@ -1,3 +1,3 @@\n line 1\n-const value = 1;\n+const value = 2;\n line 3\n"},"type":"diff"}],"kind":"edit","locations":[{"path":"<cwd>/src/app.ts"}],"name":"Edit","rawInput":{"file_path":"<cwd>/src/app.ts","new_string":"const value = 2;","old_string":"const value = 1;"},"title":"Edit src/app.ts","toolCallId":"toolu_edit"},"type":"tool_call"},"title":"Edit src/app.ts"}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"rawOutput":"The file <cwd>/src/app.ts has been updated successfully.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_edit"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"locations":[{"line":1,"path":"<cwd>/src/app.ts"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_edit"}}}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[{"content":{"text":"# Plan\n1. Do it","type":"text"},"type":"content"}],"rawInput":{"plan":"# Plan\n1. Do it"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_plan"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes, manually approve edits","optionId":"exit-plan-default"},{"kind":"allow_always","name":"Yes, clear context (0% used) and use auto mode","optionId":"exit-plan-clear-auto"},{"kind":"allow_always","name":"Yes, and use auto mode","optionId":"exit-plan-auto"},{"kind":"allow_always","name":"Yes, and bypass permissions","optionId":"exit-plan-bypass"},{"kind":"reject_once","name":"No, keep planning","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"content":{"text":"# Plan\n1. Do it","type":"text"},"type":"content"}],"kind":"switch_mode","name":"ExitPlanMode","rawInput":{"plan":"# Plan\n1. Do it"},"status":"pending","title":"Approve Plan","toolCallId":"toolu_plan"},"type":"tool_call"},"title":"Ready to code?"}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes, manually approve edits","optionId":"exit-plan-default"},{"kind":"allow_always","name":"Yes, clear context (0% used) and use auto mode","optionId":"exit-plan-clear-auto"},{"kind":"allow_always","name":"Yes, and use auto mode","optionId":"exit-plan-auto"},{"kind":"allow_always","name":"Yes, and bypass permissions","optionId":"exit-plan-bypass"},{"kind":"reject_once","name":"No, keep planning","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"content":{"text":"# Plan\n1. Do it","type":"text"},"type":"content"}],"kind":"switch_mode","name":"ExitPlanMode","rawInput":{"plan":"# Plan\n1. Do it"},"title":"Approve Plan","toolCallId":"toolu_plan"},"type":"tool_call"},"title":"Ready to code?"}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"configOptions":[{"category":"mode","configId":"mode","currentValue":"default","description":"Session permission mode","name":"Mode","options":[{"description":"Always ask before making changes","name":"Manual","value":"default"},{"description":"Automatically accept all file edits","name":"Accept edits","value":"acceptEdits"},{"description":"Create a plan before making changes","name":"Plan","value":"plan"},{"description":"Claude handles permission decisions","name":"Auto","value":"auto"},{"description":"Accepts all permissions","name":"Bypass permissions","value":"bypassPermissions"}],"type":"select"},{"category":"model","configId":"model","currentValue":"claude-sonnet-4-6","description":"AI model to use","name":"Model","options":[{"description":"Fast","name":"Claude Sonnet 4.6","value":"claude-sonnet-4-6"}],"type":"select"}],"sessionUpdate":"config_option_update"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"rawOutput":"User has approved your plan. You can now start coding.\n\n## Approved Plan:\n# Plan\n1. Do it","sessionUpdate":"tool_call_update","status":"completed","title":"Exited Plan Mode","toolCallId":"toolu_plan"}}}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[{"content":{"text":"# Plan\n1. Do it","type":"text"},"type":"content"}],"rawInput":{"plan":"# Plan\n1. Do it"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_plan"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes, manually approve edits","optionId":"exit-plan-default"},{"kind":"allow_always","name":"Yes, clear context (0% used) and use auto mode","optionId":"exit-plan-clear-auto"},{"kind":"allow_always","name":"Yes, and use auto mode","optionId":"exit-plan-auto"},{"kind":"allow_always","name":"Yes, and bypass permissions","optionId":"exit-plan-bypass"},{"kind":"reject_once","name":"No, keep planning","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"content":{"text":"# Plan\n1. Do it","type":"text"},"type":"content"}],"kind":"switch_mode","name":"ExitPlanMode","rawInput":{"plan":"# Plan\n1. Do it"},"status":"pending","title":"Approve Plan","toolCallId":"toolu_plan"},"type":"tool_call"},"title":"Ready to code?"}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes, manually approve edits","optionId":"exit-plan-default"},{"kind":"allow_always","name":"Yes, clear context (0% used) and use auto mode","optionId":"exit-plan-clear-auto"},{"kind":"allow_always","name":"Yes, and use auto mode","optionId":"exit-plan-auto"},{"kind":"allow_always","name":"Yes, and bypass permissions","optionId":"exit-plan-bypass"},{"kind":"reject_once","name":"No, keep planning","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"content":{"text":"# Plan\n1. Do it","type":"text"},"type":"content"}],"kind":"switch_mode","name":"ExitPlanMode","rawInput":{"plan":"# Plan\n1. Do it"},"title":"Approve Plan","toolCallId":"toolu_plan"},"type":"tool_call"},"title":"Ready to code?"}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[{"content":{"text":"```\n```\nThe user doesn't want to proceed with this tool use.\n```\n```","type":"text"},"type":"content"}],"rawOutput":"The user doesn't want to proceed with this tool use.","sessionUpdate":"tool_call_update","status":"failed","toolCallId":"toolu_plan"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"rawInput":{"q":"acp"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_mcp"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"_meta":{"claudeCode":{"mcpServer":{"name":"docs","source":"project"}}},"content":[],"kind":"other","name":"mcp__docs__search","rawInput":{"q":"acp"},"status":"pending","title":"mcp__docs__search","toolCallId":"toolu_mcp"},"type":"tool_call"},"title":"mcp__docs__search"}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"_meta":{"claudeCode":{"mcpServer":{"name":"docs","source":"project"}}},"content":[],"kind":"other","name":"mcp__docs__search","rawInput":{"q":"acp"},"title":"mcp__docs__search","toolCallId":"toolu_mcp"},"type":"tool_call"},"title":"mcp__docs__search"}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[{"content":{"text":"Found 2 documents.","type":"text"},"type":"content"}],"rawOutput":[{"text":"Found 2 documents.","type":"text"}],"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_mcp"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[],"kind":"other","name":"SandboxNetworkAccess","rawInput":{"host":"example.com"},"sessionUpdate":"tool_call_update","status":"pending","title":"SandboxNetworkAccess","toolCallId":"toolu_net"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"description":"Reason: Sandbox blocks network","options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"content":{"text":"```json\n{\n \"host\": \"example.com\"\n}\n```","type":"text"},"type":"content"}],"kind":"other","name":"SandboxNetworkAccess","rawInput":{"host":"example.com"},"status":"pending","title":"example.com","toolCallId":"toolu_net"},"type":"tool_call"},"title":"example.com"}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"description":"Reason: Sandbox blocks network","options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"content":{"text":"```json\n{\n \"host\": \"example.com\"\n}\n```","type":"text"},"type":"content"}],"kind":"other","name":"SandboxNetworkAccess","rawInput":{"host":"example.com"},"title":"example.com","toolCallId":"toolu_net"},"type":"tool_call"},"title":"example.com"}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_net"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"quota":{"model_usage":[],"token_count":{"cachedInputTokens":0,"cachedWriteTokens":0,"inputTokens":0,"outputTokens":0,"reasoningOutputTokens":0,"totalTokens":0}}},"sessionUpdate":"state_update","state":"idle","stopReason":"end_turn","usage":{"cachedReadTokens":0,"cachedWriteTokens":0,"inputTokens":0,"outputTokens":0,"totalTokens":0}}}}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"rawInput":{"cell_id":"cell-1","edit_mode":"replace","new_source":"print('hi')","notebook_path":"<cwd>/n.ipynb"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_nb"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[],"kind":"other","name":"NotebookEdit","rawInput":{"cell_id":"cell-1","edit_mode":"replace","new_source":"print('hi')","notebook_path":"<cwd>/n.ipynb"},"status":"pending","title":"NotebookEdit","toolCallId":"toolu_nb"},"type":"tool_call"},"title":"NotebookEdit"}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[],"kind":"other","name":"NotebookEdit","rawInput":{"cell_id":"cell-1","edit_mode":"replace","new_source":"print('hi')","notebook_path":"<cwd>/n.ipynb"},"title":"NotebookEdit","toolCallId":"toolu_nb"},"type":"tool_call"},"title":"NotebookEdit"}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[{"content":{"text":"Updated cell cell-1 with print('hi')","type":"text"},"type":"content"}],"rawOutput":"Updated cell cell-1 with print('hi')","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_nb"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionId":"agent_n","sessionUpdate":"subagent_update","state":{"state":"requires_action"}}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"agent_n","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"agent_n","subject":{"toolCall":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native"}},"content":[{"terminalId":"toolu_native_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{"command":"make","description":"Build"},"status":"pending","title":"make","toolCallId":"toolu_native_bash"},"type":"tool_call"},"title":"make"}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"agent_n","subject":{"toolCall":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_native"}},"content":[{"terminalId":"toolu_native_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{"command":"make","description":"Build"},"title":"make","toolCallId":"toolu_native_bash"},"type":"tool_call"},"title":"make"}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionId":"agent_n","sessionUpdate":"subagent_update","state":{"state":"running"}}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"agent_n","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionId":"agent_1","sessionUpdate":"subagent_update","state":{"state":"requires_action"}}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"agent_1","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"agent_1","subject":{"toolCall":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task"}},"content":[{"terminalId":"toolu_sub_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{"command":"rg parser","description":"Search"},"status":"pending","title":"rg parser","toolCallId":"toolu_sub_bash"},"type":"tool_call"},"title":"rg parser"}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"agent_1","subject":{"toolCall":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task"}},"content":[{"terminalId":"toolu_sub_bash","type":"terminal"}],"kind":"execute","name":"Bash","rawInput":{"command":"rg parser","description":"Search"},"title":"rg parser","toolCallId":"toolu_sub_bash"},"type":"tool_call"},"title":"rg parser"}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionId":"agent_1","sessionUpdate":"subagent_update","state":{"state":"running"}}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"agent_1","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
@@ -37,7 +37,7 @@
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionId":"agent_1","sessionUpdate":"subagent_update","state":{"state":"requires_action"}}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"agent_1","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"agent_1","subject":{"toolCall":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task"}},"content":[],"kind":"edit","locations":[{"path":"<cwd>/x.ts"}],"name":"Edit","rawInput":{"file_path":"<cwd>/x.ts","new_string":"b","old_string":"a"},"status":"pending","title":"Edit x.ts","toolCallId":"toolu_sub_edit"},"type":"tool_call"},"title":"Edit x.ts"}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"agent_1","subject":{"toolCall":{"_meta":{"claudeCode":{"parentToolUseId":"toolu_task"}},"content":[],"kind":"edit","locations":[{"path":"<cwd>/x.ts"}],"name":"Edit","rawInput":{"file_path":"<cwd>/x.ts","new_string":"b","old_string":"a"},"title":"Edit x.ts","toolCallId":"toolu_sub_edit"},"type":"tool_call"},"title":"Edit x.ts"}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionId":"agent_1","sessionUpdate":"subagent_update","state":{"state":"running"}}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"agent_1","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"sessionUpdate":"usage_update","size":200000,"used":3}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[{"content":{"text":"Summarize the page","type":"text"},"type":"content"}],"rawInput":{"prompt":"Summarize the page","url":"https://example.com"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_fetch"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"allow_always","name":"Yes, and don't ask again for example.com","optionId":"allow-with-updates"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"content":{"text":"Summarize the page","type":"text"},"type":"content"}],"kind":"fetch","name":"WebFetch","rawInput":{"prompt":"Summarize the page","url":"https://example.com"},"status":"pending","title":"Fetch https://example.com","toolCallId":"toolu_fetch"},"type":"tool_call"},"title":"Fetch https://example.com"}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"allow_always","name":"Yes, and don't ask again for example.com","optionId":"allow-with-updates"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"content":{"text":"Summarize the page","type":"text"},"type":"content"}],"kind":"fetch","name":"WebFetch","rawInput":{"prompt":"Summarize the page","url":"https://example.com"},"title":"Fetch https://example.com","toolCallId":"toolu_fetch"},"type":"tool_call"},"title":"Fetch https://example.com"}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[{"content":{"text":"The page is an example.","type":"text"},"type":"content"}],"rawOutput":"The page is an example.","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_fetch"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[],"kind":"fetch","name":"WebSearch","rawInput":{},"sessionUpdate":"tool_call_update","status":"pending","title":"Web search","toolCallId":"toolu_search"}}}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"rawInput":{"content":"export const x = 1;\n","file_path":"<cwd>/new.ts"},"sessionUpdate":"tool_call_update","toolCallId":"toolu_write"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"content":[{"changes":[{"fileType":"text","operation":"add","path":"<cwd>/new.ts"}],"patch":{"format":"git_patch","text":"diff --git <cwd>/new.ts <cwd>/new.ts\nnew file mode 100644\n--- /dev/null\n+++ <cwd>/new.ts\n@@ -0,0 +1 @@\n+export const x = 1;\n"},"type":"diff"}],"sessionUpdate":"tool_call_update","toolCallId":"toolu_write"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"requires_action"}}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"changes":[{"fileType":"text","operation":"add","path":"<cwd>/new.ts"}],"patch":{"format":"git_patch","text":"diff --git <cwd>/new.ts <cwd>/new.ts\nnew file mode 100644\n--- /dev/null\n+++ <cwd>/new.ts\n@@ -0,0 +1 @@\n+export const x = 1;\n"},"type":"diff"}],"kind":"edit","locations":[{"path":"<cwd>/new.ts"}],"name":"Write","rawInput":{"content":"export const x = 1;\n","file_path":"<cwd>/new.ts"},"status":"pending","title":"Write new.ts","toolCallId":"toolu_write"},"type":"tool_call"},"title":"Write new.ts"}}
|
||||
{"kind":"request","method":"session/request_permission","payload":{"options":[{"kind":"allow_once","name":"Yes","optionId":"allow-once"},{"kind":"reject_once","name":"No","optionId":"reject"}],"sessionId":"<session>","subject":{"toolCall":{"content":[{"changes":[{"fileType":"text","operation":"add","path":"<cwd>/new.ts"}],"patch":{"format":"git_patch","text":"diff --git <cwd>/new.ts <cwd>/new.ts\nnew file mode 100644\n--- /dev/null\n+++ <cwd>/new.ts\n@@ -0,0 +1 @@\n+export const x = 1;\n"},"type":"diff"}],"kind":"edit","locations":[{"path":"<cwd>/new.ts"}],"name":"Write","rawInput":{"content":"export const x = 1;\n","file_path":"<cwd>/new.ts"},"title":"Write new.ts","toolCallId":"toolu_write"},"type":"tool_call"},"title":"Write new.ts"}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"sessionUpdate":"state_update","state":"running"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"rawOutput":"File created successfully at: <cwd>/new.ts","sessionUpdate":"tool_call_update","status":"completed","toolCallId":"toolu_write"}}}
|
||||
{"kind":"notification","method":"session/update","payload":{"sessionId":"<session>","update":{"_meta":{"_claude/model":"claude-sonnet-4-6"},"cost":{"amount":0,"currency":"USD"},"sessionUpdate":"usage_update","size":200000,"used":2}}}
|
||||
|
||||
@@ -1221,10 +1221,28 @@ describe("AsyncTaskRuntime", () => {
|
||||
return { runtime, published };
|
||||
};
|
||||
|
||||
it("never announces a task that a Monitor tool call started", async () => {
|
||||
const updateKinds = (published: AcpSessionNotification[]) =>
|
||||
published.map(({ update }) => update.sessionUpdate);
|
||||
const MONITOR_SPAWN = {
|
||||
sessionUpdate: "async_task_spawned",
|
||||
taskType: "monitor",
|
||||
showInTranscript: false,
|
||||
canStop: false,
|
||||
};
|
||||
|
||||
/**
|
||||
* Scenario:
|
||||
* 1. The SDK starts a `local_bash` task for a Monitor tool call.
|
||||
* 2. The task reports progress, then its notification completes it.
|
||||
* 3. The client asks to stop the task.
|
||||
* Expected:
|
||||
* - The spawn is a monitor with no transcript card and no Stop.
|
||||
* - Progress and the completed state follow.
|
||||
* - `canStop` and `claimStop` are false.
|
||||
*/
|
||||
it("publishes a task that a Monitor tool call started as a monitor", async () => {
|
||||
const { runtime, published } = monitorRuntime();
|
||||
|
||||
// The SDK reports a Monitor task as a background shell.
|
||||
await runtime.taskStarted({
|
||||
task_id: "monitor",
|
||||
task_type: "local_bash",
|
||||
@@ -1233,22 +1251,38 @@ describe("AsyncTaskRuntime", () => {
|
||||
tool_use_id: "monitor-tool",
|
||||
});
|
||||
await runtime.taskProgress({ task_id: "monitor", summary: "First line" });
|
||||
await runtime.taskUpdated("monitor", { status: "paused" });
|
||||
await runtime.backgroundTasksChanged([{ task_id: "monitor", task_type: "local_bash" }]);
|
||||
expect(runtime.canStop("monitor")).toBe(false);
|
||||
expect(runtime.claimStop("monitor")).toBe(false);
|
||||
await runtime.taskStopped("monitor");
|
||||
const stoppable = runtime.canStop("monitor");
|
||||
const claimed = runtime.claimStop("monitor");
|
||||
await runtime.taskNotification({
|
||||
task_id: "monitor",
|
||||
status: "completed",
|
||||
tool_use_id: "monitor-tool",
|
||||
});
|
||||
await runtime.finishAll("stopped");
|
||||
|
||||
expect(published).toEqual([]);
|
||||
expect(published[0]?.update).toMatchObject({
|
||||
...MONITOR_SPAWN,
|
||||
asyncTaskId: "monitor",
|
||||
toolCallId: "monitor-tool",
|
||||
});
|
||||
expect(updateKinds(published)).toEqual([
|
||||
"async_task_spawned",
|
||||
"async_task_progress",
|
||||
"async_task_state_update",
|
||||
]);
|
||||
expect(published[2]?.update).toMatchObject({ state: "completed" });
|
||||
expect(stoppable).toBe(false);
|
||||
expect(claimed).toBe(false);
|
||||
});
|
||||
|
||||
it("never announces a held task whose tool call id names a Monitor", async () => {
|
||||
/**
|
||||
* Scenario:
|
||||
* 1. A task starts without a tool call id and is held.
|
||||
* 2. A later progress carries the Monitor tool call id.
|
||||
* Expected:
|
||||
* - The task is spawned as a monitor once the id arrives, not before.
|
||||
* - It is not stoppable.
|
||||
*/
|
||||
it("spawns a held task as a monitor when its tool call id names a Monitor", async () => {
|
||||
const { runtime, published } = monitorRuntime();
|
||||
|
||||
await runtime.taskStarted({
|
||||
@@ -1257,18 +1291,26 @@ describe("AsyncTaskRuntime", () => {
|
||||
description: "Watch the logs",
|
||||
});
|
||||
await runtime.taskProgress({ task_id: "monitor", summary: "First line" });
|
||||
const spawnedBeforeId = published.length;
|
||||
await runtime.taskProgress({
|
||||
task_id: "monitor",
|
||||
summary: "Second line",
|
||||
tool_use_id: "monitor-tool",
|
||||
});
|
||||
await runtime.releaseHeld();
|
||||
await runtime.taskNotification({ task_id: "monitor", status: "stopped" });
|
||||
|
||||
expect(published).toEqual([]);
|
||||
expect(spawnedBeforeId).toBe(0);
|
||||
expect(published[0]?.update).toMatchObject({ ...MONITOR_SPAWN, toolCallId: "monitor-tool" });
|
||||
expect(runtime.canStop("monitor")).toBe(false);
|
||||
});
|
||||
|
||||
it("never announces a held task that a Monitor ends", async () => {
|
||||
/**
|
||||
* Scenario:
|
||||
* 1. A task starts without a tool call id and is held.
|
||||
* 2. A notification with the Monitor tool call id completes it.
|
||||
* Expected:
|
||||
* - The task is spawned as a monitor, then reaches the completed state.
|
||||
*/
|
||||
it("spawns a held task that a Monitor ends as a monitor", async () => {
|
||||
const { runtime, published } = monitorRuntime();
|
||||
|
||||
await runtime.taskStarted({ task_id: "monitor", task_type: "local_workflow" });
|
||||
@@ -1278,23 +1320,47 @@ describe("AsyncTaskRuntime", () => {
|
||||
tool_use_id: "monitor-tool",
|
||||
});
|
||||
|
||||
expect(published).toEqual([]);
|
||||
expect(updateKinds(published)).toEqual(["async_task_spawned", "async_task_state_update"]);
|
||||
expect(published[0]?.update).toMatchObject(MONITOR_SPAWN);
|
||||
expect(published[1]?.update).toMatchObject({ state: "completed" });
|
||||
});
|
||||
|
||||
it("ignores a local_monitor task without a tool call", async () => {
|
||||
/**
|
||||
* Scenario:
|
||||
* 1. The SDK starts a `local_monitor` task for a Bash tool call.
|
||||
* 2. The SDK reports another `local_monitor` task only in the task level.
|
||||
* 3. The turn ends (`releaseHeld`), which spawns the level-only task without a tool call.
|
||||
* Expected:
|
||||
* - Both tasks are spawned as monitors and neither is stoppable.
|
||||
*/
|
||||
it("spawns a local_monitor task as a monitor", async () => {
|
||||
const { runtime, published } = monitorRuntime();
|
||||
|
||||
await runtime.backgroundTasksChanged([{ task_id: "level", task_type: "local_monitor" }]);
|
||||
await runtime.taskStarted({ task_id: "level", task_type: "local_monitor" });
|
||||
await runtime.taskStarted({ task_id: "started", task_type: "local_monitor" });
|
||||
await runtime.taskProgress({ task_id: "started", summary: "line" });
|
||||
await runtime.taskStarted({
|
||||
task_id: "started",
|
||||
task_type: "local_monitor",
|
||||
tool_use_id: "bash-tool",
|
||||
});
|
||||
await runtime.backgroundTasksChanged([
|
||||
{ task_id: "started", task_type: "local_monitor" },
|
||||
{ task_id: "level", task_type: "local_monitor" },
|
||||
]);
|
||||
await runtime.releaseHeld();
|
||||
await runtime.taskNotification({ task_id: "started", status: "completed" });
|
||||
|
||||
expect(published).toEqual([]);
|
||||
const spawns = published.map(({ update }) => update);
|
||||
expect(spawns).toHaveLength(2);
|
||||
expect(spawns[0]).toMatchObject({ ...MONITOR_SPAWN, asyncTaskId: "started" });
|
||||
expect(spawns[1]).toMatchObject({ ...MONITOR_SPAWN, asyncTaskId: "level" });
|
||||
expect(runtime.canStop("started")).toBe(false);
|
||||
expect(runtime.canStop("level")).toBe(false);
|
||||
});
|
||||
|
||||
/**
|
||||
* Scenario:
|
||||
* 1. The SDK starts a background `local_bash` task for a Bash tool call.
|
||||
* Expected:
|
||||
* - The spawn is a shell that stays in the transcript and can be stopped.
|
||||
*/
|
||||
it("still announces a task of another tool", async () => {
|
||||
const { runtime, published } = monitorRuntime();
|
||||
|
||||
@@ -1307,6 +1373,11 @@ describe("AsyncTaskRuntime", () => {
|
||||
});
|
||||
|
||||
expect(published.map(({ update }) => update.sessionUpdate)).toEqual(["async_task_spawned"]);
|
||||
expect(published[0]?.update).toMatchObject({
|
||||
taskType: "shell",
|
||||
showInTranscript: true,
|
||||
canStop: true,
|
||||
});
|
||||
expect(runtime.canStop("shell")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -319,13 +319,16 @@ export class AcpToolCallRenderer {
|
||||
const facts = this.facts(toolUse, options.cwd);
|
||||
if (!this.capabilities.air.client) {
|
||||
// The upstream shape: the whole tool call again. A v2 client also gets
|
||||
// the exact preview patch, which the tool call does not show.
|
||||
// the exact preview patch, which the tool call does not show, but not the
|
||||
// status: its subject is an update of the call, which was emitted before
|
||||
// the request (`ensureToolCallEmitted`), and a `pending` there would move
|
||||
// a call that already runs back.
|
||||
const content = options.previewContent ?? this.toolUseContent(toolUse.id, facts);
|
||||
const locations = [...(facts.locations ?? []), ...(options.extraLocations ?? [])];
|
||||
return {
|
||||
toolCallId: toolUse.id,
|
||||
name: toolUse.name,
|
||||
status: "pending",
|
||||
...(this.capabilities.v2 ? {} : { status: "pending" as const }),
|
||||
rawInput: toolUse.input,
|
||||
title: options.title ?? facts.title,
|
||||
kind: facts.kind,
|
||||
|
||||
Reference in New Issue
Block a user