Skip to content

Commit 0836a8f

Browse files
committed
refactor: ♻️ Refactor the cli tool type to align with core
1 parent 5e9ef89 commit 0836a8f

File tree

15 files changed

+305
-216
lines changed

15 files changed

+305
-216
lines changed

extensions/cli/src/stream/handleToolCalls.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ export async function getRequestTools(isHeadless: boolean) {
189189
const allowedTools: Tool[] = [];
190190
for (const tool of availableTools) {
191191
const result = checkToolPermission(
192-
{ name: tool.name, arguments: {} },
192+
{ name: tool.function.name, arguments: {} },
193193
permissionsState.permissions,
194194
);
195195

extensions/cli/src/tools/edit.ts

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export function validateAndResolveFilePath(args: any): {
5050
if (!readFilesSet.has(resolvedPath)) {
5151
throw new ContinueError(
5252
ContinueErrorReason.EditToolFileNotRead,
53-
`You must use the ${readFileTool.name} tool to read ${file_path} before editing it.`,
53+
`You must use the ${readFileTool.function.name} tool to read ${file_path} before editing it.`,
5454
);
5555
}
5656

@@ -62,47 +62,51 @@ export interface EditArgs extends EditOperation {
6262
}
6363

6464
export const editTool: Tool = {
65-
name: "Edit",
66-
displayName: "Edit",
67-
readonly: false,
68-
isBuiltIn: true,
69-
description: `Performs exact string replacements in a file.
65+
type: "function",
66+
function: {
67+
name: "Edit",
68+
description: `Performs exact string replacements in a file.
7069
7170
USAGE:
72-
- ALWAYS use the \`${readFileTool.name}\` tool just before making edits, to understand the file's up-to-date contents and context.
73-
- When editing text from ${readFileTool.name} tool output, ensure you preserve exact whitespace/indentation.
71+
- ALWAYS use the \`${readFileTool.function.name}\` tool just before making edits, to understand the file's up-to-date contents and context.
72+
- When editing text from ${readFileTool.function.name} tool output, ensure you preserve exact whitespace/indentation.
7473
- Always prefer editing existing files in the codebase. NEVER write new files unless explicitly required.
7574
- Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked.
7675
- Use \`replace_all\` for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable, for instance.
7776
7877
WARNINGS:
7978
- 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\`.
80-
- The edit will FAIL if you have not recently used the \`${readFileTool.name}\` tool to view up-to-date file contents.`,
81-
parameters: {
82-
type: "object",
83-
required: ["file_path", "old_string", "new_string"],
84-
properties: {
85-
file_path: {
86-
type: "string",
87-
description:
88-
"Absolute or relative path to the file to modify. Absolute preferred",
89-
},
90-
old_string: {
91-
type: "string",
92-
description:
93-
"The text to replace - must be exact including whitespace/indentation",
94-
},
95-
new_string: {
96-
type: "string",
97-
description:
98-
"The text to replace it with (MUST be different from old_string)",
99-
},
100-
replace_all: {
101-
type: "boolean",
102-
description: "Replace all occurrences of old_string (default false)",
79+
- The edit will FAIL if you have not recently used the \`${readFileTool.function.name}\` tool to view up-to-date file contents.`,
80+
parameters: {
81+
type: "object",
82+
required: ["file_path", "old_string", "new_string"],
83+
properties: {
84+
file_path: {
85+
type: "string",
86+
description:
87+
"Absolute or relative path to the file to modify. Absolute preferred",
88+
},
89+
old_string: {
90+
type: "string",
91+
description:
92+
"The text to replace - must be exact including whitespace/indentation",
93+
},
94+
new_string: {
95+
type: "string",
96+
description:
97+
"The text to replace it with (MUST be different from old_string)",
98+
},
99+
replace_all: {
100+
type: "boolean",
101+
description: "Replace all occurrences of old_string (default false)",
102+
},
103103
},
104104
},
105105
},
106+
displayTitle: "Edit",
107+
readonly: false,
108+
group: "Built-In",
109+
isBuiltIn: true,
106110
preprocess: async (args) => {
107111
const { old_string, new_string, replace_all } = args as EditArgs;
108112

extensions/cli/src/tools/exit.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
import { Tool } from "./types.js";
22

33
export const exitTool: Tool = {
4-
name: "Exit",
5-
displayName: "Exit",
6-
description:
7-
"Exit the current process with status code 1, indicating a failure or error",
8-
parameters: {
9-
type: "object",
10-
properties: {},
4+
type: "function",
5+
function: {
6+
name: "Exit",
7+
description:
8+
"Exit the current process with status code 1, indicating a failure or error",
9+
parameters: {
10+
type: "object",
11+
properties: {},
12+
},
1113
},
14+
displayTitle: "Exit",
1215
readonly: false,
16+
group: "Built-In",
1317
isBuiltIn: true,
1418
run: async (): Promise<string> => {
1519
const { gracefulExit } = await import("../util/exit.js");

extensions/cli/src/tools/fetch.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,25 @@ import { fetchUrlContentImpl } from "core/tools/implementations/fetchUrlContent.
44
import { Tool } from "./types.js";
55

66
export const fetchTool: Tool = {
7-
name: "Fetch",
8-
displayName: "Fetch",
9-
description:
10-
"Fetches content from a URL, converts to markdown, and handles long content with truncation",
11-
parameters: {
12-
type: "object",
13-
required: ["url"],
14-
properties: {
15-
url: {
16-
type: "string",
17-
description: "The URL to fetch content from",
7+
type: "function",
8+
function: {
9+
name: "Fetch",
10+
description:
11+
"Fetches content from a URL, converts to markdown, and handles long content with truncation",
12+
parameters: {
13+
type: "object",
14+
required: ["url"],
15+
properties: {
16+
url: {
17+
type: "string",
18+
description: "The URL to fetch content from",
19+
},
1820
},
1921
},
2022
},
23+
displayTitle: "Fetch",
2124
readonly: true,
25+
group: "Built-In",
2226
isBuiltIn: true,
2327
preprocess: async (args) => {
2428
return {

extensions/cli/src/tools/index.tsx

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ export async function getAllAvailableTools(
101101
}
102102

103103
export function getToolDisplayName(toolName: string): string {
104-
const tool = ALL_BUILT_IN_TOOLS.find((t) => t.name === toolName);
105-
return tool?.displayName || toolName;
104+
const tool = ALL_BUILT_IN_TOOLS.find((t) => t.function.name === toolName);
105+
return tool?.displayTitle || toolName;
106106
}
107107

108108
export function extractToolCalls(
@@ -136,31 +136,35 @@ export function convertToolToChatCompletionTool(
136136
return {
137137
type: "function" as const,
138138
function: {
139-
name: tool.name,
140-
description: tool.description,
141-
parameters: {
139+
name: tool.function.name,
140+
description: tool.function.description,
141+
parameters: tool.function.parameters || {
142142
type: "object",
143-
required: tool.parameters.required,
144-
properties: tool.parameters.properties,
143+
properties: {},
144+
required: [],
145145
},
146146
},
147147
};
148148
}
149149

150150
export function convertMcpToolToContinueTool(mcpTool: MCPTool): Tool {
151151
return {
152-
name: mcpTool.name,
153-
displayName: mcpTool.name.replace("mcp__", "").replace("ide__", ""),
154-
description: mcpTool.description ?? "",
155-
parameters: {
156-
type: "object",
157-
properties: (mcpTool.inputSchema.properties ?? {}) as Record<
158-
string,
159-
ParameterSchema
160-
>,
161-
required: mcpTool.inputSchema.required,
152+
type: "function" as const,
153+
function: {
154+
name: mcpTool.name,
155+
description: mcpTool.description ?? "",
156+
parameters: {
157+
type: "object",
158+
properties: (mcpTool.inputSchema.properties ?? {}) as Record<
159+
string,
160+
ParameterSchema
161+
>,
162+
required: mcpTool.inputSchema.required,
163+
},
162164
},
163-
readonly: undefined, // MCP tools don't have readonly property
165+
displayTitle: mcpTool.name.replace("mcp__", "").replace("ide__", ""),
166+
readonly: false,
167+
group: "MCP",
164168
isBuiltIn: false,
165169
run: async (args: any) => {
166170
const result = await services.mcp?.runTool(mcpTool.name, args);
@@ -234,12 +238,22 @@ export async function executeToolCall(
234238

235239
// Only checks top-level required
236240
export function validateToolCallArgsPresent(toolCall: ToolCall, tool: Tool) {
237-
const requiredParams = tool.parameters.required ?? [];
238-
for (const [paramName] of Object.entries(tool.parameters)) {
241+
const parameters = tool.function.parameters;
242+
if (
243+
!parameters ||
244+
typeof parameters !== "object" ||
245+
!("required" in parameters)
246+
) {
247+
return; // No parameter validation if schema is missing
248+
}
249+
250+
const requiredParams = parameters.required ?? [];
251+
const properties = parameters.properties ?? {};
252+
253+
for (const paramName of requiredParams) {
239254
if (
240-
requiredParams.includes(paramName) &&
241-
(toolCall.arguments[paramName] === undefined ||
242-
toolCall.arguments[paramName] === null)
255+
toolCall.arguments[paramName] === undefined ||
256+
toolCall.arguments[paramName] === null
243257
) {
244258
throw new Error(
245259
`Required parameter "${paramName}" missing for tool "${toolCall.name}"`,

extensions/cli/src/tools/listFiles.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,24 @@ import { Tool } from "./types.js";
66

77
// List files in a directory
88
export const listFilesTool: Tool = {
9-
name: "List",
10-
displayName: "List",
11-
description: "List files in a directory",
12-
parameters: {
13-
type: "object",
14-
required: ["dirpath"],
15-
properties: {
16-
dirpath: {
17-
type: "string",
18-
description: "The path to the directory to list",
9+
type: "function",
10+
function: {
11+
name: "List",
12+
description: "List files in a directory",
13+
parameters: {
14+
type: "object",
15+
required: ["dirpath"],
16+
properties: {
17+
dirpath: {
18+
type: "string",
19+
description: "The path to the directory to list",
20+
},
1921
},
2022
},
2123
},
24+
displayTitle: "List",
2225
readonly: true,
26+
group: "Built-In",
2327
isBuiltIn: true,
2428
preprocess: async (args) => {
2529
// Resolve relative paths

0 commit comments

Comments
 (0)