Browse Source

Feat/issue 5149 configurable max search results (#5402)

* feat: add configurable max search results for codebase indexing (#5149)

- Add codebaseIndexSearchMaxResults to configuration schema with validation (10-1000)
- Update Qdrant client to accept maxResults parameter in search method
- Add UI slider in Experimental Settings to configure max search results
- Rename constants to DEFAULT_MAX_SEARCH_RESULTS and DEFAULT_SEARCH_MIN_SCORE for clarity
- Add translations for new setting across all 17 supported languages
- Add comprehensive test coverage for config manager, Qdrant client, and UI components

fix: settings persistence for codebase index configuration

- Add new updateCodebaseIndexConfig message type to properly merge config updates
- Update SettingsView to send entire codebaseIndexConfig object instead of just enabled flag
- Add backend handler to merge configuration updates instead of overwriting
- Add tests for the new message handler functionality

This ensures the max search results setting persists correctly when saved.

* fix: correct property name in updateCodebaseIndexConfig message

The frontend was sending 'config' but the backend expects 'codebaseIndexConfig'.
This mismatch was preventing the max search results setting from persisting.

* feat: refactor codebase index constants and update search result defaults

* feat(chat): add advanced settings for maximum search results configuration

* refactor: remove updateCodebaseIndexConfig and integrate max search results into saveCodeIndexSettingsAtomic

- Removed updateCodebaseIndexConfig message type and handler as per PR feedback
- Added codebaseIndexSearchMaxResults to codeIndexSettings type in WebviewMessage.ts
- Updated saveCodeIndexSettingsAtomic to save codebaseIndexSearchMaxResults
- Fixed SettingsView.tsx to use codebaseIndexEnabled message instead of updateCodebaseIndexConfig

* Delete webview-ui/src/components/settings/__tests__/ExperimentalSettings.spec.tsx

* refactor: remove updateCodebaseIndexConfig tests to streamline codebase indexing logic

* revert this

---------

Co-authored-by: Daniel Riccio <[email protected]>
Co-authored-by: Daniel <[email protected]>
Murilo Pires 8 months ago
parent
commit
4a78f51fe5
31 changed files with 291 additions and 46 deletions
  1. 16 0
      packages/types/src/codebase-index.ts
  2. 1 0
      src/core/webview/webviewMessageHandler.ts
  3. 60 2
      src/services/code-index/__tests__/config-manager.spec.ts
  4. 16 3
      src/services/code-index/config-manager.ts
  5. 4 2
      src/services/code-index/constants/index.ts
  6. 1 0
      src/services/code-index/interfaces/config.ts
  7. 9 2
      src/services/code-index/interfaces/vector-store.ts
  8. 2 1
      src/services/code-index/search-service.ts
  9. 35 11
      src/services/code-index/vector-store/__tests__/qdrant-client.spec.ts
  10. 7 8
      src/services/code-index/vector-store/qdrant-client.ts
  11. 1 0
      src/shared/WebviewMessage.ts
  12. 67 0
      webview-ui/src/components/chat/CodeIndexPopover.tsx
  13. 1 0
      webview-ui/src/context/ExtensionStateContext.tsx
  14. 4 1
      webview-ui/src/i18n/locales/ca/settings.json
  15. 4 1
      webview-ui/src/i18n/locales/de/settings.json
  16. 3 0
      webview-ui/src/i18n/locales/en/settings.json
  17. 4 1
      webview-ui/src/i18n/locales/es/settings.json
  18. 4 1
      webview-ui/src/i18n/locales/fr/settings.json
  19. 4 1
      webview-ui/src/i18n/locales/hi/settings.json
  20. 4 1
      webview-ui/src/i18n/locales/id/settings.json
  21. 4 1
      webview-ui/src/i18n/locales/it/settings.json
  22. 4 1
      webview-ui/src/i18n/locales/ja/settings.json
  23. 4 1
      webview-ui/src/i18n/locales/ko/settings.json
  24. 4 1
      webview-ui/src/i18n/locales/nl/settings.json
  25. 4 1
      webview-ui/src/i18n/locales/pl/settings.json
  26. 4 1
      webview-ui/src/i18n/locales/pt-BR/settings.json
  27. 4 1
      webview-ui/src/i18n/locales/ru/settings.json
  28. 4 1
      webview-ui/src/i18n/locales/tr/settings.json
  29. 4 1
      webview-ui/src/i18n/locales/vi/settings.json
  30. 4 1
      webview-ui/src/i18n/locales/zh-CN/settings.json
  31. 4 1
      webview-ui/src/i18n/locales/zh-TW/settings.json

+ 16 - 0
packages/types/src/codebase-index.ts

@@ -1,5 +1,16 @@
 import { z } from "zod"
 
+/**
+ * Codebase Index Constants
+ */
+export const CODEBASE_INDEX_DEFAULTS = {
+	MIN_SEARCH_RESULTS: 10,
+	MAX_SEARCH_RESULTS: 200,
+	DEFAULT_SEARCH_RESULTS: 50,
+	SEARCH_RESULTS_STEP: 10,
+	DEFAULT_SEARCH_MIN_SCORE: 0.4,
+} as const
+
 /**
  * CodebaseIndexConfig
  */
@@ -11,6 +22,11 @@ export const codebaseIndexConfigSchema = z.object({
 	codebaseIndexEmbedderBaseUrl: z.string().optional(),
 	codebaseIndexEmbedderModelId: z.string().optional(),
 	codebaseIndexSearchMinScore: z.number().min(0).max(1).optional(),
+	codebaseIndexSearchMaxResults: z
+		.number()
+		.min(CODEBASE_INDEX_DEFAULTS.MIN_SEARCH_RESULTS)
+		.max(CODEBASE_INDEX_DEFAULTS.MAX_SEARCH_RESULTS)
+		.optional(),
 })
 
 export type CodebaseIndexConfig = z.infer<typeof codebaseIndexConfigSchema>

+ 1 - 0
src/core/webview/webviewMessageHandler.ts

@@ -1840,6 +1840,7 @@ export const webviewMessageHandler = async (
 					codebaseIndexEmbedderModelId: settings.codebaseIndexEmbedderModelId,
 					codebaseIndexOpenAiCompatibleBaseUrl: settings.codebaseIndexOpenAiCompatibleBaseUrl,
 					codebaseIndexOpenAiCompatibleModelDimension: settings.codebaseIndexOpenAiCompatibleModelDimension,
+					codebaseIndexSearchMaxResults: settings.codebaseIndexSearchMaxResults,
 				}
 
 				// Save global state first

+ 60 - 2
src/services/code-index/__tests__/config-manager.spec.ts

@@ -767,7 +767,7 @@ describe("CodeIndexConfigManager", () => {
 					expect(configManager.currentSearchMinScore).toBe(0.15)
 				})
 
-				it("should fall back to default SEARCH_MIN_SCORE when neither user setting nor model threshold exists", async () => {
+				it("should fall back to default DEFAULT_SEARCH_MIN_SCORE when neither user setting nor model threshold exists", async () => {
 					mockContextProxy.getGlobalState.mockReturnValue({
 						codebaseIndexEnabled: true,
 						codebaseIndexQdrantUrl: "http://qdrant.local",
@@ -781,7 +781,7 @@ describe("CodeIndexConfigManager", () => {
 					})
 
 					await configManager.loadConfiguration()
-					// Should fall back to default SEARCH_MIN_SCORE (0.4)
+					// Should fall back to default DEFAULT_SEARCH_MIN_SCORE (0.4)
 					expect(configManager.currentSearchMinScore).toBe(0.4)
 				})
 
@@ -881,6 +881,61 @@ describe("CodeIndexConfigManager", () => {
 					expect(anotherManager.currentSearchMinScore).toBe(0.4) // Default
 				})
 			})
+
+			describe("currentSearchMaxResults", () => {
+				it("should return user setting when provided, otherwise default", async () => {
+					// Test 1: User setting takes precedence
+					mockContextProxy.getGlobalState.mockReturnValue({
+						codebaseIndexEnabled: true,
+						codebaseIndexQdrantUrl: "http://qdrant.local",
+						codebaseIndexEmbedderProvider: "openai",
+						codebaseIndexEmbedderModelId: "text-embedding-3-small",
+						codebaseIndexSearchMaxResults: 150, // User setting
+					})
+
+					await configManager.loadConfiguration()
+					expect(configManager.currentSearchMaxResults).toBe(150) // User setting
+
+					// Test 2: Default when no user setting
+					mockContextProxy.getGlobalState.mockReturnValue({
+						codebaseIndexEnabled: true,
+						codebaseIndexQdrantUrl: "http://qdrant.local",
+						codebaseIndexEmbedderProvider: "openai",
+						codebaseIndexEmbedderModelId: "text-embedding-3-small",
+						// No user setting
+					})
+
+					const newManager = new CodeIndexConfigManager(mockContextProxy)
+					await newManager.loadConfiguration()
+					expect(newManager.currentSearchMaxResults).toBe(50) // Default (DEFAULT_MAX_SEARCH_RESULTS)
+
+					// Test 3: Boundary values
+					mockContextProxy.getGlobalState.mockReturnValue({
+						codebaseIndexEnabled: true,
+						codebaseIndexQdrantUrl: "http://qdrant.local",
+						codebaseIndexEmbedderProvider: "openai",
+						codebaseIndexEmbedderModelId: "text-embedding-3-small",
+						codebaseIndexSearchMaxResults: 10, // Minimum allowed
+					})
+
+					const minManager = new CodeIndexConfigManager(mockContextProxy)
+					await minManager.loadConfiguration()
+					expect(minManager.currentSearchMaxResults).toBe(10)
+
+					// Test 4: Maximum value
+					mockContextProxy.getGlobalState.mockReturnValue({
+						codebaseIndexEnabled: true,
+						codebaseIndexQdrantUrl: "http://qdrant.local",
+						codebaseIndexEmbedderProvider: "openai",
+						codebaseIndexEmbedderModelId: "text-embedding-3-small",
+						codebaseIndexSearchMaxResults: 200, // Maximum allowed
+					})
+
+					const maxManager = new CodeIndexConfigManager(mockContextProxy)
+					await maxManager.loadConfiguration()
+					expect(maxManager.currentSearchMaxResults).toBe(200)
+				})
+			})
 		})
 
 		describe("empty/missing API key handling", () => {
@@ -1157,9 +1212,12 @@ describe("CodeIndexConfigManager", () => {
 				modelId: "text-embedding-3-large",
 				openAiOptions: { openAiNativeApiKey: "test-openai-key" },
 				ollamaOptions: { ollamaBaseUrl: undefined },
+				geminiOptions: undefined,
+				openAiCompatibleOptions: undefined,
 				qdrantUrl: "http://qdrant.local",
 				qdrantApiKey: "test-qdrant-key",
 				searchMinScore: 0.4,
+				searchMaxResults: 50,
 			})
 		})
 

+ 16 - 3
src/services/code-index/config-manager.ts

@@ -2,7 +2,7 @@ import { ApiHandlerOptions } from "../../shared/api"
 import { ContextProxy } from "../../core/config/ContextProxy"
 import { EmbedderProvider } from "./interfaces/manager"
 import { CodeIndexConfig, PreviousConfigSnapshot } from "./interfaces/config"
-import { SEARCH_MIN_SCORE } from "./constants"
+import { DEFAULT_SEARCH_MIN_SCORE, DEFAULT_MAX_SEARCH_RESULTS } from "./constants"
 import { getDefaultModelId, getModelDimension, getModelScoreThreshold } from "../../shared/embeddingModels"
 
 /**
@@ -20,6 +20,7 @@ export class CodeIndexConfigManager {
 	private qdrantUrl?: string = "http://localhost:6333"
 	private qdrantApiKey?: string
 	private searchMinScore?: number
+	private searchMaxResults?: number
 
 	constructor(private readonly contextProxy: ContextProxy) {
 		// Initialize with current configuration to avoid false restart triggers
@@ -46,6 +47,7 @@ export class CodeIndexConfigManager {
 			codebaseIndexEmbedderBaseUrl: "",
 			codebaseIndexEmbedderModelId: "",
 			codebaseIndexSearchMinScore: undefined,
+			codebaseIndexSearchMaxResults: undefined,
 		}
 
 		const {
@@ -55,6 +57,7 @@ export class CodeIndexConfigManager {
 			codebaseIndexEmbedderBaseUrl,
 			codebaseIndexEmbedderModelId,
 			codebaseIndexSearchMinScore,
+			codebaseIndexSearchMaxResults,
 		} = codebaseIndexConfig
 
 		const openAiKey = this.contextProxy?.getSecret("codeIndexOpenAiKey") ?? ""
@@ -71,6 +74,7 @@ export class CodeIndexConfigManager {
 		this.qdrantUrl = codebaseIndexQdrantUrl
 		this.qdrantApiKey = qdrantApiKey ?? ""
 		this.searchMinScore = codebaseIndexSearchMinScore
+		this.searchMaxResults = codebaseIndexSearchMaxResults
 		this.openAiOptions = { openAiNativeApiKey: openAiKey }
 
 		// Set embedder provider with support for openai-compatible
@@ -334,6 +338,7 @@ export class CodeIndexConfigManager {
 			qdrantUrl: this.qdrantUrl,
 			qdrantApiKey: this.qdrantApiKey,
 			searchMinScore: this.currentSearchMinScore,
+			searchMaxResults: this.currentSearchMaxResults,
 		}
 	}
 
@@ -377,7 +382,7 @@ export class CodeIndexConfigManager {
 
 	/**
 	 * Gets the configured minimum search score based on user setting, model-specific threshold, or fallback.
-	 * Priority: 1) User setting, 2) Model-specific threshold, 3) Default SEARCH_MIN_SCORE constant.
+	 * Priority: 1) User setting, 2) Model-specific threshold, 3) Default DEFAULT_SEARCH_MIN_SCORE constant.
 	 */
 	public get currentSearchMinScore(): number {
 		// First check if user has configured a custom score threshold
@@ -388,6 +393,14 @@ export class CodeIndexConfigManager {
 		// Fall back to model-specific threshold
 		const currentModelId = this.modelId ?? getDefaultModelId(this.embedderProvider)
 		const modelSpecificThreshold = getModelScoreThreshold(this.embedderProvider, currentModelId)
-		return modelSpecificThreshold ?? SEARCH_MIN_SCORE
+		return modelSpecificThreshold ?? DEFAULT_SEARCH_MIN_SCORE
+	}
+
+	/**
+	 * Gets the configured maximum search results.
+	 * Returns user setting if configured, otherwise returns default.
+	 */
+	public get currentSearchMaxResults(): number {
+		return this.searchMaxResults ?? DEFAULT_MAX_SEARCH_RESULTS
 	}
 }

+ 4 - 2
src/services/code-index/constants/index.ts

@@ -1,3 +1,5 @@
+import { CODEBASE_INDEX_DEFAULTS } from "@roo-code/types"
+
 /**Parser */
 export const MAX_BLOCK_CHARS = 1000
 export const MIN_BLOCK_CHARS = 50
@@ -5,8 +7,8 @@ export const MIN_CHUNK_REMAINDER_CHARS = 200 // Minimum characters for the *next
 export const MAX_CHARS_TOLERANCE_FACTOR = 1.15 // 15% tolerance for max chars
 
 /**Search */
-export const SEARCH_MIN_SCORE = 0.4
-export const MAX_SEARCH_RESULTS = 50 // Maximum number of search results to return
+export const DEFAULT_SEARCH_MIN_SCORE = CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_MIN_SCORE
+export const DEFAULT_MAX_SEARCH_RESULTS = CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_RESULTS
 
 /**File Watcher */
 export const QDRANT_CODE_BLOCK_NAMESPACE = "f47ac10b-58cc-4372-a567-0e02b2c3d479"

+ 1 - 0
src/services/code-index/interfaces/config.ts

@@ -16,6 +16,7 @@ export interface CodeIndexConfig {
 	qdrantUrl?: string
 	qdrantApiKey?: string
 	searchMinScore?: number
+	searchMaxResults?: number
 }
 
 /**

+ 9 - 2
src/services/code-index/interfaces/vector-store.ts

@@ -23,10 +23,17 @@ export interface IVectorStore {
 	/**
 	 * Searches for similar vectors
 	 * @param queryVector Vector to search for
-	 * @param limit Maximum number of results to return
+	 * @param directoryPrefix Optional directory prefix to filter results
+	 * @param minScore Optional minimum score threshold
+	 * @param maxResults Optional maximum number of results to return
 	 * @returns Promise resolving to search results
 	 */
-	search(queryVector: number[], directoryPrefix?: string, minScore?: number): Promise<VectorStoreSearchResult[]>
+	search(
+		queryVector: number[],
+		directoryPrefix?: string,
+		minScore?: number,
+		maxResults?: number,
+	): Promise<VectorStoreSearchResult[]>
 
 	/**
 	 * Deletes points by file path

+ 2 - 1
src/services/code-index/search-service.ts

@@ -30,6 +30,7 @@ export class CodeIndexSearchService {
 		}
 
 		const minScore = this.configManager.currentSearchMinScore
+		const maxResults = this.configManager.currentSearchMaxResults
 
 		const currentState = this.stateManager.getCurrentStatus().systemStatus
 		if (currentState !== "Indexed" && currentState !== "Indexing") {
@@ -52,7 +53,7 @@ export class CodeIndexSearchService {
 			}
 
 			// Perform search
-			const results = await this.vectorStore.search(vector, normalizedPrefix, minScore)
+			const results = await this.vectorStore.search(vector, normalizedPrefix, minScore, maxResults)
 			return results
 		} catch (error) {
 			console.error("[CodeIndexSearchService] Error during search:", error)

+ 35 - 11
src/services/code-index/vector-store/__tests__/qdrant-client.spec.ts

@@ -3,7 +3,7 @@ import { createHash } from "crypto"
 
 import { QdrantVectorStore } from "../qdrant-client"
 import { getWorkspacePath } from "../../../../utils/path"
-import { MAX_SEARCH_RESULTS, SEARCH_MIN_SCORE } from "../../constants"
+import { DEFAULT_MAX_SEARCH_RESULTS, DEFAULT_SEARCH_MIN_SCORE } from "../../constants"
 
 // Mocks
 vitest.mock("@qdrant/js-client-rest")
@@ -1005,8 +1005,8 @@ describe("QdrantVectorStore", () => {
 			expect(mockQdrantClientInstance.query).toHaveBeenCalledWith(expectedCollectionName, {
 				query: queryVector,
 				filter: undefined,
-				score_threshold: SEARCH_MIN_SCORE,
-				limit: MAX_SEARCH_RESULTS,
+				score_threshold: DEFAULT_SEARCH_MIN_SCORE,
+				limit: DEFAULT_MAX_SEARCH_RESULTS,
 				params: {
 					hnsw_ef: 128,
 					exact: false,
@@ -1056,8 +1056,8 @@ describe("QdrantVectorStore", () => {
 						},
 					],
 				},
-				score_threshold: SEARCH_MIN_SCORE,
-				limit: MAX_SEARCH_RESULTS,
+				score_threshold: DEFAULT_SEARCH_MIN_SCORE,
+				limit: DEFAULT_MAX_SEARCH_RESULTS,
 				params: {
 					hnsw_ef: 128,
 					exact: false,
@@ -1083,7 +1083,31 @@ describe("QdrantVectorStore", () => {
 				query: queryVector,
 				filter: undefined,
 				score_threshold: customMinScore,
-				limit: MAX_SEARCH_RESULTS,
+				limit: DEFAULT_MAX_SEARCH_RESULTS,
+				params: {
+					hnsw_ef: 128,
+					exact: false,
+				},
+				with_payload: {
+					include: ["filePath", "codeChunk", "startLine", "endLine", "pathSegments"],
+				},
+			})
+		})
+
+		it("should use custom maxResults when provided", async () => {
+			const queryVector = [0.1, 0.2, 0.3]
+			const customMaxResults = 100
+			const mockQdrantResults = { points: [] }
+
+			mockQdrantClientInstance.query.mockResolvedValue(mockQdrantResults)
+
+			await vectorStore.search(queryVector, undefined, undefined, customMaxResults)
+
+			expect(mockQdrantClientInstance.query).toHaveBeenCalledWith(expectedCollectionName, {
+				query: queryVector,
+				filter: undefined,
+				score_threshold: DEFAULT_SEARCH_MIN_SCORE,
+				limit: customMaxResults,
 				params: {
 					hnsw_ef: 128,
 					exact: false,
@@ -1229,8 +1253,8 @@ describe("QdrantVectorStore", () => {
 						},
 					],
 				},
-				score_threshold: SEARCH_MIN_SCORE,
-				limit: MAX_SEARCH_RESULTS,
+				score_threshold: DEFAULT_SEARCH_MIN_SCORE,
+				limit: DEFAULT_MAX_SEARCH_RESULTS,
 				params: {
 					hnsw_ef: 128,
 					exact: false,
@@ -1254,7 +1278,7 @@ describe("QdrantVectorStore", () => {
 			;(console.error as any).mockRestore()
 		})
 
-		it("should use constants MAX_SEARCH_RESULTS and SEARCH_MIN_SCORE correctly", async () => {
+		it("should use constants DEFAULT_MAX_SEARCH_RESULTS and DEFAULT_SEARCH_MIN_SCORE correctly", async () => {
 			const queryVector = [0.1, 0.2, 0.3]
 			const mockQdrantResults = { points: [] }
 
@@ -1263,8 +1287,8 @@ describe("QdrantVectorStore", () => {
 			await vectorStore.search(queryVector)
 
 			const callArgs = mockQdrantClientInstance.query.mock.calls[0][1]
-			expect(callArgs.limit).toBe(MAX_SEARCH_RESULTS)
-			expect(callArgs.score_threshold).toBe(SEARCH_MIN_SCORE)
+			expect(callArgs.limit).toBe(DEFAULT_MAX_SEARCH_RESULTS)
+			expect(callArgs.score_threshold).toBe(DEFAULT_SEARCH_MIN_SCORE)
 		})
 	})
 })

+ 7 - 8
src/services/code-index/vector-store/qdrant-client.ts

@@ -4,7 +4,7 @@ import * as path from "path"
 import { getWorkspacePath } from "../../../utils/path"
 import { IVectorStore } from "../interfaces/vector-store"
 import { Payload, VectorStoreSearchResult } from "../interfaces"
-import { MAX_SEARCH_RESULTS, SEARCH_MIN_SCORE } from "../constants"
+import { DEFAULT_MAX_SEARCH_RESULTS, DEFAULT_SEARCH_MIN_SCORE } from "../constants"
 import { t } from "../../../i18n"
 
 /**
@@ -271,13 +271,16 @@ export class QdrantVectorStore implements IVectorStore {
 	/**
 	 * Searches for similar vectors
 	 * @param queryVector Vector to search for
-	 * @param limit Maximum number of results to return
+	 * @param directoryPrefix Optional directory prefix to filter results
+	 * @param minScore Optional minimum score threshold
+	 * @param maxResults Optional maximum number of results to return
 	 * @returns Promise resolving to search results
 	 */
 	async search(
 		queryVector: number[],
 		directoryPrefix?: string,
 		minScore?: number,
+		maxResults?: number,
 	): Promise<VectorStoreSearchResult[]> {
 		try {
 			let filter = undefined
@@ -296,8 +299,8 @@ export class QdrantVectorStore implements IVectorStore {
 			const searchRequest = {
 				query: queryVector,
 				filter,
-				score_threshold: SEARCH_MIN_SCORE,
-				limit: MAX_SEARCH_RESULTS,
+				score_threshold: minScore ?? DEFAULT_SEARCH_MIN_SCORE,
+				limit: maxResults ?? DEFAULT_MAX_SEARCH_RESULTS,
 				params: {
 					hnsw_ef: 128,
 					exact: false,
@@ -307,10 +310,6 @@ export class QdrantVectorStore implements IVectorStore {
 				},
 			}
 
-			if (minScore !== undefined) {
-				searchRequest.score_threshold = minScore
-			}
-
 			const operationResult = await this.client.query(this.collectionName, searchRequest)
 			const filteredPoints = operationResult.points.filter((p) => this.isPayloadValid(p.payload))
 

+ 1 - 0
src/shared/WebviewMessage.ts

@@ -234,6 +234,7 @@ export interface WebviewMessage {
 		codebaseIndexEmbedderModelId: string
 		codebaseIndexOpenAiCompatibleBaseUrl?: string
 		codebaseIndexOpenAiCompatibleModelDimension?: number
+		codebaseIndexSearchMaxResults?: number
 
 		// Secret settings
 		codeIndexOpenAiKey?: string

+ 67 - 0
webview-ui/src/components/chat/CodeIndexPopover.tsx

@@ -31,10 +31,13 @@ import {
 	Popover,
 	PopoverContent,
 	PopoverTrigger,
+	Slider,
+	StandardTooltip,
 } from "@src/components/ui"
 import { useRooPortal } from "@src/components/ui/hooks/useRooPortal"
 import type { EmbedderProvider } from "@roo/embeddingModels"
 import type { IndexingStatus } from "@roo/ExtensionMessage"
+import { CODEBASE_INDEX_DEFAULTS } from "@roo-code/types"
 
 interface CodeIndexPopoverProps {
 	children: React.ReactNode
@@ -48,6 +51,7 @@ interface LocalCodeIndexSettings {
 	codebaseIndexEmbedderProvider: EmbedderProvider
 	codebaseIndexEmbedderBaseUrl?: string
 	codebaseIndexEmbedderModelId: string
+	codebaseIndexSearchMaxResults?: number
 
 	// Secret settings (start empty, will be loaded separately)
 	codeIndexOpenAiKey?: string
@@ -66,6 +70,7 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
 	const { t } = useAppTranslation()
 	const { codebaseIndexConfig, codebaseIndexModels } = useExtensionState()
 	const [open, setOpen] = useState(false)
+	const [isAdvancedSettingsOpen, setIsAdvancedSettingsOpen] = useState(false)
 
 	const [indexingStatus, setIndexingStatus] = useState<IndexingStatus>(externalIndexingStatus)
 
@@ -79,6 +84,7 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
 		codebaseIndexEmbedderProvider: "openai",
 		codebaseIndexEmbedderBaseUrl: "",
 		codebaseIndexEmbedderModelId: "",
+		codebaseIndexSearchMaxResults: CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_RESULTS,
 		codeIndexOpenAiKey: "",
 		codeIndexQdrantApiKey: "",
 		codebaseIndexOpenAiCompatibleBaseUrl: "",
@@ -107,6 +113,8 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
 				codebaseIndexEmbedderProvider: codebaseIndexConfig.codebaseIndexEmbedderProvider || "openai",
 				codebaseIndexEmbedderBaseUrl: codebaseIndexConfig.codebaseIndexEmbedderBaseUrl || "",
 				codebaseIndexEmbedderModelId: codebaseIndexConfig.codebaseIndexEmbedderModelId || "",
+				codebaseIndexSearchMaxResults:
+					codebaseIndexConfig.codebaseIndexSearchMaxResults || CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_RESULTS,
 				codeIndexOpenAiKey: "",
 				codeIndexQdrantApiKey: "",
 				codebaseIndexOpenAiCompatibleBaseUrl: "",
@@ -575,6 +583,65 @@ export const CodeIndexPopover: React.FC<CodeIndexPopoverProps> = ({
 						/>
 					</div>
 
+					{/* Advanced Settings Disclosure */}
+					<div className="mt-4">
+						<button
+							onClick={() => setIsAdvancedSettingsOpen(!isAdvancedSettingsOpen)}
+							className="flex items-center text-xs text-vscode-foreground hover:text-vscode-textLink-foreground focus:outline-none"
+							aria-expanded={isAdvancedSettingsOpen}>
+							<span
+								className={`codicon codicon-${isAdvancedSettingsOpen ? "chevron-down" : "chevron-right"} mr-1`}></span>
+							<span>{t("settings:codeIndex.advancedConfigLabel")}</span>
+						</button>
+
+						{isAdvancedSettingsOpen && (
+							<div className="mt-4 space-y-4 pl-4">
+								{/* Maximum Search Results Slider */}
+								<div className="space-y-2">
+									<div className="flex items-center gap-2">
+										<label className="text-sm font-medium">
+											{t("settings:codeIndex.searchMaxResultsLabel")}
+										</label>
+										<StandardTooltip content={t("settings:codeIndex.searchMaxResultsDescription")}>
+											<span className="codicon codicon-info text-xs text-vscode-descriptionForeground cursor-help" />
+										</StandardTooltip>
+									</div>
+									<div className="flex items-center gap-2">
+										<Slider
+											min={CODEBASE_INDEX_DEFAULTS.MIN_SEARCH_RESULTS}
+											max={CODEBASE_INDEX_DEFAULTS.MAX_SEARCH_RESULTS}
+											step={CODEBASE_INDEX_DEFAULTS.SEARCH_RESULTS_STEP}
+											value={[
+												currentSettings.codebaseIndexSearchMaxResults ||
+													CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_RESULTS,
+											]}
+											onValueChange={(values) =>
+												updateSetting("codebaseIndexSearchMaxResults", values[0])
+											}
+											className="flex-1"
+											data-testid="search-max-results-slider"
+										/>
+										<span className="w-12 text-center">
+											{currentSettings.codebaseIndexSearchMaxResults ||
+												CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_RESULTS}
+										</span>
+										<VSCodeButton
+											appearance="icon"
+											title={t("settings:codeIndex.resetToDefault")}
+											onClick={() =>
+												updateSetting(
+													"codebaseIndexSearchMaxResults",
+													CODEBASE_INDEX_DEFAULTS.DEFAULT_SEARCH_RESULTS,
+												)
+											}>
+											<span className="codicon codicon-discard" />
+										</VSCodeButton>
+									</div>
+								</div>
+							</div>
+						)}
+					</div>
+
 					{/* Action Buttons */}
 					<div className="flex items-center justify-between gap-2 pt-2">
 						<div className="flex gap-2">

+ 1 - 0
webview-ui/src/context/ExtensionStateContext.tsx

@@ -217,6 +217,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
 			codebaseIndexEmbedderProvider: "openai",
 			codebaseIndexEmbedderBaseUrl: "",
 			codebaseIndexEmbedderModelId: "",
+			codebaseIndexSearchMaxResults: undefined,
 		},
 		codebaseIndexModels: { ollama: {}, openai: {} },
 	})

+ 4 - 1
webview-ui/src/i18n/locales/ca/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "Configuració avançada",
 		"searchMinScoreLabel": "Llindar de puntuació de cerca",
 		"searchMinScoreDescription": "Puntuació mínima de similitud (0.0-1.0) requerida per als resultats de la cerca. Valors més baixos retornen més resultats però poden ser menys rellevants. Valors més alts retornen menys resultats però més rellevants.",
-		"searchMinScoreResetTooltip": "Restablir al valor per defecte (0.4)"
+		"searchMinScoreResetTooltip": "Restablir al valor per defecte (0.4)",
+		"searchMaxResultsLabel": "Màxim de resultats de cerca",
+		"searchMaxResultsDescription": "Nombre màxim de resultats de cerca a retornar quan es consulta l'índex de la base de codi. Els valors més alts proporcionen més context però poden incloure resultats menys rellevants.",
+		"resetToDefault": "Restablir al valor per defecte"
 	},
 	"autoApprove": {
 		"description": "Permet que Roo realitzi operacions automàticament sense requerir aprovació. Activeu aquesta configuració només si confieu plenament en la IA i enteneu els riscos de seguretat associats.",

+ 4 - 1
webview-ui/src/i18n/locales/de/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "Erweiterte Konfiguration",
 		"searchMinScoreLabel": "Suchergebnis-Schwellenwert",
 		"searchMinScoreDescription": "Mindestähnlichkeitswert (0.0-1.0), der für Suchergebnisse erforderlich ist. Niedrigere Werte liefern mehr Ergebnisse, die jedoch möglicherweise weniger relevant sind. Höhere Werte liefern weniger, aber relevantere Ergebnisse.",
-		"searchMinScoreResetTooltip": "Auf Standardwert zurücksetzen (0.4)"
+		"searchMinScoreResetTooltip": "Auf Standardwert zurücksetzen (0.4)",
+		"searchMaxResultsLabel": "Maximale Suchergebnisse",
+		"searchMaxResultsDescription": "Maximale Anzahl von Suchergebnissen, die bei der Abfrage des Codebase-Index zurückgegeben werden. Höhere Werte bieten mehr Kontext, können aber weniger relevante Ergebnisse enthalten.",
+		"resetToDefault": "Auf Standard zurücksetzen"
 	},
 	"autoApprove": {
 		"description": "Erlaubt Roo, Operationen automatisch ohne Genehmigung durchzuführen. Aktiviere diese Einstellungen nur, wenn du der KI vollständig vertraust und die damit verbundenen Sicherheitsrisiken verstehst.",

+ 3 - 0
webview-ui/src/i18n/locales/en/settings.json

@@ -76,6 +76,9 @@
 		"searchMinScoreLabel": "Search Score Threshold",
 		"searchMinScoreDescription": "Minimum similarity score (0.0-1.0) required for search results. Lower values return more results but may be less relevant. Higher values return fewer but more relevant results.",
 		"searchMinScoreResetTooltip": "Reset to default value (0.4)",
+		"searchMaxResultsLabel": "Maximum Search Results",
+		"searchMaxResultsDescription": "Maximum number of search results to return when querying the codebase index. Higher values provide more context but may include less relevant results.",
+		"resetToDefault": "Reset to default",
 		"startIndexingButton": "Start Indexing",
 		"clearIndexDataButton": "Clear Index Data",
 		"unsavedSettingsMessage": "Please save your settings before starting the indexing process.",

+ 4 - 1
webview-ui/src/i18n/locales/es/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "Configuración avanzada",
 		"searchMinScoreLabel": "Umbral de puntuación de búsqueda",
 		"searchMinScoreDescription": "Puntuación mínima de similitud (0.0-1.0) requerida para los resultados de búsqueda. Valores más bajos devuelven más resultados pero pueden ser menos relevantes. Valores más altos devuelven menos resultados pero más relevantes.",
-		"searchMinScoreResetTooltip": "Restablecer al valor predeterminado (0.4)"
+		"searchMinScoreResetTooltip": "Restablecer al valor predeterminado (0.4)",
+		"searchMaxResultsLabel": "Resultados máximos de búsqueda",
+		"searchMaxResultsDescription": "Número máximo de resultados de búsqueda a devolver al consultar el índice de código. Valores más altos proporcionan más contexto pero pueden incluir resultados menos relevantes.",
+		"resetToDefault": "Restablecer al valor predeterminado"
 	},
 	"autoApprove": {
 		"description": "Permitir que Roo realice operaciones automáticamente sin requerir aprobación. Habilite esta configuración solo si confía plenamente en la IA y comprende los riesgos de seguridad asociados.",

+ 4 - 1
webview-ui/src/i18n/locales/fr/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "Configuration avancée",
 		"searchMinScoreLabel": "Seuil de score de recherche",
 		"searchMinScoreDescription": "Score de similarité minimum (0.0-1.0) requis pour les résultats de recherche. Des valeurs plus faibles renvoient plus de résultats mais peuvent être moins pertinents. Des valeurs plus élevées renvoient moins de résultats mais plus pertinents.",
-		"searchMinScoreResetTooltip": "Réinitialiser à la valeur par défaut (0.4)"
+		"searchMinScoreResetTooltip": "Réinitialiser à la valeur par défaut (0.4)",
+		"searchMaxResultsLabel": "Résultats de recherche maximum",
+		"searchMaxResultsDescription": "Nombre maximum de résultats de recherche à retourner lors de l'interrogation de l'index de code. Des valeurs plus élevées fournissent plus de contexte mais peuvent inclure des résultats moins pertinents.",
+		"resetToDefault": "Réinitialiser par défaut"
 	},
 	"autoApprove": {
 		"description": "Permettre à Roo d'effectuer automatiquement des opérations sans requérir d'approbation. Activez ces paramètres uniquement si vous faites entièrement confiance à l'IA et que vous comprenez les risques de sécurité associés.",

+ 4 - 1
webview-ui/src/i18n/locales/hi/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "उन्नत कॉन्फ़िगरेशन",
 		"searchMinScoreLabel": "खोज स्कोर थ्रेसहोल्ड",
 		"searchMinScoreDescription": "खोज परिणामों के लिए आवश्यक न्यूनतम समानता स्कोर (0.0-1.0)। कम मान अधिक परिणाम लौटाते हैं लेकिन कम प्रासंगिक हो सकते हैं। उच्च मान कम लेकिन अधिक प्रासंगिक परिणाम लौटाते हैं।",
-		"searchMinScoreResetTooltip": "डिफ़ॉल्ट मान पर रीसेट करें (0.4)"
+		"searchMinScoreResetTooltip": "डिफ़ॉल्ट मान पर रीसेट करें (0.4)",
+		"searchMaxResultsLabel": "अधिकतम खोज परिणाम",
+		"searchMaxResultsDescription": "कोडबेस इंडेक्स को क्वेरी करते समय वापस करने के लिए खोज परिणामों की अधिकतम संख्या। उच्च मान अधिक संदर्भ प्रदान करते हैं लेकिन कम प्रासंगिक परिणाम शामिल कर सकते हैं।",
+		"resetToDefault": "डिफ़ॉल्ट पर रीसेट करें"
 	},
 	"autoApprove": {
 		"description": "Roo को अनुमोदन की आवश्यकता के बिना स्वचालित रूप से ऑपरेशन करने की अनुमति दें। इन सेटिंग्स को केवल तभी सक्षम करें जब आप AI पर पूरी तरह से भरोसा करते हों और संबंधित सुरक्षा जोखिमों को समझते हों।",

+ 4 - 1
webview-ui/src/i18n/locales/id/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "Konfigurasi Lanjutan",
 		"searchMinScoreLabel": "Ambang Batas Skor Pencarian",
 		"searchMinScoreDescription": "Skor kesamaan minimum (0.0-1.0) yang diperlukan untuk hasil pencarian. Nilai yang lebih rendah mengembalikan lebih banyak hasil tetapi mungkin kurang relevan. Nilai yang lebih tinggi mengembalikan lebih sedikit hasil tetapi lebih relevan.",
-		"searchMinScoreResetTooltip": "Reset ke nilai default (0.4)"
+		"searchMinScoreResetTooltip": "Reset ke nilai default (0.4)",
+		"searchMaxResultsLabel": "Hasil Pencarian Maksimum",
+		"searchMaxResultsDescription": "Jumlah maksimum hasil pencarian yang dikembalikan saat melakukan query indeks basis kode. Nilai yang lebih tinggi memberikan lebih banyak konteks tetapi mungkin menyertakan hasil yang kurang relevan.",
+		"resetToDefault": "Reset ke default"
 	},
 	"autoApprove": {
 		"description": "Izinkan Roo untuk secara otomatis melakukan operasi tanpa memerlukan persetujuan. Aktifkan pengaturan ini hanya jika kamu sepenuhnya mempercayai AI dan memahami risiko keamanan yang terkait.",

+ 4 - 1
webview-ui/src/i18n/locales/it/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "Configurazione avanzata",
 		"searchMinScoreLabel": "Soglia punteggio di ricerca",
 		"searchMinScoreDescription": "Punteggio minimo di somiglianza (0.0-1.0) richiesto per i risultati della ricerca. Valori più bassi restituiscono più risultati ma potrebbero essere meno pertinenti. Valori più alti restituiscono meno risultati ma più pertinenti.",
-		"searchMinScoreResetTooltip": "Ripristina al valore predefinito (0.4)"
+		"searchMinScoreResetTooltip": "Ripristina al valore predefinito (0.4)",
+		"searchMaxResultsLabel": "Risultati di ricerca massimi",
+		"searchMaxResultsDescription": "Numero massimo di risultati di ricerca da restituire quando si interroga l'indice del codice. Valori più alti forniscono più contesto ma possono includere risultati meno pertinenti.",
+		"resetToDefault": "Ripristina al valore predefinito"
 	},
 	"autoApprove": {
 		"description": "Permetti a Roo di eseguire automaticamente operazioni senza richiedere approvazione. Abilita queste impostazioni solo se ti fidi completamente dell'IA e comprendi i rischi di sicurezza associati.",

+ 4 - 1
webview-ui/src/i18n/locales/ja/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "詳細設定",
 		"searchMinScoreLabel": "検索スコアのしきい値",
 		"searchMinScoreDescription": "検索結果に必要な最小類似度スコア(0.0-1.0)。値を低くするとより多くの結果が返されますが、関連性が低くなる可能性があります。値を高くすると返される結果は少なくなりますが、より関連性が高くなります。",
-		"searchMinScoreResetTooltip": "デフォルト値(0.4)にリセット"
+		"searchMinScoreResetTooltip": "デフォルト値(0.4)にリセット",
+		"searchMaxResultsLabel": "最大検索結果数",
+		"searchMaxResultsDescription": "コードベースインデックスをクエリする際に返される検索結果の最大数。値を高くするとより多くのコンテキストが提供されますが、関連性の低い結果が含まれる可能性があります。",
+		"resetToDefault": "デフォルトにリセット"
 	},
 	"autoApprove": {
 		"description": "Rooが承認なしで自動的に操作を実行できるようにします。AIを完全に信頼し、関連するセキュリティリスクを理解している場合にのみ、これらの設定を有効にしてください。",

+ 4 - 1
webview-ui/src/i18n/locales/ko/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "고급 구성",
 		"searchMinScoreLabel": "검색 점수 임계값",
 		"searchMinScoreDescription": "검색 결과에 필요한 최소 유사도 점수(0.0-1.0). 값이 낮을수록 더 많은 결과가 반환되지만 관련성이 떨어질 수 있습니다. 값이 높을수록 결과는 적지만 관련성이 높은 결과가 반환됩니다.",
-		"searchMinScoreResetTooltip": "기본값(0.4)으로 재설정"
+		"searchMinScoreResetTooltip": "기본값(0.4)으로 재설정",
+		"searchMaxResultsLabel": "최대 검색 결과",
+		"searchMaxResultsDescription": "코드베이스 인덱스를 쿼리할 때 반환할 최대 검색 결과 수입니다. 값이 높을수록 더 많은 컨텍스트를 제공하지만 관련성이 낮은 결과가 포함될 수 있습니다.",
+		"resetToDefault": "기본값으로 재설정"
 	},
 	"autoApprove": {
 		"description": "Roo가 승인 없이 자동으로 작업을 수행할 수 있도록 허용합니다. AI를 완전히 신뢰하고 관련 보안 위험을 이해하는 경우에만 이러한 설정을 활성화하세요.",

+ 4 - 1
webview-ui/src/i18n/locales/nl/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "Geavanceerde configuratie",
 		"searchMinScoreLabel": "Zoekscore drempel",
 		"searchMinScoreDescription": "Minimale overeenkomstscore (0.0-1.0) vereist voor zoekresultaten. Lagere waarden leveren meer resultaten op, maar zijn mogelijk minder relevant. Hogere waarden leveren minder, maar relevantere resultaten op.",
-		"searchMinScoreResetTooltip": "Reset naar standaardwaarde (0.4)"
+		"searchMinScoreResetTooltip": "Reset naar standaardwaarde (0.4)",
+		"searchMaxResultsLabel": "Maximum Zoekresultaten",
+		"searchMaxResultsDescription": "Maximum aantal zoekresultaten dat wordt geretourneerd bij het doorzoeken van de codebase-index. Hogere waarden bieden meer context maar kunnen minder relevante resultaten bevatten.",
+		"resetToDefault": "Reset naar standaard"
 	},
 	"autoApprove": {
 		"description": "Sta Roo toe om automatisch handelingen uit te voeren zonder goedkeuring. Schakel deze instellingen alleen in als je de AI volledig vertrouwt en de bijbehorende beveiligingsrisico's begrijpt.",

+ 4 - 1
webview-ui/src/i18n/locales/pl/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "Konfiguracja zaawansowana",
 		"searchMinScoreLabel": "Próg wyniku wyszukiwania",
 		"searchMinScoreDescription": "Minimalny wynik podobieństwa (0.0-1.0) wymagany dla wyników wyszukiwania. Niższe wartości zwracają więcej wyników, ale mogą być mniej trafne. Wyższe wartości zwracają mniej wyników, ale bardziej trafnych.",
-		"searchMinScoreResetTooltip": "Zresetuj do wartości domyślnej (0.4)"
+		"searchMinScoreResetTooltip": "Zresetuj do wartości domyślnej (0.4)",
+		"searchMaxResultsLabel": "Maksymalna liczba wyników wyszukiwania",
+		"searchMaxResultsDescription": "Maksymalna liczba wyników wyszukiwania zwracanych podczas zapytania do indeksu bazy kodu. Wyższe wartości zapewniają więcej kontekstu, ale mogą zawierać mniej istotne wyniki.",
+		"resetToDefault": "Przywróć domyślne"
 	},
 	"autoApprove": {
 		"description": "Pozwól Roo na automatyczne wykonywanie operacji bez wymagania zatwierdzenia. Włącz te ustawienia tylko jeśli w pełni ufasz AI i rozumiesz związane z tym zagrożenia bezpieczeństwa.",

+ 4 - 1
webview-ui/src/i18n/locales/pt-BR/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "Configuração Avançada",
 		"searchMinScoreLabel": "Limite de pontuação de busca",
 		"searchMinScoreDescription": "Pontuação mínima de similaridade (0.0-1.0) necessária para os resultados da busca. Valores mais baixos retornam mais resultados, mas podem ser menos relevantes. Valores mais altos retornam menos resultados, mas mais relevantes.",
-		"searchMinScoreResetTooltip": "Redefinir para o valor padrão (0.4)"
+		"searchMinScoreResetTooltip": "Redefinir para o valor padrão (0.4)",
+		"searchMaxResultsLabel": "Resultados máximos de busca",
+		"searchMaxResultsDescription": "Número máximo de resultados de busca a retornar ao consultar o índice de código. Valores mais altos fornecem mais contexto, mas podem incluir resultados menos relevantes.",
+		"resetToDefault": "Redefinir para o padrão"
 	},
 	"autoApprove": {
 		"description": "Permitir que o Roo realize operações automaticamente sem exigir aprovação. Ative essas configurações apenas se confiar totalmente na IA e compreender os riscos de segurança associados.",

+ 4 - 1
webview-ui/src/i18n/locales/ru/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "Расширенная конфигурация",
 		"searchMinScoreLabel": "Порог оценки поиска",
 		"searchMinScoreDescription": "Минимальный балл сходства (0.0-1.0), необходимый для результатов поиска. Более низкие значения возвращают больше результатов, но они могут быть менее релевантными. Более высокие значения возвращают меньше результатов, но более релевантных.",
-		"searchMinScoreResetTooltip": "Сбросить к значению по умолчанию (0.4)"
+		"searchMinScoreResetTooltip": "Сбросить к значению по умолчанию (0.4)",
+		"searchMaxResultsLabel": "Максимальное количество результатов поиска",
+		"searchMaxResultsDescription": "Максимальное количество результатов поиска, возвращаемых при запросе индекса кодовой базы. Более высокие значения предоставляют больше контекста, но могут включать менее релевантные результаты.",
+		"resetToDefault": "Сбросить к значению по умолчанию"
 	},
 	"autoApprove": {
 		"description": "Разрешить Roo автоматически выполнять операции без необходимости одобрения. Включайте эти параметры только если полностью доверяете ИИ и понимаете связанные с этим риски безопасности.",

+ 4 - 1
webview-ui/src/i18n/locales/tr/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "Gelişmiş Yapılandırma",
 		"searchMinScoreLabel": "Arama Skoru Eşiği",
 		"searchMinScoreDescription": "Arama sonuçları için gereken minimum benzerlik puanı (0.0-1.0). Düşük değerler daha fazla sonuç döndürür ancak daha az alakalı olabilir. Yüksek değerler daha az ancak daha alakalı sonuçlar döndürür.",
-		"searchMinScoreResetTooltip": "Varsayılan değere sıfırla (0.4)"
+		"searchMinScoreResetTooltip": "Varsayılan değere sıfırla (0.4)",
+		"searchMaxResultsLabel": "Maksimum Arama Sonuçları",
+		"searchMaxResultsDescription": "Kod tabanı dizinini sorgularken döndürülecek maksimum arama sonucu sayısı. Daha yüksek değerler daha fazla bağlam sağlar ancak daha az alakalı sonuçlar içerebilir.",
+		"resetToDefault": "Varsayılana sıfırla"
 	},
 	"autoApprove": {
 		"description": "Roo'nun onay gerektirmeden otomatik olarak işlemler gerçekleştirmesine izin verin. Bu ayarları yalnızca yapay zekaya tamamen güveniyorsanız ve ilgili güvenlik risklerini anlıyorsanız etkinleştirin.",

+ 4 - 1
webview-ui/src/i18n/locales/vi/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "Cấu hình nâng cao",
 		"searchMinScoreLabel": "Ngưỡng điểm tìm kiếm",
 		"searchMinScoreDescription": "Điểm tương đồng tối thiểu (0.0-1.0) cần thiết cho kết quả tìm kiếm. Giá trị thấp hơn trả về nhiều kết quả hơn nhưng có thể kém liên quan hơn. Giá trị cao hơn trả về ít kết quả hơn nhưng có liên quan hơn.",
-		"searchMinScoreResetTooltip": "Đặt lại về giá trị mặc định (0.4)"
+		"searchMinScoreResetTooltip": "Đặt lại về giá trị mặc định (0.4)",
+		"searchMaxResultsLabel": "Số Kết Quả Tìm Kiếm Tối Đa",
+		"searchMaxResultsDescription": "Số lượng kết quả tìm kiếm tối đa được trả về khi truy vấn chỉ mục cơ sở mã. Giá trị cao hơn cung cấp nhiều ngữ cảnh hơn nhưng có thể bao gồm các kết quả ít liên quan hơn.",
+		"resetToDefault": "Đặt lại về mặc định"
 	},
 	"autoApprove": {
 		"description": "Cho phép Roo tự động thực hiện các hoạt động mà không cần phê duyệt. Chỉ bật những cài đặt này nếu bạn hoàn toàn tin tưởng AI và hiểu rõ các rủi ro bảo mật liên quan.",

+ 4 - 1
webview-ui/src/i18n/locales/zh-CN/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "高级配置",
 		"searchMinScoreLabel": "搜索分数阈值",
 		"searchMinScoreDescription": "搜索结果所需的最低相似度分数(0.0-1.0)。较低的值返回更多结果,但可能不太相关。较高的值返回较少但更相关的结果。",
-		"searchMinScoreResetTooltip": "恢复默认值 (0.4)"
+		"searchMinScoreResetTooltip": "恢复默认值 (0.4)",
+		"searchMaxResultsLabel": "最大搜索结果数",
+		"searchMaxResultsDescription": "查询代码库索引时返回的最大搜索结果数。较高的值提供更多上下文,但可能包含相关性较低的结果。",
+		"resetToDefault": "恢复默认值"
 	},
 	"autoApprove": {
 		"description": "允许 Roo 自动执行操作而无需批准。只有在您完全信任 AI 并了解相关安全风险的情况下才启用这些设置。",

+ 4 - 1
webview-ui/src/i18n/locales/zh-TW/settings.json

@@ -100,7 +100,10 @@
 		"advancedConfigLabel": "進階設定",
 		"searchMinScoreLabel": "搜尋分數閾值",
 		"searchMinScoreDescription": "搜尋結果所需的最低相似度分數(0.0-1.0)。較低的值會傳回更多結果,但可能較不相關。較高的值會傳回較少但更相關的結果。",
-		"searchMinScoreResetTooltip": "重設為預設值 (0.4)"
+		"searchMinScoreResetTooltip": "重設為預設值 (0.4)",
+		"searchMaxResultsLabel": "最大搜尋結果數",
+		"searchMaxResultsDescription": "查詢程式碼庫索引時傳回的最大搜尋結果數。較高的值提供更多上下文,但可能包含相關性較低的結果。",
+		"resetToDefault": "重設為預設值"
 	},
 	"autoApprove": {
 		"description": "允許 Roo 無需核准即執行操作。僅在您完全信任 AI 並了解相關安全風險時啟用這些設定。",