diff --git a/src/core/ClaudeDev.ts b/src/core/ClaudeDev.ts index 25bd73d..44775ed 100644 --- a/src/core/ClaudeDev.ts +++ b/src/core/ClaudeDev.ts @@ -31,11 +31,11 @@ import { arePathsEqual, getReadablePath } from "../utils/path" import { AssistantMessageContent, TextContent, - ToolCall, - ToolCallName, - toolCallNames, ToolParamName, toolParamNames, + ToolUse, + ToolUseName, + toolUseNames, } from "./prompts/AssistantMessage" import { parseMentions } from "./mentions" import { formatResponse } from "./prompts/responses" @@ -1140,7 +1140,7 @@ export class ClaudeDev { case "text": await this.say("text", block.content, undefined, block.partial) break - case "tool_call": + case "tool_use": const toolDescription = () => { switch (block.name) { case "execute_command": @@ -2058,9 +2058,9 @@ export class ClaudeDev { content: "", partial: true, } - let toolCalls: ToolCall[] = [] + let toolUses: ToolUse[] = [] - let currentToolCall: ToolCall | undefined = undefined + let currentToolUse: ToolUse | undefined = undefined let currentParamName: ToolParamName | undefined = undefined let currentParamValueLines: string[] = [] let textContentLines: string[] = [] @@ -2090,42 +2090,47 @@ export class ClaudeDev { for (const line of rawLines) { const trimmed = line.trim() // if currenttoolcall or currentparamname look for closing tag, more efficient and safe - if (currentToolCall && currentParamName && trimmed === ``) { + if (currentToolUse && currentParamName && trimmed === ``) { // End of a tool parameter - currentToolCall.params[currentParamName] = currentParamValueLines.join("\n") + currentToolUse.params[currentParamName] = currentParamValueLines.join("\n") currentParamName = undefined currentParamValueLines = [] // currentParamValue = undefined continue - } else if (currentToolCall && !currentParamName && trimmed === ``) { + } else if (currentToolUse && !currentParamName && trimmed === ``) { // End of a tool call - currentToolCall.partial = false - toolCalls.push(currentToolCall) - currentToolCall = undefined + currentToolUse.partial = false + toolUses.push(currentToolUse) + currentToolUse = undefined continue } if (!currentParamName && trimmed.startsWith("<") && trimmed.endsWith(">")) { const tag = trimmed.slice(1, -1) - if (toolCallNames.includes(tag as ToolCallName)) { + if (toolUseNames.includes(tag as ToolUseName)) { // Start of a new tool call - currentToolCall = { type: "tool_call", name: tag as ToolCallName, params: {}, partial: true } + currentToolUse = { + type: "tool_use", + name: tag as ToolUseName, + params: {}, + partial: true, + } satisfies ToolUse // This also indicates the end of the text content textContent.partial = false continue - } else if (currentToolCall && toolParamNames.includes(tag as ToolParamName)) { + } else if (currentToolUse && toolParamNames.includes(tag as ToolParamName)) { // Start of a parameter currentParamName = tag as ToolParamName - // currentToolCall.params[currentParamName] = "" + // currentToolUse.params[currentParamName] = "" continue } } - if (currentToolCall && !currentParamName) { + if (currentToolUse && !currentParamName) { // current tool doesn't have a param match yet, it's likely partial so ignore continue } - if (currentToolCall && currentParamName) { + if (currentToolUse && currentParamName) { // add line to current param value currentParamValueLines.push(line) continue @@ -2137,18 +2142,18 @@ export class ClaudeDev { } } - if (currentToolCall) { + if (currentToolUse) { // stream did not complete tool call, add it as partial if (currentParamName) { // tool call has a parameter that was not completed - currentToolCall.params[currentParamName] = currentParamValueLines.join("\n") + currentToolUse.params[currentParamName] = currentParamValueLines.join("\n") } - toolCalls.push(currentToolCall) + toolUses.push(currentToolUse) } textContent.content = textContentLines.join("\n") const prevLength = this.assistantMessageContent.length - this.assistantMessageContent = [textContent, ...toolCalls] + this.assistantMessageContent = [textContent, ...toolUses] if (this.assistantMessageContent.length > prevLength) { this.userMessageContentReady = false // new content we need to present, reset to false in case previous content set this to true } @@ -2321,7 +2326,7 @@ export class ClaudeDev { await pWaitFor(() => this.userMessageContentReady) // if the model did not tool use, then we need to tell it to either use a tool or attempt_completion - const didToolUse = this.assistantMessageContent.some((block) => block.type === "tool_call") + const didToolUse = this.assistantMessageContent.some((block) => block.type === "tool_use") if (!didToolUse) { this.userMessageContent.push({ type: "text", diff --git a/src/core/prompts/AssistantMessage.ts b/src/core/prompts/AssistantMessage.ts index 56641fd..328d94e 100644 --- a/src/core/prompts/AssistantMessage.ts +++ b/src/core/prompts/AssistantMessage.ts @@ -1,9 +1,4 @@ -// export interface AssistantMessage { -// textContent: TextContent -// toolCalls: ToolCall[] -// } - -export type AssistantMessageContent = TextContent | ToolCall +export type AssistantMessageContent = TextContent | ToolUse export interface TextContent { type: "text" @@ -11,7 +6,7 @@ export interface TextContent { partial: boolean } -export const toolCallNames = [ +export const toolUseNames = [ "execute_command", "read_file", "write_to_file", @@ -24,7 +19,7 @@ export const toolCallNames = [ ] as const // Converts array of tool call names into a union type ("execute_command" | "read_file" | ...) -export type ToolCallName = (typeof toolCallNames)[number] +export type ToolUseName = (typeof toolUseNames)[number] export const toolParamNames = [ "command", @@ -40,56 +35,56 @@ export const toolParamNames = [ export type ToolParamName = (typeof toolParamNames)[number] -export interface ToolCall { - type: "tool_call" - name: ToolCallName +export interface ToolUse { + type: "tool_use" + name: ToolUseName // params is a partial record, allowing only some or none of the possible parameters to be used params: Partial> partial: boolean } -interface ExecuteCommandToolCall extends ToolCall { +export interface ExecuteCommandToolUse extends ToolUse { name: "execute_command" // Pick, "command"> makes "command" required, but Partial<> makes it optional params: Partial, "command">> } -interface ReadFileToolCall extends ToolCall { +export interface ReadFileToolUse extends ToolUse { name: "read_file" params: Partial, "path">> } -interface WriteToFileToolCall extends ToolCall { +export interface WriteToFileToolUse extends ToolUse { name: "write_to_file" params: Partial, "path" | "content">> } -interface SearchFilesToolCall extends ToolCall { +export interface SearchFilesToolUse extends ToolUse { name: "search_files" params: Partial, "path" | "regex" | "file_pattern">> } -interface ListFilesToolCall extends ToolCall { +export interface ListFilesToolUse extends ToolUse { name: "list_files" params: Partial, "path" | "recursive">> } -interface ListCodeDefinitionNamesToolCall extends ToolCall { +export interface ListCodeDefinitionNamesToolUse extends ToolUse { name: "list_code_definition_names" params: Partial, "path">> } -interface InspectSiteToolCall extends ToolCall { +export interface InspectSiteToolUse extends ToolUse { name: "inspect_site" params: Partial, "url">> } -interface AskFollowupQuestionToolCall extends ToolCall { +export interface AskFollowupQuestionToolUse extends ToolUse { name: "ask_followup_question" params: Partial, "question">> } -interface AttemptCompletionToolCall extends ToolCall { +export interface AttemptCompletionToolUse extends ToolUse { name: "attempt_completion" params: Partial, "result" | "command">> }