Plannning

Co-authored-by: Richard Feldman <oss@rtfeldman.com>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
This commit is contained in:
Conrad Irwin
2025-08-27 12:01:50 -06:00
parent 581e9f8785
commit 554c6c3232
3 changed files with 244 additions and 12 deletions

View File

@@ -34,7 +34,7 @@ import { ContentBlock } from "@zed-industries/agent-client-protocol";
import { SessionNotification } from "@zed-industries/agent-client-protocol";
import { createMcpServer } from "./mcp-server.js";
import { AddressInfo } from "node:net";
import { toolContent, toolLabel, toolKind } from "./tools.js";
import { toolContent, toolLabel, toolKind, planEntries } from "./tools.js";
// Implement the ACP Agent interface
export class ClaudeAcpAgent implements Agent {
@@ -225,7 +225,7 @@ function promptToClaude(prompt: PromptRequest): SDKUserMessage {
* Convert an SDKAssistantMessage (Claude) to a SessionNotification (ACP).
* Only handles text, image, and thinking chunks for now.
*/
function toAcpNotifications(
export function toAcpNotifications(
message: SDKAssistantMessage | SDKUserMessage,
sessionId: string,
): SessionNotification[] {
@@ -266,16 +266,100 @@ function toAcpNotifications(
};
break;
case "tool_use":
update = {
toolCallId: chunk.id,
title: toolLabel(chunk),
sessionUpdate: "tool_call",
kind: toolKind(chunk.name), // todo!()
rawInput: chunk.input,
status: "pending",
content: toolContent(chunk),
};
break;
// {
// "type": "assistant",
// "message": {
// "id": "msg_017eNosJgww7F5qD4a8BcAcx",
// "type": "message",
// "role": "assistant",
// "model": "claude-sonnet-4-20250514",
// "content": [
// {
// "type": "tool_use",
// "id": "toolu_01HaXZ4LfdchSeSR8ygt4zyq",
// "name": "TodoWrite",
// "input": {
// "todos": [
// {
// "content": "Analyze existing test coverage and identify gaps",
// "status": "in_progress",
// "activeForm": "Analyzing existing test coverage"
// },
// {
// "content": "Add comprehensive edge case tests",
// "status": "pending",
// "activeForm": "Adding comprehensive edge case tests"
// },
// {
// "content": "Add performance and timing tests",
// "status": "pending",
// "activeForm": "Adding performance and timing tests"
// },
// {
// "content": "Add error handling and panic behavior tests",
// "status": "pending",
// "activeForm": "Adding error handling tests"
// },
// {
// "content": "Add concurrent access and race condition tests",
// "status": "pending",
// "activeForm": "Adding concurrent access tests"
// },
// {
// "content": "Add tests for Each function with various data types",
// "status": "pending",
// "activeForm": "Adding Each function tests"
// },
// {
// "content": "Add benchmark tests for performance measurement",
// "status": "pending",
// "activeForm": "Adding benchmark tests"
// },
// {
// "content": "Improve test organization and helper functions",
// "status": "pending",
// "activeForm": "Improving test organization"
// }
// ]
// }
// }
// ],
// "stop_reason": null,
// "stop_sequence": null,
// "usage": {
// "input_tokens": 6,
// "cache_creation_input_tokens": 326,
// "cache_read_input_tokens": 17265,
// "cache_creation": {
// "ephemeral_5m_input_tokens": 326,
// "ephemeral_1h_input_tokens": 0
// },
// "output_tokens": 1,
// "service_tier": "standard"
// }
// },
// "parent_tool_use_id": null,
// "session_id": "d056596f-e328-41e9-badd-b07122ae5227",
// "uuid": "b7c3330c-de8f-4bba-ac53-68c7f76ffeb5"
// }
if (chunk.name == "TodoWrite") {
update = {
sessionUpdate: "plan",
entries: planEntries(chunk.input),
};
break;
} else {
update = {
toolCallId: chunk.id,
title: toolLabel(chunk),
sessionUpdate: "tool_call",
kind: toolKind(chunk.name), // todo!()
rawInput: chunk.input,
status: "pending",
content: toolContent(chunk),
};
break;
}
case "tool_result":
update = {

View File

@@ -15,6 +15,9 @@ import {
} from "@zed-industries/agent-client-protocol";
import { nodeToWebWritable, nodeToWebReadable } from "../utils.js";
import { toolContent, toolKind, toolLabel } from "../tools.js";
import { toAcpNotifications } from "../acp-agent.js";
import { UUID } from "crypto";
import { SDKAssistantMessage } from "@anthropic-ai/claude-code";
describe("ACP subprocess integration", () => {
let child: ReturnType<typeof spawn>;
@@ -96,4 +99,134 @@ describe("tool conversions", () => {
},
]);
});
it("should handle plan entries", () => {
const received: SDKAssistantMessage = {
type: "assistant",
message: {
id: "msg_017eNosJgww7F5qD4a8BcAcx",
type: "message",
role: "assistant",
model: "claude-sonnet-4-20250514",
content: [
{
type: "tool_use",
id: "toolu_01HaXZ4LfdchSeSR8ygt4zyq",
name: "TodoWrite",
input: {
todos: [
{
content: "Analyze existing test coverage and identify gaps",
status: "in_progress",
activeForm: "Analyzing existing test coverage",
},
{
content: "Add comprehensive edge case tests",
status: "pending",
activeForm: "Adding comprehensive edge case tests",
},
{
content: "Add performance and timing tests",
status: "pending",
activeForm: "Adding performance and timing tests",
},
{
content: "Add error handling and panic behavior tests",
status: "pending",
activeForm: "Adding error handling tests",
},
{
content: "Add concurrent access and race condition tests",
status: "pending",
activeForm: "Adding concurrent access tests",
},
{
content:
"Add tests for Each function with various data types",
status: "pending",
activeForm: "Adding Each function tests",
},
{
content: "Add benchmark tests for performance measurement",
status: "pending",
activeForm: "Adding benchmark tests",
},
{
content: "Improve test organization and helper functions",
status: "pending",
activeForm: "Improving test organization",
},
],
},
},
],
stop_reason: null,
stop_sequence: null,
usage: {
input_tokens: 6,
cache_creation_input_tokens: 326,
cache_read_input_tokens: 17265,
cache_creation: {
ephemeral_5m_input_tokens: 326,
ephemeral_1h_input_tokens: 0,
},
output_tokens: 1,
service_tier: "standard",
},
},
parent_tool_use_id: null,
session_id: "d056596f-e328-41e9-badd-b07122ae5227",
uuid: "b7c3330c-de8f-4bba-ac53-68c7f76ffeb5",
};
expect(toAcpNotifications(received, "test")).toStrictEqual([
{
sessionId: "test",
update: {
sessionUpdate: "plan",
entries: [
{
content: "Analyze existing test coverage and identify gaps",
priority: "medium",
status: "in_progress",
},
{
content: "Add comprehensive edge case tests",
priority: "medium",
status: "pending",
},
{
content: "Add performance and timing tests",
priority: "medium",
status: "pending",
},
{
content: "Add error handling and panic behavior tests",
priority: "medium",
status: "pending",
},
{
content: "Add concurrent access and race condition tests",
priority: "medium",
status: "pending",
},
{
content: "Add tests for Each function with various data types",
priority: "medium",
status: "pending",
},
{
content: "Add benchmark tests for performance measurement",
priority: "medium",
status: "pending",
},
{
content: "Improve test organization and helper functions",
priority: "medium",
status: "pending",
},
],
},
},
]);
});
});

View File

@@ -1,4 +1,5 @@
import {
PlanEntry,
ToolCallContent,
ToolKind,
} from "@zed-industries/agent-client-protocol";
@@ -249,3 +250,17 @@ export function toolContent(toolUse: any): ToolCallContent[] {
return [];
}
type ClaudePlanEntry = {
content: string;
status: "pending" | "in_progress" | "completed";
activeForm: string;
};
export function planEntries(input: { todos: ClaudePlanEntry[] }): PlanEntry[] {
return input.todos.map((input) => ({
content: input.content,
status: input.status,
priority: "medium",
}));
}