diff --git a/extensions/cli/src/permissions/permissionChecker.ts b/extensions/cli/src/permissions/permissionChecker.ts index 093137d30f6..5c4fd886610 100644 --- a/extensions/cli/src/permissions/permissionChecker.ts +++ b/extensions/cli/src/permissions/permissionChecker.ts @@ -147,7 +147,9 @@ export function checkToolPermission( } // Check if tool has dynamic policy evaluation - const tool = ALL_BUILT_IN_TOOLS.find((t) => t.name === toolCall.name); + const tool = ALL_BUILT_IN_TOOLS.find( + (t) => t.function.name === toolCall.name, + ); if (tool?.evaluateToolCallPolicy) { // Convert CLI permission to core policy const basePolicy = permissionPolicyToToolPolicy(basePermission); diff --git a/extensions/cli/src/services/ToolPermissionService.ts b/extensions/cli/src/services/ToolPermissionService.ts index 3b0af61d856..9801d25502d 100644 --- a/extensions/cli/src/services/ToolPermissionService.ts +++ b/extensions/cli/src/services/ToolPermissionService.ts @@ -138,9 +138,9 @@ export class ToolPermissionService })); policies.push(...allowed); const specificBuiltInSet = new Set(specificBuiltIns); - const notMentioned = ALL_BUILT_IN_TOOLS.map((t) => t.name).filter( - (name) => !specificBuiltInSet.has(name), - ); + const notMentioned = ALL_BUILT_IN_TOOLS.map( + (t) => t.function.name, + ).filter((name) => !specificBuiltInSet.has(name)); const disallowed: ToolPermissionPolicy[] = notMentioned.map((tool) => ({ tool, permission: "exclude", diff --git a/extensions/cli/src/stream/handleToolCalls.ts b/extensions/cli/src/stream/handleToolCalls.ts index 4e4ec89d883..f0ec206dc2b 100644 --- a/extensions/cli/src/stream/handleToolCalls.ts +++ b/extensions/cli/src/stream/handleToolCalls.ts @@ -189,7 +189,7 @@ export async function getRequestTools(isHeadless: boolean) { const allowedTools: Tool[] = []; for (const tool of availableTools) { const result = checkToolPermission( - { name: tool.name, arguments: {} }, + { name: tool.function.name, arguments: {} }, permissionsState.permissions, ); diff --git a/extensions/cli/src/stream/streamChatResponse.helpers.ts b/extensions/cli/src/stream/streamChatResponse.helpers.ts index 6121e34265c..651854a5c7c 100644 --- a/extensions/cli/src/stream/streamChatResponse.helpers.ts +++ b/extensions/cli/src/stream/streamChatResponse.helpers.ts @@ -309,12 +309,16 @@ export async function preprocessStreamedToolCalls( // Get all available tools + // Get all available tools + const availableTools: Tool[] = await getAllAvailableTools(isHeadless); + // Process each tool call for (const toolCall of toolCalls) { const startTime = Date.now(); try { - const availableTools: Tool[] = await getAllAvailableTools(isHeadless); - const tool = availableTools.find((t) => t.name === toolCall.name); + const tool = availableTools.find( + (t) => t.function.name === toolCall.name, + ); if (!tool) { throw new Error(`Tool ${toolCall.name} not found`); } diff --git a/extensions/cli/src/tools/edit.ts b/extensions/cli/src/tools/edit.ts index 30aaacb8649..519e9c25604 100644 --- a/extensions/cli/src/tools/edit.ts +++ b/extensions/cli/src/tools/edit.ts @@ -50,7 +50,7 @@ export function validateAndResolveFilePath(args: any): { if (!readFilesSet.has(resolvedPath)) { throw new ContinueError( ContinueErrorReason.EditToolFileNotRead, - `You must use the ${readFileTool.name} tool to read ${file_path} before editing it.`, + `You must use the ${readFileTool.function.name} tool to read ${file_path} before editing it.`, ); } @@ -62,47 +62,50 @@ export interface EditArgs extends EditOperation { } export const editTool: Tool = { - name: "Edit", - displayName: "Edit", - readonly: false, - isBuiltIn: true, - description: `Performs exact string replacements in a file. + type: "function", + function: { + name: "Edit", + description: `Performs exact string replacements in a file. USAGE: -- ALWAYS use the \`${readFileTool.name}\` tool just before making edits, to understand the file's up-to-date contents and context. -- When editing text from ${readFileTool.name} tool output, ensure you preserve exact whitespace/indentation. +- ALWAYS use the \`${readFileTool.function.name}\` tool just before making edits, to understand the file's up-to-date contents and context. +- When editing text from ${readFileTool.function.name} tool output, ensure you preserve exact whitespace/indentation. - Always prefer editing existing files in the codebase. NEVER write new files unless explicitly required. - Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked. - Use \`replace_all\` for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable, for instance. WARNINGS: - When not using \`replace_all\`, the edit will FAIL if \`old_string\` is not unique in the file. Either provide a larger string with more surrounding context to make it unique or use \`replace_all\` to change every instance of \`old_string\`. -- The edit will FAIL if you have not recently used the \`${readFileTool.name}\` tool to view up-to-date file contents.`, - parameters: { - type: "object", - required: ["file_path", "old_string", "new_string"], - properties: { - file_path: { - type: "string", - description: - "Absolute or relative path to the file to modify. Absolute preferred", - }, - old_string: { - type: "string", - description: - "The text to replace - must be exact including whitespace/indentation", - }, - new_string: { - type: "string", - description: - "The text to replace it with (MUST be different from old_string)", - }, - replace_all: { - type: "boolean", - description: "Replace all occurrences of old_string (default false)", +- The edit will FAIL if you have not recently used the \`${readFileTool.function.name}\` tool to view up-to-date file contents.`, + parameters: { + type: "object", + required: ["file_path", "old_string", "new_string"], + properties: { + file_path: { + type: "string", + description: + "Absolute or relative path to the file to modify. Absolute preferred", + }, + old_string: { + type: "string", + description: + "The text to replace - must be exact including whitespace/indentation", + }, + new_string: { + type: "string", + description: + "The text to replace it with (MUST be different from old_string)", + }, + replace_all: { + type: "boolean", + description: "Replace all occurrences of old_string (default false)", + }, }, }, }, + displayName: "Edit", + readonly: false, + isBuiltIn: true, preprocess: async (args) => { const { old_string, new_string, replace_all } = args as EditArgs; diff --git a/extensions/cli/src/tools/exit.ts b/extensions/cli/src/tools/exit.ts index a6d84bdc3ee..9a7b07780c2 100644 --- a/extensions/cli/src/tools/exit.ts +++ b/extensions/cli/src/tools/exit.ts @@ -1,14 +1,17 @@ import { Tool } from "./types.js"; export const exitTool: Tool = { - name: "Exit", - displayName: "Exit", - description: - "Exit the current process with status code 1, indicating a failure or error", - parameters: { - type: "object", - properties: {}, + type: "function", + function: { + name: "Exit", + description: + "Exit the current process with status code 1, indicating a failure or error", + parameters: { + type: "object", + properties: {}, + }, }, + displayName: "Exit", readonly: false, isBuiltIn: true, run: async (): Promise => { diff --git a/extensions/cli/src/tools/fetch.test.ts b/extensions/cli/src/tools/fetch.test.ts index dc8e84ea690..3f1663b1133 100644 --- a/extensions/cli/src/tools/fetch.test.ts +++ b/extensions/cli/src/tools/fetch.test.ts @@ -136,14 +136,15 @@ describe("fetchTool", () => { }); it("should have correct tool metadata", () => { - expect(fetchTool.name).toBe("Fetch"); + expect(fetchTool.type).toBe("function"); + expect(fetchTool.function.name).toBe("Fetch"); expect(fetchTool.displayName).toBe("Fetch"); - expect(fetchTool.description).toBe( + expect(fetchTool.function.description).toBe( "Fetches content from a URL, converts to markdown, and handles long content with truncation", ); expect(fetchTool.readonly).toBe(true); expect(fetchTool.isBuiltIn).toBe(true); - expect(fetchTool.parameters).toEqual({ + expect(fetchTool.function.parameters).toEqual({ type: "object", required: ["url"], properties: { diff --git a/extensions/cli/src/tools/fetch.ts b/extensions/cli/src/tools/fetch.ts index 9a04a7a05aa..2dd8ccc12af 100644 --- a/extensions/cli/src/tools/fetch.ts +++ b/extensions/cli/src/tools/fetch.ts @@ -4,20 +4,23 @@ import { fetchUrlContentImpl } from "core/tools/implementations/fetchUrlContent. import { Tool } from "./types.js"; export const fetchTool: Tool = { - name: "Fetch", - displayName: "Fetch", - description: - "Fetches content from a URL, converts to markdown, and handles long content with truncation", - parameters: { - type: "object", - required: ["url"], - properties: { - url: { - type: "string", - description: "The URL to fetch content from", + type: "function", + function: { + name: "Fetch", + description: + "Fetches content from a URL, converts to markdown, and handles long content with truncation", + parameters: { + type: "object", + required: ["url"], + properties: { + url: { + type: "string", + description: "The URL to fetch content from", + }, }, }, }, + displayName: "Fetch", readonly: true, isBuiltIn: true, preprocess: async (args) => { diff --git a/extensions/cli/src/tools/index.tsx b/extensions/cli/src/tools/index.tsx index 21da49321cf..a9e95e61226 100644 --- a/extensions/cli/src/tools/index.tsx +++ b/extensions/cli/src/tools/index.tsx @@ -70,11 +70,10 @@ export async function getAllAvailableTools( const isCapable = isModelCapable(provider, name, model); if (isCapable) { tools.push(multiEditTool); + logger.debug("Using MultiEdit tool for capable model"); } else { tools.push(editTool); - logger.debug( - "Excluded Edit tool for capable model - MultiEdit will be used instead", - ); + logger.debug("Using Edit tool for basic model"); } logger.debug("Capability-based tool filtering", { @@ -101,7 +100,7 @@ export async function getAllAvailableTools( } export function getToolDisplayName(toolName: string): string { - const tool = ALL_BUILT_IN_TOOLS.find((t) => t.name === toolName); + const tool = ALL_BUILT_IN_TOOLS.find((t) => t.function.name === toolName); return tool?.displayName || toolName; } @@ -136,12 +135,12 @@ export function convertToolToChatCompletionTool( return { type: "function" as const, function: { - name: tool.name, - description: tool.description, + name: tool.function.name, + description: tool.function.description, parameters: { type: "object", - required: tool.parameters.required, - properties: tool.parameters.properties, + required: tool.function.parameters.required, + properties: tool.function.parameters.properties, }, }, }; @@ -149,17 +148,20 @@ export function convertToolToChatCompletionTool( export function convertMcpToolToContinueTool(mcpTool: MCPTool): Tool { return { - name: mcpTool.name, - displayName: mcpTool.name.replace("mcp__", "").replace("ide__", ""), - description: mcpTool.description ?? "", - parameters: { - type: "object", - properties: (mcpTool.inputSchema.properties ?? {}) as Record< - string, - ParameterSchema - >, - required: mcpTool.inputSchema.required, + type: "function", + function: { + name: mcpTool.name, + description: mcpTool.description ?? "", + parameters: { + type: "object", + properties: (mcpTool.inputSchema.properties ?? {}) as Record< + string, + ParameterSchema + >, + required: mcpTool.inputSchema.required, + }, }, + displayName: mcpTool.name.replace("mcp__", "").replace("ide__", ""), readonly: undefined, // MCP tools don't have readonly property isBuiltIn: false, run: async (args: any) => { @@ -234,8 +236,10 @@ export async function executeToolCall( // Only checks top-level required export function validateToolCallArgsPresent(toolCall: ToolCall, tool: Tool) { - const requiredParams = tool.parameters.required ?? []; - for (const [paramName] of Object.entries(tool.parameters)) { + const requiredParams = tool.function.parameters.required ?? []; + for (const [paramName] of Object.entries( + tool.function.parameters.properties ?? {}, + )) { if ( requiredParams.includes(paramName) && (toolCall.arguments[paramName] === undefined || diff --git a/extensions/cli/src/tools/listFiles.ts b/extensions/cli/src/tools/listFiles.ts index e90f6039b98..c897f60bb99 100644 --- a/extensions/cli/src/tools/listFiles.ts +++ b/extensions/cli/src/tools/listFiles.ts @@ -6,19 +6,22 @@ import { Tool } from "./types.js"; // List files in a directory export const listFilesTool: Tool = { - name: "List", - displayName: "List", - description: "List files in a directory", - parameters: { - type: "object", - required: ["dirpath"], - properties: { - dirpath: { - type: "string", - description: "The path to the directory to list", + type: "function", + function: { + name: "List", + description: "List files in a directory", + parameters: { + type: "object", + required: ["dirpath"], + properties: { + dirpath: { + type: "string", + description: "The path to the directory to list", + }, }, }, }, + displayName: "List", readonly: true, isBuiltIn: true, preprocess: async (args) => { diff --git a/extensions/cli/src/tools/multiEdit.ts b/extensions/cli/src/tools/multiEdit.ts index 983687c94d1..c919fc0c595 100644 --- a/extensions/cli/src/tools/multiEdit.ts +++ b/extensions/cli/src/tools/multiEdit.ts @@ -27,12 +27,11 @@ export interface MultiEditArgs { } export const multiEditTool: Tool = { - name: "MultiEdit", - displayName: "MultiEdit", - readonly: false, - isBuiltIn: true, - description: `Use this tool to make multiple edits to a single file in one operation. It allows you to perform multiple find-and-replace operations efficiently. -Prefer this tool over the ${editTool.name} tool when you need to make multiple edits to the same file. + type: "function", + function: { + name: "MultiEdit", + description: `Use this tool to make multiple edits to a single file in one operation. It allows you to perform multiple find-and-replace operations efficiently. +Prefer this tool over the ${editTool.function.name} tool when you need to make multiple edits to the same file. To make multiple edits to a file, provide the following: 1. file_path: The absolute path to the file to modify. Relative paths can also be used (resolved against cwd) but absolute is preferred @@ -49,7 +48,7 @@ IMPORTANT: - This tool is ideal when you need to make several changes to different parts of the same file CRITICAL REQUIREMENTS: -1. ALWAYS use the ${readFileTool.name} tool just before making edits, to understand the file's up-to-date contents and context +1. ALWAYS use the ${readFileTool.function.name} tool just before making edits, to understand the file's up-to-date contents and context 2. When making edits: - Ensure all edits result in idiomatic, correct code - Do not leave the code in a broken state @@ -62,46 +61,50 @@ WARNINGS: - If earlier edits affect the text that later edits are trying to find, files can become mangled - The tool will fail if edits.old_string doesn't match the file contents exactly (including whitespace) - The tool will fail if edits.old_string and edits.new_string are the same - they MUST be different -- The tool will fail if you have not used the ${readFileTool.name} tool to read the file in this session +- The tool will fail if you have not used the ${readFileTool.function.name} tool to read the file in this session - The tool will fail if the file does not exist - it cannot create new files - This tool cannot create new files - the file must already exist`, - parameters: { - type: "object", - required: ["file_path", "edits"], - properties: { - file_path: { - type: "string", - description: - "Absolute or relative path to the file to modify. Absolute preferred", - }, - edits: { - type: "array", - description: - "Array of edit operations to perform sequentially on the file", - items: { - type: "object", - required: ["old_string", "new_string"], - properties: { - old_string: { - type: "string", - description: - "The text to replace (exact match including whitespace/indentation)", - }, - new_string: { - type: "string", - description: - "The text to replace it with. MUST be different than old_string.", - }, - replace_all: { - type: "boolean", - description: - "Replace all occurrences of old_string (default false) in the file", + parameters: { + type: "object", + required: ["file_path", "edits"], + properties: { + file_path: { + type: "string", + description: + "Absolute or relative path to the file to modify. Absolute preferred", + }, + edits: { + type: "array", + description: + "Array of edit operations to perform sequentially on the file", + items: { + type: "object", + required: ["old_string", "new_string"], + properties: { + old_string: { + type: "string", + description: + "The text to replace (exact match including whitespace/indentation)", + }, + new_string: { + type: "string", + description: + "The text to replace it with. MUST be different than old_string.", + }, + replace_all: { + type: "boolean", + description: + "Replace all occurrences of old_string (default false) in the file", + }, }, }, }, }, }, }, + displayName: "MultiEdit", + readonly: false, + isBuiltIn: true, preprocess: async (args) => { const { resolvedPath } = validateAndResolveFilePath(args); diff --git a/extensions/cli/src/tools/readFile.ts b/extensions/cli/src/tools/readFile.ts index e62413e4620..c65f2912d9e 100644 --- a/extensions/cli/src/tools/readFile.ts +++ b/extensions/cli/src/tools/readFile.ts @@ -12,19 +12,22 @@ export function markFileAsRead(filePath: string) { } export const readFileTool: Tool = { - name: "Read", - displayName: "Read", - description: "Read the contents of a file at the specified path", - parameters: { - type: "object", - required: ["filepath"], - properties: { - filepath: { - type: "string", - description: "The path to the file to read", + type: "function", + function: { + name: "Read", + description: "Read the contents of a file at the specified path", + parameters: { + type: "object", + required: ["filepath"], + properties: { + filepath: { + type: "string", + description: "The path to the file to read", + }, }, }, }, + displayName: "Read", readonly: true, isBuiltIn: true, preprocess: async (args) => { diff --git a/extensions/cli/src/tools/runTerminalCommand.ts b/extensions/cli/src/tools/runTerminalCommand.ts index 00204d55bd1..6d8b07f4b62 100644 --- a/extensions/cli/src/tools/runTerminalCommand.ts +++ b/extensions/cli/src/tools/runTerminalCommand.ts @@ -29,22 +29,25 @@ function getShellCommand(command: string): { shell: string; args: string[] } { } export const runTerminalCommandTool: Tool = { - name: "Bash", - displayName: "Bash", - description: `Executes a terminal command and returns the output + type: "function", + function: { + name: "Bash", + description: `Executes a terminal command and returns the output Commands are automatically executed from the current working directory (${process.cwd()}), so there's no need to change directories with 'cd' commands. `, - parameters: { - type: "object", - required: ["command"], - properties: { - command: { - type: "string", - description: "The command to execute in the terminal.", + parameters: { + type: "object", + required: ["command"], + properties: { + command: { + type: "string", + description: "The command to execute in the terminal.", + }, }, }, }, + displayName: "Bash", readonly: false, isBuiltIn: true, evaluateToolCallPolicy: ( diff --git a/extensions/cli/src/tools/searchCode.ts b/extensions/cli/src/tools/searchCode.ts index 53e0f7a301f..5e42becde65 100644 --- a/extensions/cli/src/tools/searchCode.ts +++ b/extensions/cli/src/tools/searchCode.ts @@ -10,27 +10,31 @@ const execPromise = util.promisify(child_process.exec); const DEFAULT_MAX_RESULTS = 100; export const searchCodeTool: Tool = { - name: "Search", - displayName: "Search", - description: "Search the codebase using ripgrep (rg) for a specific pattern", - parameters: { - type: "object", - required: ["pattern"], - properties: { - pattern: { - type: "string", - description: "The search pattern to look for", - }, - path: { - type: "string", - description: "The path to search in (defaults to current directory)", - }, - file_pattern: { - type: "string", - description: "Optional file pattern to filter results (e.g., '*.ts')", + type: "function", + function: { + name: "Search", + description: + "Search the codebase using ripgrep (rg) for a specific pattern", + parameters: { + type: "object", + required: ["pattern"], + properties: { + pattern: { + type: "string", + description: "The search pattern to look for", + }, + path: { + type: "string", + description: "The path to search in (defaults to current directory)", + }, + file_pattern: { + type: "string", + description: "Optional file pattern to filter results (e.g., '*.ts')", + }, }, }, }, + displayName: "Search", readonly: true, isBuiltIn: true, preprocess: async (args) => { diff --git a/extensions/cli/src/tools/status.ts b/extensions/cli/src/tools/status.ts index 3cdaf6a620f..8d37c71a345 100644 --- a/extensions/cli/src/tools/status.ts +++ b/extensions/cli/src/tools/status.ts @@ -20,9 +20,10 @@ function getAgentIdFromArgs(): string | undefined { } export const statusTool: Tool = { - name: "Status", - displayName: "Status", - description: `Set the current status of your task for the user to see + type: "function", + function: { + name: "Status", + description: `Set the current status of your task for the user to see The default available statuses are: - PLANNING: You are creating a plan before beginning implementation @@ -33,16 +34,18 @@ The default available statuses are: However, if the user explicitly specifies in their prompt to use one or more different statuses, you can use those as well. You should use this tool to notify the user whenever the state of your work changes. By default, the status is assumed to be "PLANNING" prior to you setting a different status.`, - parameters: { - type: "object", - required: ["status"], - properties: { - status: { - type: "string", - description: "The status value to set", + parameters: { + type: "object", + required: ["status"], + properties: { + status: { + type: "string", + description: "The status value to set", + }, }, }, }, + displayName: "Status", readonly: true, isBuiltIn: true, run: async (args: { status: string }): Promise => { diff --git a/extensions/cli/src/tools/types.ts b/extensions/cli/src/tools/types.ts index 5adb45a92f8..776629a63fe 100644 --- a/extensions/cli/src/tools/types.ts +++ b/extensions/cli/src/tools/types.ts @@ -32,10 +32,14 @@ export interface PreprocessToolCallResult { } export interface Tool { - name: string; + type: "function"; + function: { + name: string; + type?: string; + description?: string; + parameters: ToolParametersSchema; + }; displayName: string; - description: string; - parameters: ToolParametersSchema; preprocess?: (args: any) => Promise; run: (args: any) => Promise; readonly?: boolean; // Indicates if the tool is readonly diff --git a/extensions/cli/src/tools/viewDiff.ts b/extensions/cli/src/tools/viewDiff.ts index 8b9f12d1d18..b052a336502 100644 --- a/extensions/cli/src/tools/viewDiff.ts +++ b/extensions/cli/src/tools/viewDiff.ts @@ -7,19 +7,22 @@ import { Tool } from "./types.js"; const execPromise = util.promisify(child_process.exec); export const viewDiffTool: Tool = { - name: "Diff", - displayName: "Diff", - description: "View all uncommitted changes in the git repository", - parameters: { - type: "object", - properties: { - path: { - type: "string", - description: - "The path to the git repository (defaults to current directory)", + type: "function", + function: { + name: "Diff", + description: "View all uncommitted changes in the git repository", + parameters: { + type: "object", + properties: { + path: { + type: "string", + description: + "The path to the git repository (defaults to current directory)", + }, }, }, }, + displayName: "Diff", readonly: true, isBuiltIn: true, preprocess: async (args) => { diff --git a/extensions/cli/src/tools/writeChecklist.test.ts b/extensions/cli/src/tools/writeChecklist.test.ts index f7638442fd2..e538b907f46 100644 --- a/extensions/cli/src/tools/writeChecklist.test.ts +++ b/extensions/cli/src/tools/writeChecklist.test.ts @@ -12,12 +12,13 @@ describe("writeChecklistTool", () => { }); it("should have correct tool properties", () => { - expect(writeChecklistTool.name).toBe("Checklist"); + expect(writeChecklistTool.type).toBe("function"); + expect(writeChecklistTool.function.name).toBe("Checklist"); expect(writeChecklistTool.displayName).toBe("Checklist"); expect(writeChecklistTool.readonly).toBe(false); expect(writeChecklistTool.isBuiltIn).toBe(true); - expect(writeChecklistTool.parameters.required?.includes("checklist")).toBe( - true, - ); + expect( + writeChecklistTool.function.parameters.required?.includes("checklist"), + ).toBe(true); }); }); diff --git a/extensions/cli/src/tools/writeChecklist.ts b/extensions/cli/src/tools/writeChecklist.ts index d2ca3b2c858..05ca9a7987d 100644 --- a/extensions/cli/src/tools/writeChecklist.ts +++ b/extensions/cli/src/tools/writeChecklist.ts @@ -1,23 +1,26 @@ import type { Tool } from "./types.js"; export const writeChecklistTool: Tool = { - name: "Checklist", - displayName: "Checklist", - description: - "Create or update a task checklist. The old checklist can be seen in the chat history if it exists. Use this tool to write a new checklist or edit the existing one.", - readonly: false, - isBuiltIn: true, - parameters: { - type: "object", - required: ["checklist"], - properties: { - checklist: { - type: "string", - description: - "The complete checklist in markdown format using - [ ] for incomplete tasks and - [x] for completed tasks. Avoid headers and additional content unless specifically being used to group checkboxes. Try to keep the list short, and make each item specific and actionable.", + type: "function", + function: { + name: "Checklist", + description: + "Create or update a task checklist. The old checklist can be seen in the chat history if it exists. Use this tool to write a new checklist or edit the existing one.", + parameters: { + type: "object", + required: ["checklist"], + properties: { + checklist: { + type: "string", + description: + "The complete checklist in markdown format using - [ ] for incomplete tasks and - [x] for completed tasks. Avoid headers and additional content unless specifically being used to group checkboxes. Try to keep the list short, and make each item specific and actionable.", + }, }, }, }, + displayName: "Checklist", + readonly: false, + isBuiltIn: true, preprocess: async (args: { checklist: string }) => { return { preview: [ diff --git a/extensions/cli/src/tools/writeFile.ts b/extensions/cli/src/tools/writeFile.ts index 55ef4f44c5b..2762ef8a62c 100644 --- a/extensions/cli/src/tools/writeFile.ts +++ b/extensions/cli/src/tools/writeFile.ts @@ -28,23 +28,26 @@ export function generateDiff( } export const writeFileTool: Tool = { - name: "Write", - displayName: "Write", - description: "Write content to a file at the specified path", - parameters: { - type: "object", - required: ["filepath", "content"], - properties: { - filepath: { - type: "string", - description: "The path to the file to write", - }, - content: { - type: "string", - description: "The content to write to the file", + type: "function", + function: { + name: "Write", + description: "Write content to a file at the specified path", + parameters: { + type: "object", + required: ["filepath", "content"], + properties: { + filepath: { + type: "string", + description: "The path to the file to write", + }, + content: { + type: "string", + description: "The content to write to the file", + }, }, }, }, + displayName: "Write", readonly: false, isBuiltIn: true, preprocess: async (args) => {