Skip to content

Commit 7a68182

Browse files
committed
feat: implement Daniel's feedback on PR #6118
1 parent 5ce9ea5 commit 7a68182

File tree

4 files changed

+188
-18
lines changed

4 files changed

+188
-18
lines changed

src/core/tools/__tests__/codebaseSearchTool.spec.ts

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { codebaseSearchTool } from "../codebaseSearchTool"
33
import { CodeIndexManager } from "../../../services/code-index/manager"
44
import { Task } from "../../task/Task"
55
import { ToolUse } from "../../../shared/tools"
6+
import { TelemetryService } from "@roo-code/telemetry"
7+
import { TelemetryEventName } from "@roo-code/types"
68

79
// Mock dependencies
810
vi.mock("../../../services/code-index/manager")
@@ -19,6 +21,13 @@ vi.mock("vscode", () => ({
1921
asRelativePath: vi.fn((path: string) => path.replace("/test/workspace/", "")),
2022
},
2123
}))
24+
vi.mock("@roo-code/telemetry", () => ({
25+
TelemetryService: {
26+
instance: {
27+
captureEvent: vi.fn(),
28+
},
29+
},
30+
}))
2231

2332
describe("codebaseSearchTool", () => {
2433
let mockTask: Task
@@ -274,6 +283,145 @@ describe("codebaseSearchTool", () => {
274283
expect.stringContaining("Semantic search is not available yet (currently Standby)"),
275284
)
276285
})
286+
287+
it("should track telemetry when indexing is in Standby state", async () => {
288+
mockCodeIndexManager.state = "Standby"
289+
290+
const block: ToolUse = {
291+
type: "tool_use",
292+
name: "codebase_search",
293+
params: { query: "test query" },
294+
partial: false,
295+
}
296+
297+
await codebaseSearchTool(
298+
mockTask,
299+
block,
300+
mockAskApproval,
301+
mockHandleError,
302+
mockPushToolResult,
303+
mockRemoveClosingTag,
304+
)
305+
306+
expect(TelemetryService.instance.captureEvent).toHaveBeenCalledWith(TelemetryEventName.TOOL_USED, {
307+
tool: "codebase_search",
308+
codeIndexState: "Standby",
309+
hasQuery: true,
310+
result: "unavailable_not_indexed",
311+
})
312+
})
313+
314+
it("should track telemetry when indexing is in progress", async () => {
315+
mockCodeIndexManager.state = "Indexing"
316+
317+
const block: ToolUse = {
318+
type: "tool_use",
319+
name: "codebase_search",
320+
params: { query: "test query" },
321+
partial: false,
322+
}
323+
324+
await codebaseSearchTool(
325+
mockTask,
326+
block,
327+
mockAskApproval,
328+
mockHandleError,
329+
mockPushToolResult,
330+
mockRemoveClosingTag,
331+
)
332+
333+
expect(TelemetryService.instance.captureEvent).toHaveBeenCalledWith(TelemetryEventName.TOOL_USED, {
334+
tool: "codebase_search",
335+
codeIndexState: "Indexing",
336+
hasQuery: true,
337+
result: "unavailable_not_indexed",
338+
})
339+
expect(mockPushToolResult).toHaveBeenCalledWith(
340+
expect.stringContaining("Code indexing is currently in progress"),
341+
)
342+
})
343+
344+
it("should track telemetry when indexing is in error state", async () => {
345+
mockCodeIndexManager.state = "Error"
346+
347+
const block: ToolUse = {
348+
type: "tool_use",
349+
name: "codebase_search",
350+
params: { query: "test query" },
351+
partial: false,
352+
}
353+
354+
await codebaseSearchTool(
355+
mockTask,
356+
block,
357+
mockAskApproval,
358+
mockHandleError,
359+
mockPushToolResult,
360+
mockRemoveClosingTag,
361+
)
362+
363+
expect(TelemetryService.instance.captureEvent).toHaveBeenCalledWith(TelemetryEventName.TOOL_USED, {
364+
tool: "codebase_search",
365+
codeIndexState: "Error",
366+
hasQuery: true,
367+
result: "unavailable_not_indexed",
368+
})
369+
expect(mockPushToolResult).toHaveBeenCalledWith(
370+
expect.stringContaining("Code indexing encountered an error"),
371+
)
372+
})
373+
374+
it("should not track telemetry when indexing is complete", async () => {
375+
mockCodeIndexManager.state = "Indexed"
376+
mockCodeIndexManager.searchIndex.mockResolvedValue([])
377+
378+
const block: ToolUse = {
379+
type: "tool_use",
380+
name: "codebase_search",
381+
params: { query: "test query" },
382+
partial: false,
383+
}
384+
385+
await codebaseSearchTool(
386+
mockTask,
387+
block,
388+
mockAskApproval,
389+
mockHandleError,
390+
mockPushToolResult,
391+
mockRemoveClosingTag,
392+
)
393+
394+
// Should not capture telemetry event for non-indexed states
395+
expect(TelemetryService.instance.captureEvent).not.toHaveBeenCalledWith(
396+
TelemetryEventName.TOOL_USED,
397+
expect.objectContaining({
398+
result: "unavailable_not_indexed",
399+
}),
400+
)
401+
})
402+
403+
it("should track telemetry with hasQuery false when query is missing", async () => {
404+
mockCodeIndexManager.state = "Standby"
405+
406+
const block: ToolUse = {
407+
type: "tool_use",
408+
name: "codebase_search",
409+
params: {},
410+
partial: false,
411+
}
412+
413+
await codebaseSearchTool(
414+
mockTask,
415+
block,
416+
mockAskApproval,
417+
mockHandleError,
418+
mockPushToolResult,
419+
mockRemoveClosingTag,
420+
)
421+
422+
// Even though query is missing, telemetry should still be tracked before parameter validation
423+
expect(mockTask.sayAndCreateMissingParamError).toHaveBeenCalledWith("codebase_search", "query")
424+
})
277425
})
278426

279427
describe("parameter validation", () => {

src/core/tools/codebaseSearchTool.ts

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,28 @@ import { formatResponse } from "../prompts/responses"
77
import { VectorStoreSearchResult } from "../../services/code-index/interfaces"
88
import { AskApproval, HandleError, PushToolResult, RemoveClosingTag, ToolUse } from "../../shared/tools"
99
import path from "path"
10+
import { TelemetryService } from "@roo-code/telemetry"
11+
import { TelemetryEventName } from "@roo-code/types"
12+
13+
type IndexingState = "Standby" | "Indexing" | "Indexed" | "Error"
14+
15+
/**
16+
* Get a user-friendly message for the current indexing state
17+
* @param state The current indexing state
18+
* @returns A descriptive message for the user
19+
*/
20+
function getIndexingStateMessage(state: IndexingState): string {
21+
switch (state) {
22+
case "Standby":
23+
return "Code indexing has not started yet. Please wait for the initial indexing to complete."
24+
case "Indexing":
25+
return "Code indexing is currently in progress. Semantic search will be available once indexing is complete."
26+
case "Error":
27+
return "Code indexing encountered an error. Please check your configuration and try again."
28+
default:
29+
return `Code indexing is in an unexpected state: ${state}`
30+
}
31+
}
1032

1133
export async function codebaseSearchTool(
1234
cline: Task,
@@ -83,24 +105,20 @@ export async function codebaseSearchTool(
83105
}
84106

85107
// Check indexing state at runtime
86-
const indexingState = manager.state
108+
const indexingState = manager.state as IndexingState
109+
110+
// Track telemetry for non-indexed states
111+
if (indexingState !== "Indexed") {
112+
TelemetryService.instance.captureEvent(TelemetryEventName.TOOL_USED, {
113+
tool: toolName,
114+
codeIndexState: indexingState,
115+
hasQuery: query ? true : false,
116+
result: "unavailable_not_indexed",
117+
})
118+
}
119+
87120
if (indexingState !== "Indexed") {
88-
let stateMessage = ""
89-
switch (indexingState) {
90-
case "Standby":
91-
stateMessage =
92-
"Code indexing has not started yet. Please wait for the initial indexing to complete."
93-
break
94-
case "Indexing":
95-
stateMessage =
96-
"Code indexing is currently in progress. Semantic search will be available once indexing is complete."
97-
break
98-
case "Error":
99-
stateMessage = "Code indexing encountered an error. Please check your configuration and try again."
100-
break
101-
default:
102-
stateMessage = `Code indexing is in an unexpected state: ${indexingState}`
103-
}
121+
const stateMessage = getIndexingStateMessage(indexingState)
104122

105123
// Return informative message instead of throwing error
106124
pushToolResult(

src/i18n/locales/en/embeddings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,8 @@
5252
"vectorDimensionNotDetermined": "Could not determine vector dimension for model '{{modelId}}' with provider '{{provider}}'. Check model profiles or configuration.",
5353
"qdrantUrlMissing": "Qdrant URL missing for vector store creation",
5454
"codeIndexingNotConfigured": "Cannot create services: Code indexing is not properly configured"
55+
},
56+
"codeIndex": {
57+
"errorState": "Code index is in error state. Please check your configuration."
5558
}
5659
}

src/services/code-index/search-service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { CodeIndexConfigManager } from "./config-manager"
66
import { CodeIndexStateManager } from "./state-manager"
77
import { TelemetryService } from "@roo-code/telemetry"
88
import { TelemetryEventName } from "@roo-code/types"
9+
import { t } from "../../i18n"
910

1011
/**
1112
* Service responsible for searching the code index.
@@ -38,7 +39,7 @@ export class CodeIndexSearchService {
3839
// This allows the tool to provide more user-friendly feedback
3940
const currentState = this.stateManager.getCurrentStatus().systemStatus
4041
if (currentState === "Error") {
41-
throw new Error(`Code index is in error state. Please check your configuration.`)
42+
throw new Error(t("embeddings:codeIndex.errorState"))
4243
}
4344

4445
try {

0 commit comments

Comments
 (0)