|
| 1 | +import { toolRegistry } from "./ToolRegistry" |
| 2 | +import { ToolName } from "@roo-code/types" |
| 3 | +import { Task } from "../task/Task" |
| 4 | +import { ToolUse, AskApproval, HandleError, PushToolResult, RemoveClosingTag } from "../../shared/tools" |
| 5 | + |
| 6 | +/** |
| 7 | + * ToolAdapter - Provides backward compatibility with existing tool invocation code |
| 8 | + * This adapter allows the existing codebase to work with the new RooTool classes |
| 9 | + * without requiring immediate changes to all tool invocations. |
| 10 | + * |
| 11 | + * This is a transitional component that can be removed once all code |
| 12 | + * has been updated to use the ToolRegistry directly. |
| 13 | + */ |
| 14 | +export class ToolAdapter { |
| 15 | + /** |
| 16 | + * Execute a tool by name using the new RooTool system |
| 17 | + * This method provides the same interface as the old tool functions |
| 18 | + * but delegates to the new RooTool implementations |
| 19 | + */ |
| 20 | + static async executeTool( |
| 21 | + toolName: ToolName, |
| 22 | + cline: Task, |
| 23 | + block: ToolUse, |
| 24 | + askApproval: AskApproval, |
| 25 | + handleError: HandleError, |
| 26 | + pushToolResult: PushToolResult, |
| 27 | + removeClosingTag: RemoveClosingTag, |
| 28 | + ): Promise<void> { |
| 29 | + const tool = toolRegistry.getTool(toolName) |
| 30 | + |
| 31 | + if (!tool) { |
| 32 | + // Fall back to legacy implementation if tool hasn't been migrated yet |
| 33 | + return ToolAdapter.executeLegacyTool( |
| 34 | + toolName, |
| 35 | + cline, |
| 36 | + block, |
| 37 | + askApproval, |
| 38 | + handleError, |
| 39 | + pushToolResult, |
| 40 | + removeClosingTag, |
| 41 | + ) |
| 42 | + } |
| 43 | + |
| 44 | + // Execute using the new RooTool implementation |
| 45 | + return tool.execute(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 46 | + } |
| 47 | + |
| 48 | + /** |
| 49 | + * Execute a legacy tool that hasn't been migrated yet |
| 50 | + * This allows for gradual migration of tools |
| 51 | + */ |
| 52 | + private static async executeLegacyTool( |
| 53 | + toolName: ToolName, |
| 54 | + cline: Task, |
| 55 | + block: ToolUse, |
| 56 | + askApproval: AskApproval, |
| 57 | + handleError: HandleError, |
| 58 | + pushToolResult: PushToolResult, |
| 59 | + removeClosingTag: RemoveClosingTag, |
| 60 | + ): Promise<void> { |
| 61 | + // Import and execute legacy tool implementations |
| 62 | + // These imports will be removed as tools are migrated |
| 63 | + switch (toolName) { |
| 64 | + case "write_to_file": { |
| 65 | + // This is already migrated, but keeping as example |
| 66 | + const { writeToFileTool } = await import("../tools/writeToFileTool") |
| 67 | + return writeToFileTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 68 | + } |
| 69 | + case "read_file": { |
| 70 | + const { readFileTool } = await import("../tools/readFileTool") |
| 71 | + return readFileTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 72 | + } |
| 73 | + case "execute_command": { |
| 74 | + const { executeCommandTool } = await import("../tools/executeCommandTool") |
| 75 | + return executeCommandTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 76 | + } |
| 77 | + case "apply_diff": { |
| 78 | + // Use the legacy apply diff for now |
| 79 | + const { applyDiffToolLegacy } = await import("../tools/applyDiffTool") |
| 80 | + return applyDiffToolLegacy(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 81 | + } |
| 82 | + case "search_files": { |
| 83 | + const { searchFilesTool } = await import("../tools/searchFilesTool") |
| 84 | + return searchFilesTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 85 | + } |
| 86 | + case "list_files": { |
| 87 | + const { listFilesTool } = await import("../tools/listFilesTool") |
| 88 | + return listFilesTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 89 | + } |
| 90 | + case "list_code_definition_names": { |
| 91 | + const { listCodeDefinitionNamesTool } = await import("../tools/listCodeDefinitionNamesTool") |
| 92 | + return listCodeDefinitionNamesTool( |
| 93 | + cline, |
| 94 | + block, |
| 95 | + askApproval, |
| 96 | + handleError, |
| 97 | + pushToolResult, |
| 98 | + removeClosingTag, |
| 99 | + ) |
| 100 | + } |
| 101 | + case "browser_action": { |
| 102 | + const { browserActionTool } = await import("../tools/browserActionTool") |
| 103 | + return browserActionTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 104 | + } |
| 105 | + case "use_mcp_tool": { |
| 106 | + const { useMcpToolTool } = await import("../tools/useMcpToolTool") |
| 107 | + return useMcpToolTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 108 | + } |
| 109 | + case "access_mcp_resource": { |
| 110 | + const { accessMcpResourceTool } = await import("../tools/accessMcpResourceTool") |
| 111 | + return accessMcpResourceTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 112 | + } |
| 113 | + case "ask_followup_question": { |
| 114 | + const { askFollowupQuestionTool } = await import("../tools/askFollowupQuestionTool") |
| 115 | + return askFollowupQuestionTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 116 | + } |
| 117 | + case "attempt_completion": { |
| 118 | + const { attemptCompletionTool } = await import("../tools/attemptCompletionTool") |
| 119 | + // attemptCompletionTool requires additional parameters |
| 120 | + const toolDescription = () => `[${block.name}]` |
| 121 | + const askFinishSubTaskApproval = async () => { |
| 122 | + const toolMessage = JSON.stringify({ tool: "finishTask" }) |
| 123 | + return await askApproval("tool", toolMessage) |
| 124 | + } |
| 125 | + return attemptCompletionTool( |
| 126 | + cline, |
| 127 | + block, |
| 128 | + askApproval, |
| 129 | + handleError, |
| 130 | + pushToolResult, |
| 131 | + removeClosingTag, |
| 132 | + toolDescription, |
| 133 | + askFinishSubTaskApproval, |
| 134 | + ) |
| 135 | + } |
| 136 | + case "switch_mode": { |
| 137 | + const { switchModeTool } = await import("../tools/switchModeTool") |
| 138 | + return switchModeTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 139 | + } |
| 140 | + case "new_task": { |
| 141 | + const { newTaskTool } = await import("../tools/newTaskTool") |
| 142 | + return newTaskTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 143 | + } |
| 144 | + case "insert_content": { |
| 145 | + const { insertContentTool } = await import("../tools/insertContentTool") |
| 146 | + return insertContentTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 147 | + } |
| 148 | + case "search_and_replace": { |
| 149 | + const { searchAndReplaceTool } = await import("../tools/searchAndReplaceTool") |
| 150 | + return searchAndReplaceTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 151 | + } |
| 152 | + case "codebase_search": { |
| 153 | + const { codebaseSearchTool } = await import("../tools/codebaseSearchTool") |
| 154 | + return codebaseSearchTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 155 | + } |
| 156 | + case "update_todo_list": { |
| 157 | + const { updateTodoListTool } = await import("../tools/updateTodoListTool") |
| 158 | + return updateTodoListTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 159 | + } |
| 160 | + case "run_slash_command": { |
| 161 | + const { runSlashCommandTool } = await import("../tools/runSlashCommandTool") |
| 162 | + return runSlashCommandTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 163 | + } |
| 164 | + case "generate_image": { |
| 165 | + const { generateImageTool } = await import("../tools/generateImageTool") |
| 166 | + return generateImageTool(cline, block, askApproval, handleError, pushToolResult, removeClosingTag) |
| 167 | + } |
| 168 | + case "fetch_instructions": { |
| 169 | + const { fetchInstructionsTool } = await import("../tools/fetchInstructionsTool") |
| 170 | + return fetchInstructionsTool(cline, block, askApproval, handleError, pushToolResult) |
| 171 | + } |
| 172 | + default: |
| 173 | + throw new Error(`Unknown tool: ${toolName}`) |
| 174 | + } |
| 175 | + } |
| 176 | + |
| 177 | + /** |
| 178 | + * Get tool usage description using the new system |
| 179 | + * Falls back to legacy implementation if needed |
| 180 | + */ |
| 181 | + static getToolUsageDescription(block: ToolUse): string { |
| 182 | + const tool = toolRegistry.getTool(block.name as ToolName) |
| 183 | + |
| 184 | + if (tool) { |
| 185 | + return tool.getToolUsageDescription(block) |
| 186 | + } |
| 187 | + |
| 188 | + // Fall back to legacy description logic |
| 189 | + // This is copied from presentAssistantMessage.ts and can be removed |
| 190 | + // once all tools are migrated |
| 191 | + switch (block.name) { |
| 192 | + case "execute_command": |
| 193 | + return `[${block.name} for '${block.params.command}']` |
| 194 | + case "write_to_file": |
| 195 | + return `[${block.name} to '${block.params.path}']` |
| 196 | + case "read_file": |
| 197 | + // This would use the getReadFileToolDescription function |
| 198 | + return `[${block.name} for '${block.params.path || block.params.args}']` |
| 199 | + case "list_files": |
| 200 | + return `[${block.name} for '${block.params.path}']` |
| 201 | + case "list_code_definition_names": |
| 202 | + return `[${block.name} for '${block.params.path}']` |
| 203 | + case "search_files": |
| 204 | + return `[${block.name} for '${block.params.regex}' in '${block.params.path}']` |
| 205 | + case "browser_action": |
| 206 | + return `[${block.name} for '${block.params.action}']` |
| 207 | + case "use_mcp_tool": |
| 208 | + return `[${block.name} for '${block.params.server_name}']` |
| 209 | + case "access_mcp_resource": |
| 210 | + return `[${block.name} for '${block.params.server_name}']` |
| 211 | + case "ask_followup_question": |
| 212 | + return `[${block.name} for '${block.params.question}']` |
| 213 | + case "attempt_completion": |
| 214 | + return `[${block.name}]` |
| 215 | + case "switch_mode": |
| 216 | + return `[${block.name} to '${block.params.mode_slug}'${block.params.reason ? ` because: ${block.params.reason}` : ""}]` |
| 217 | + case "codebase_search": |
| 218 | + return `[${block.name} for '${block.params.query}']` |
| 219 | + case "update_todo_list": |
| 220 | + return `[${block.name}]` |
| 221 | + case "new_task": |
| 222 | + return `[${block.name} in ${block.params.mode} mode: '${block.params.message}']` |
| 223 | + case "run_slash_command": |
| 224 | + return `[${block.name} for '${block.params.command}'${block.params.args ? ` with args: ${block.params.args}` : ""}]` |
| 225 | + case "generate_image": |
| 226 | + return `[${block.name} for '${block.params.path}']` |
| 227 | + default: |
| 228 | + return `[${block.name}]` |
| 229 | + } |
| 230 | + } |
| 231 | +} |
0 commit comments