From 1236c3b57104b5ddfaa1d49d805c8315ed19ddd8 Mon Sep 17 00:00:00 2001 From: daniel-lxs Date: Tue, 25 Nov 2025 14:28:12 -0500 Subject: [PATCH] fix: conditionally include codebase_search in native tools based on feature status --- .../native-tools/__tests__/index.spec.ts | 61 +++++++++++++++++++ src/core/prompts/tools/native-tools/index.ts | 17 ++++-- src/core/task/build-tools.ts | 9 ++- 3 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 src/core/prompts/tools/native-tools/__tests__/index.spec.ts diff --git a/src/core/prompts/tools/native-tools/__tests__/index.spec.ts b/src/core/prompts/tools/native-tools/__tests__/index.spec.ts new file mode 100644 index 0000000000..7b10c3232a --- /dev/null +++ b/src/core/prompts/tools/native-tools/__tests__/index.spec.ts @@ -0,0 +1,61 @@ +import { describe, it, expect } from "vitest" +import { getNativeTools } from "../index" + +// Helper to extract tool names +function getToolNames(tools: ReturnType): string[] { + return tools.map((t) => ("function" in t ? t.function.name : "")) +} + +// Helper to find a tool by name +function findTool(tools: ReturnType, name: string) { + return tools.find((t) => "function" in t && t.function.name === name) +} + +describe("getNativeTools", () => { + it("should include codebase_search when codebaseSearchEnabled is true", () => { + const tools = getNativeTools(true, true) + const toolNames = getToolNames(tools) + expect(toolNames).toContain("codebase_search") + }) + + it("should exclude codebase_search when codebaseSearchEnabled is false", () => { + const tools = getNativeTools(true, false) + const toolNames = getToolNames(tools) + expect(toolNames).not.toContain("codebase_search") + }) + + it("should include codebase_search by default (codebaseSearchEnabled defaults to true)", () => { + const tools = getNativeTools(true) + const toolNames = getToolNames(tools) + expect(toolNames).toContain("codebase_search") + }) + + it("should include read_file with line_ranges when partialReadsEnabled is true", () => { + const tools = getNativeTools(true, true) + const readFileTool = findTool(tools, "read_file") + expect(readFileTool).toBeDefined() + if (readFileTool && "function" in readFileTool) { + expect(readFileTool.function.description).toContain("line_ranges") + } + }) + + it("should include read_file without line_ranges when partialReadsEnabled is false", () => { + const tools = getNativeTools(false, true) + const readFileTool = findTool(tools, "read_file") + expect(readFileTool).toBeDefined() + if (readFileTool && "function" in readFileTool) { + expect(readFileTool.function.description).not.toContain("line_ranges") + } + }) + + it("should always include core tools regardless of settings", () => { + const tools = getNativeTools(true, true) + const toolNames = getToolNames(tools) + expect(toolNames).toContain("read_file") + expect(toolNames).toContain("write_to_file") + expect(toolNames).toContain("execute_command") + expect(toolNames).toContain("apply_diff") + expect(toolNames).toContain("ask_followup_question") + expect(toolNames).toContain("attempt_completion") + }) +}) diff --git a/src/core/prompts/tools/native-tools/index.ts b/src/core/prompts/tools/native-tools/index.ts index bb0d50da88..eed311fa9c 100644 --- a/src/core/prompts/tools/native-tools/index.ts +++ b/src/core/prompts/tools/native-tools/index.ts @@ -26,16 +26,19 @@ export { convertOpenAIToolToAnthropic, convertOpenAIToolsToAnthropic } from "./c * Get native tools array, optionally customizing based on settings. * * @param partialReadsEnabled - Whether to include line_ranges support in read_file tool (default: true) + * @param codebaseSearchEnabled - Whether to include codebase_search tool (default: true) * @returns Array of native tool definitions */ -export function getNativeTools(partialReadsEnabled: boolean = true): OpenAI.Chat.ChatCompletionTool[] { - return [ +export function getNativeTools( + partialReadsEnabled: boolean = true, + codebaseSearchEnabled: boolean = true, +): OpenAI.Chat.ChatCompletionTool[] { + const tools: OpenAI.Chat.ChatCompletionTool[] = [ accessMcpResource, apply_diff_single_file, askFollowupQuestion, attemptCompletion, browserAction, - codebaseSearch, executeCommand, fetchInstructions, generateImage, @@ -49,7 +52,13 @@ export function getNativeTools(partialReadsEnabled: boolean = true): OpenAI.Chat switchMode, updateTodoList, writeToFile, - ] satisfies OpenAI.Chat.ChatCompletionTool[] + ] + + if (codebaseSearchEnabled) { + tools.push(codebaseSearch) + } + + return tools } // Backward compatibility: export default tools with line ranges enabled diff --git a/src/core/task/build-tools.ts b/src/core/task/build-tools.ts index 4708a462d6..bc7f18abad 100644 --- a/src/core/task/build-tools.ts +++ b/src/core/task/build-tools.ts @@ -41,8 +41,15 @@ export async function buildNativeToolsArray(options: BuildToolsOptions): Promise // Determine if partial reads are enabled based on maxReadFileLine setting const partialReadsEnabled = maxReadFileLine !== -1 + // Determine if codebase_search should be included + const codebaseSearchEnabled = !!( + codeIndexManager?.isFeatureEnabled && + codeIndexManager?.isFeatureConfigured && + codeIndexManager?.isInitialized + ) + // Build native tools with dynamic read_file tool based on partialReadsEnabled - const nativeTools = getNativeTools(partialReadsEnabled) + const nativeTools = getNativeTools(partialReadsEnabled, codebaseSearchEnabled) // Filter native tools based on mode restrictions const filteredNativeTools = filterNativeToolsForMode(