Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/types/src/codebase-index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export const codebaseIndexConfigSchema = z.object({
codebaseIndexBedrockProfile: z.string().optional(),
// OpenRouter specific fields
codebaseIndexOpenRouterSpecificProvider: z.string().optional(),
// WarpGrep specific fields
warpGrepEnabled: z.boolean().optional(),
})

export type CodebaseIndexConfig = z.infer<typeof codebaseIndexConfigSchema>
Expand Down Expand Up @@ -85,6 +87,7 @@ export const codebaseIndexProviderSchema = z.object({
codebaseIndexMistralApiKey: z.string().optional(),
codebaseIndexVercelAiGatewayApiKey: z.string().optional(),
codebaseIndexOpenRouterApiKey: z.string().optional(),
warpGrepApiKey: z.string().optional(),
})

export type CodebaseIndexProvider = z.infer<typeof codebaseIndexProviderSchema>
1 change: 1 addition & 0 deletions packages/types/src/global-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ export const SECRET_STATE_KEYS = [
"codebaseIndexMistralApiKey",
"codebaseIndexVercelAiGatewayApiKey",
"codebaseIndexOpenRouterApiKey",
"warpGrepApiKey",
"sambaNovaApiKey",
"zaiApiKey",
"fireworksApiKey",
Expand Down
4 changes: 4 additions & 0 deletions packages/types/src/vscode-extension-host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,10 @@ export interface WebviewMessage {
codebaseIndexMistralApiKey?: string
codebaseIndexVercelAiGatewayApiKey?: string
codebaseIndexOpenRouterApiKey?: string

// WarpGrep specific fields
warpGrepEnabled?: boolean
warpGrepApiKey?: string
}
updatedSettings?: RooCodeSettings
/** Task configuration applied via `createTask()` when starting a cloud task. */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type OpenAI from "openai"

import { filterNativeToolsForMode, isToolAllowedInMode } from "../filter-tools-for-mode"

function makeTool(name: string): OpenAI.Chat.ChatCompletionTool {
return {
type: "function",
function: {
name,
description: `${name} tool`,
parameters: { type: "object", properties: {} },
},
} as OpenAI.Chat.ChatCompletionTool
}

describe("filterNativeToolsForMode - WarpGrep", () => {
it("keeps codebase_search available when WarpGrep is enabled", () => {
const result = filterNativeToolsForMode(
[makeTool("codebase_search"), makeTool("read_file")],
"code",
undefined,
undefined,
undefined,
{
codebaseIndexConfig: {
warpGrepEnabled: true,
},
},
)

expect(result.map((tool) => (tool as any).function.name)).toContain("codebase_search")
})

it("reports codebase_search as allowed when WarpGrep is enabled", () => {
expect(
isToolAllowedInMode("codebase_search", "code", undefined, undefined, undefined, {
codebaseIndexConfig: {
warpGrepEnabled: true,
},
}),
).toBe(true)
})
})
25 changes: 18 additions & 7 deletions src/core/prompts/tools/filter-tools-for-mode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,16 @@ export function filterNativeToolsForMode(
allowedToolNames = customizedTools

// Conditionally exclude codebase_search if feature is disabled or not configured
// WarpGrep can serve as an alternative backend for codebase_search
const warpGrepEnabled = settings?.codebaseIndexConfig?.warpGrepEnabled === true
if (
!codeIndexManager ||
!(codeIndexManager.isFeatureEnabled && codeIndexManager.isFeatureConfigured && codeIndexManager.isInitialized)
!warpGrepEnabled &&
(!codeIndexManager ||
!(
codeIndexManager.isFeatureEnabled &&
codeIndexManager.isFeatureConfigured &&
codeIndexManager.isInitialized
))
) {
allowedToolNames.delete("codebase_search")
}
Expand Down Expand Up @@ -363,11 +370,15 @@ export function isToolAllowedInMode(
if (ALWAYS_AVAILABLE_TOOLS.includes(toolName)) {
// But still check for conditional exclusions
if (toolName === "codebase_search") {
return !!(
codeIndexManager &&
codeIndexManager.isFeatureEnabled &&
codeIndexManager.isFeatureConfigured &&
codeIndexManager.isInitialized
const warpGrepEnabled = settings?.codebaseIndexConfig?.warpGrepEnabled === true
return (
warpGrepEnabled ||
!!(
codeIndexManager &&
codeIndexManager.isFeatureEnabled &&
codeIndexManager.isFeatureConfigured &&
codeIndexManager.isInitialized
)
)
}
if (toolName === "update_todo_list") {
Expand Down
1 change: 1 addition & 0 deletions src/core/task/build-tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export async function buildNativeToolsArrayWithRestrictions(options: BuildToolsO
// Build settings object for tool filtering.
const filterSettings = {
todoListEnabled: apiConfiguration?.todoListEnabled ?? true,
codebaseIndexConfig: provider.contextProxy.getGlobalState("codebaseIndexConfig"),
disabledTools,
modelInfo,
}
Expand Down
28 changes: 27 additions & 1 deletion src/core/tools/CodebaseSearchTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CodeIndexManager } from "../../services/code-index/manager"
import { getWorkspacePath } from "../../utils/path"
import { formatResponse } from "../prompts/responses"
import { VectorStoreSearchResult } from "../../services/code-index/interfaces"
import { executeWarpGrepSearch } from "../../services/warpgrep"
import type { ToolUse } from "../../shared/tools"

import { BaseTool, ToolCallbacks } from "./BaseTool"
Expand Down Expand Up @@ -52,7 +53,32 @@ export class CodebaseSearchTool extends BaseTool<"codebase_search"> {
task.consecutiveMistakeCount = 0

try {
const context = task.providerRef.deref()?.context
const provider = task.providerRef.deref()
const contextProxy = provider?.contextProxy

// Try WarpGrep first if enabled
if (contextProxy) {
const codebaseIndexConfig = contextProxy.getGlobalState("codebaseIndexConfig")
const warpGrepApiKey = contextProxy.getSecret("warpGrepApiKey")

if (codebaseIndexConfig?.warpGrepEnabled && warpGrepApiKey) {
const result = await executeWarpGrepSearch(
workspacePath,
query,
warpGrepApiKey,
task.rooIgnoreController,
)

if (result.success) {
pushToolResult(`Query: ${query}\n\n${result.content}`)
return
}

// Fall through to CodeIndexManager if available
}
}

const context = provider?.context
if (!context) {
throw new Error("Extension context is not available.")
}
Expand Down
6 changes: 6 additions & 0 deletions src/core/webview/webviewMessageHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2517,6 +2517,7 @@ export const webviewMessageHandler = async (
codebaseIndexSearchMaxResults: settings.codebaseIndexSearchMaxResults,
codebaseIndexSearchMinScore: settings.codebaseIndexSearchMinScore,
codebaseIndexOpenRouterSpecificProvider: settings.codebaseIndexOpenRouterSpecificProvider,
warpGrepEnabled: settings.warpGrepEnabled,
}

// Save global state first
Expand Down Expand Up @@ -2559,6 +2560,9 @@ export const webviewMessageHandler = async (
settings.codebaseIndexOpenRouterApiKey,
)
}
if (settings.warpGrepApiKey !== undefined) {
await provider.contextProxy.storeSecret("warpGrepApiKey", settings.warpGrepApiKey)
}

// Send success response first - settings are saved regardless of validation
await provider.postMessageToWebview({
Expand Down Expand Up @@ -2697,6 +2701,7 @@ export const webviewMessageHandler = async (
"codebaseIndexVercelAiGatewayApiKey",
))
const hasOpenRouterApiKey = !!(await provider.context.secrets.get("codebaseIndexOpenRouterApiKey"))
const hasWarpGrepApiKey = !!(await provider.context.secrets.get("warpGrepApiKey"))

provider.postMessageToWebview({
type: "codeIndexSecretStatus",
Expand All @@ -2708,6 +2713,7 @@ export const webviewMessageHandler = async (
hasMistralApiKey,
hasVercelAiGatewayApiKey,
hasOpenRouterApiKey,
hasWarpGrepApiKey,
},
})
break
Expand Down
Loading
Loading