diff --git a/extensions/cli/src/stream/streamChatResponse.getAllTools.test.ts b/extensions/cli/src/stream/streamChatResponse.getAllTools.test.ts index 800ae9aa960..b3f329ec341 100644 --- a/extensions/cli/src/stream/streamChatResponse.getAllTools.test.ts +++ b/extensions/cli/src/stream/streamChatResponse.getAllTools.test.ts @@ -47,7 +47,6 @@ describe("getRequestTools - Tool Filtering", () => { // Read-only tools should still be available expect(toolNames).toContain("Read"); expect(toolNames).toContain("List"); - expect(toolNames).toContain("Search"); expect(toolNames).toContain("Fetch"); expect(toolNames).toContain("Checklist"); @@ -130,7 +129,6 @@ describe("getRequestTools - Tool Filtering", () => { expect(toolNames).toContain("Bash"); expect(toolNames).toContain("Write"); expect(toolNames).toContain("List"); - expect(toolNames).toContain("Search"); }); test("plan mode should override allow flags (regression test for GitHub Actions issue)", async () => { @@ -158,6 +156,5 @@ describe("getRequestTools - Tool Filtering", () => { // Read-only tools should be available expect(toolNames).toContain("Read"); expect(toolNames).toContain("List"); - expect(toolNames).toContain("Search"); }); }); diff --git a/extensions/cli/src/tools/index.tsx b/extensions/cli/src/tools/index.tsx index 2c27d84bc6d..95dfc60f69b 100644 --- a/extensions/cli/src/tools/index.tsx +++ b/extensions/cli/src/tools/index.tsx @@ -27,7 +27,7 @@ import { multiEditTool } from "./multiEdit.js"; import { readFileTool } from "./readFile.js"; import { reportFailureTool } from "./reportFailure.js"; import { runTerminalCommandTool } from "./runTerminalCommand.js"; -import { searchCodeTool } from "./searchCode.js"; +import { checkIfRipgrepIsInstalled, searchCodeTool } from "./searchCode.js"; import { type Tool, type ToolCall, @@ -57,32 +57,29 @@ const BASE_BUILTIN_TOOLS: Tool[] = [ readFileTool, writeFileTool, listFilesTool, - searchCodeTool, runTerminalCommandTool, fetchTool, writeChecklistTool, - reportFailureTool, ]; +const BUILTIN_SEARCH_TOOLS: Tool[] = [searchCodeTool]; + // Get all builtin tools including dynamic ones, with capability-based filtering export async function getAllAvailableTools( isHeadless: boolean, ): Promise { const tools = [...BASE_BUILTIN_TOOLS]; - // Filter out ReportFailure tool if no agent ID is present + const isRipgrepInstalled = await checkIfRipgrepIsInstalled(); + if (isRipgrepInstalled) { + tools.push(...BUILTIN_SEARCH_TOOLS); + } + + // Add ReportFailure tool if no agent ID is present // (it requires --id to function and will confuse the agent if unavailable) const agentId = getAgentIdFromArgs(); - if (!agentId) { - const reportFailureIndex = tools.findIndex( - (t) => t.name === reportFailureTool.name, - ); - if (reportFailureIndex !== -1) { - tools.splice(reportFailureIndex, 1); - logger.debug( - `Filtered out ${reportFailureTool.name} tool - no agent ID present (--id flag not provided)`, - ); - } + if (agentId) { + tools.push(reportFailureTool); } // If model is capable, exclude editTool in favor of multiEditTool diff --git a/extensions/cli/src/tools/searchCode.ts b/extensions/cli/src/tools/searchCode.ts index af9e78756f3..cd4a1d77eef 100644 --- a/extensions/cli/src/tools/searchCode.ts +++ b/extensions/cli/src/tools/searchCode.ts @@ -12,6 +12,15 @@ const execPromise = util.promisify(child_process.exec); const DEFAULT_MAX_RESULTS = 100; const MAX_LINE_LENGTH = 1000; +export async function checkIfRipgrepIsInstalled(): Promise { + try { + await execPromise("rg --version"); + return true; + } catch { + return false; + } +} + export const searchCodeTool: Tool = { name: "Search", displayName: "Search",