diff --git a/apps/cli/src/ui/components/ChatHistoryItem.tsx b/apps/cli/src/ui/components/ChatHistoryItem.tsx index c51b0faddbc..227c6e077f2 100644 --- a/apps/cli/src/ui/components/ChatHistoryItem.tsx +++ b/apps/cli/src/ui/components/ChatHistoryItem.tsx @@ -15,7 +15,7 @@ type ToolCategory = "file" | "directory" | "search" | "command" | "browser" | "m function getToolCategory(toolName: string): ToolCategory { const fileTools = ["readFile", "read_file", "writeToFile", "write_to_file", "applyDiff", "apply_diff"] const dirTools = ["listFiles", "list_files", "listFilesRecursive", "listFilesTopLevel"] - const searchTools = ["searchFiles", "search_files"] + const searchTools = ["searchFiles", "search_files", "webSearch", "web_search"] const commandTools = ["executeCommand", "execute_command"] const browserTools = ["browserAction", "browser_action"] const modeTools = ["switchMode", "switch_mode", "newTask", "new_task"] diff --git a/apps/cli/src/ui/components/tools/types.ts b/apps/cli/src/ui/components/tools/types.ts index 28a1b5faa02..38fecb381fa 100644 --- a/apps/cli/src/ui/components/tools/types.ts +++ b/apps/cli/src/ui/components/tools/types.ts @@ -35,7 +35,7 @@ export function getToolCategory(toolName: string): ToolCategory { "writeToFile", ] - const searchTools = ["searchFiles", "search_files", "codebaseSearch", "codebase_search"] + const searchTools = ["searchFiles", "search_files", "codebaseSearch", "codebase_search", "webSearch", "web_search"] const commandTools = ["execute_command", "executeCommand"] const browserTools = ["browser_action", "browserAction"] const modeTools = ["switchMode", "switch_mode", "newTask", "new_task", "finishTask"] diff --git a/apps/cli/src/ui/components/tools/utils.ts b/apps/cli/src/ui/components/tools/utils.ts index 5eaee33b127..bb92a04a130 100644 --- a/apps/cli/src/ui/components/tools/utils.ts +++ b/apps/cli/src/ui/components/tools/utils.ts @@ -69,6 +69,8 @@ export function getToolDisplayName(toolName: string): string { search_files: "Search Files", codebaseSearch: "Codebase Search", codebase_search: "Codebase Search", + webSearch: "Web Search", + web_search: "Web Search", // Command operations execute_command: "Execute Command", @@ -126,6 +128,8 @@ export function getToolIconName(toolName: string): IconName { search_files: "search", codebaseSearch: "search", codebase_search: "search", + webSearch: "search", + web_search: "search", // Command operations execute_command: "terminal", diff --git a/packages/types/src/tool.ts b/packages/types/src/tool.ts index 76e03f8c803..5c542cf518d 100644 --- a/packages/types/src/tool.ts +++ b/packages/types/src/tool.ts @@ -26,6 +26,7 @@ export const toolNames = [ "search_files", "list_files", "browser_action", + "web_search", "use_mcp_tool", "access_mcp_resource", "ask_followup_question", diff --git a/packages/types/src/vscode-extension-host.ts b/packages/types/src/vscode-extension-host.ts index c0bb8726d7d..176005ebd09 100644 --- a/packages/types/src/vscode-extension-host.ts +++ b/packages/types/src/vscode-extension-host.ts @@ -676,6 +676,7 @@ export interface ClineSayTool { | "listFilesTopLevel" | "listFilesRecursive" | "searchFiles" + | "webSearch" | "switchMode" | "newTask" | "finishTask" diff --git a/src/core/assistant-message/presentAssistantMessage.ts b/src/core/assistant-message/presentAssistantMessage.ts index 693327a022e..af506575a61 100644 --- a/src/core/assistant-message/presentAssistantMessage.ts +++ b/src/core/assistant-message/presentAssistantMessage.ts @@ -40,6 +40,7 @@ import { generateImageTool } from "../tools/GenerateImageTool" import { applyDiffTool as applyDiffToolClass } from "../tools/ApplyDiffTool" import { validateToolUse } from "../tools/validateToolUse" import { codebaseSearchTool } from "../tools/CodebaseSearchTool" +import { webSearchTool } from "../tools/WebSearchTool" import { formatResponse } from "../prompts/responses" @@ -1016,6 +1017,15 @@ export async function presentAssistantMessage(cline: Task) { toolProtocol, }) break + case "web_search": + await webSearchTool.handle(cline, block as ToolUse<"web_search">, { + askApproval, + handleError, + pushToolResult, + removeClosingTag, + toolProtocol, + }) + break case "browser_action": await browserActionTool( cline, diff --git a/src/core/auto-approval/tools.ts b/src/core/auto-approval/tools.ts index a43f0cd994e..3e952d0c73d 100644 --- a/src/core/auto-approval/tools.ts +++ b/src/core/auto-approval/tools.ts @@ -12,6 +12,7 @@ export function isReadOnlyToolAction(tool: ClineSayTool): boolean { "listFilesRecursive", "searchFiles", "codebaseSearch", + "webSearch", "runSlashCommand", ].includes(tool.tool) } diff --git a/src/core/prompts/tools/filter-tools-for-mode.ts b/src/core/prompts/tools/filter-tools-for-mode.ts index f296c1b5c50..6dfe2f07e29 100644 --- a/src/core/prompts/tools/filter-tools-for-mode.ts +++ b/src/core/prompts/tools/filter-tools-for-mode.ts @@ -294,6 +294,7 @@ export function filterNativeToolsForMode( // Conditionally exclude browser_action if disabled in settings if (settings?.browserToolEnabled === false) { allowedToolNames.delete("browser_action") + allowedToolNames.delete("web_search") } // Conditionally exclude apply_diff if diffs are disabled @@ -383,7 +384,7 @@ export function isToolAllowedInMode( } // Check for browser_action being disabled by user settings - if (toolName === "browser_action" && settings?.browserToolEnabled === false) { + if ((toolName === "browser_action" || toolName === "web_search") && settings?.browserToolEnabled === false) { return false } diff --git a/src/core/prompts/tools/index.ts b/src/core/prompts/tools/index.ts index b75725a99b3..e9b37570946 100644 --- a/src/core/prompts/tools/index.ts +++ b/src/core/prompts/tools/index.ts @@ -23,6 +23,7 @@ import { getAccessMcpResourceDescription } from "./access-mcp-resource" import { getSwitchModeDescription } from "./switch-mode" import { getNewTaskDescription } from "./new-task" import { getCodebaseSearchDescription } from "./codebase-search" +import { getWebSearchDescription } from "./web-search" import { getUpdateTodoListDescription } from "./update-todo-list" import { getRunSlashCommandDescription } from "./run-slash-command" import { getGenerateImageDescription } from "./generate-image" @@ -36,6 +37,7 @@ const toolDescriptionMap: Record string | undefined> search_files: (args) => getSearchFilesDescription(args), list_files: (args) => getListFilesDescription(args), browser_action: (args) => getBrowserActionDescription(args), + web_search: () => getWebSearchDescription(), ask_followup_question: () => getAskFollowupQuestionDescription(), attempt_completion: (args) => getAttemptCompletionDescription(args), use_mcp_tool: (args) => getUseMcpToolDescription(args), @@ -131,6 +133,11 @@ export function getToolDescriptionsForMode( tools.delete("run_slash_command") } + // Conditionally exclude web_search if browser tools are disabled in settings + if (settings?.browserToolEnabled === false) { + tools.delete("web_search") + } + // Map tool descriptions for allowed tools const descriptions = Array.from(tools).map((toolName) => { const descriptionFn = toolDescriptionMap[toolName] @@ -164,6 +171,7 @@ export { getAccessMcpResourceDescription, getSwitchModeDescription, getCodebaseSearchDescription, + getWebSearchDescription, getRunSlashCommandDescription, getGenerateImageDescription, } diff --git a/src/core/prompts/tools/native-tools/index.ts b/src/core/prompts/tools/native-tools/index.ts index 4f78729cdc8..b64d6e872ff 100644 --- a/src/core/prompts/tools/native-tools/index.ts +++ b/src/core/prompts/tools/native-tools/index.ts @@ -19,6 +19,7 @@ import edit_file from "./edit_file" import searchFiles from "./search_files" import switchMode from "./switch_mode" import updateTodoList from "./update_todo_list" +import webSearch from "./web_search" import writeToFile from "./write_to_file" export { getMcpServerTools } from "./mcp_server" @@ -73,6 +74,7 @@ export function getNativeTools(options: NativeToolsOptions = {}): OpenAI.Chat.Ch searchFiles, switchMode, updateTodoList, + webSearch, writeToFile, ] satisfies OpenAI.Chat.ChatCompletionTool[] } diff --git a/src/core/prompts/tools/native-tools/web_search.ts b/src/core/prompts/tools/native-tools/web_search.ts new file mode 100644 index 00000000000..7c6f61901d9 --- /dev/null +++ b/src/core/prompts/tools/native-tools/web_search.ts @@ -0,0 +1,38 @@ +import type OpenAI from "openai" + +const WEB_SEARCH_DESCRIPTION = `Search the public web for up-to-date information and return a concise list of results with titles, URLs, and snippets. Use this tool when you need real-time or external context that is not available in the local workspace. + +Parameters: +- query: (required) The search query to run. +- max_results: (optional) Maximum number of results to return (default: 5, max: 10). + +Example: Searching for release notes +{ "query": "Cline 3.48.0 web search tool", "max_results": 5 }` + +const QUERY_PARAMETER_DESCRIPTION = `Search query string` + +const MAX_RESULTS_PARAMETER_DESCRIPTION = `Optional cap on number of results (1-10)` + +export default { + type: "function", + function: { + name: "web_search", + description: WEB_SEARCH_DESCRIPTION, + strict: true, + parameters: { + type: "object", + properties: { + query: { + type: "string", + description: QUERY_PARAMETER_DESCRIPTION, + }, + max_results: { + type: ["integer", "null"], + description: MAX_RESULTS_PARAMETER_DESCRIPTION, + }, + }, + required: ["query", "max_results"], + additionalProperties: false, + }, + }, +} satisfies OpenAI.Chat.ChatCompletionTool diff --git a/src/core/prompts/tools/web-search.ts b/src/core/prompts/tools/web-search.ts new file mode 100644 index 00000000000..3c34c98b93c --- /dev/null +++ b/src/core/prompts/tools/web-search.ts @@ -0,0 +1,20 @@ +export function getWebSearchDescription(): string { + return `## web_search +Description: Search the public web for up-to-date information and return a concise list of results with titles, URLs, and snippets. Use this tool when you need real-time or external context that is not available in the local workspace. + +Parameters: +- query: (required) The search query to run. +- max_results: (optional) Maximum number of results to return (default: 5, max: 10). + +Usage: + +Your search query +5 + + +Example: + +OpenAI Responses API web search tool +3 +` +} diff --git a/src/core/tools/WebSearchTool.ts b/src/core/tools/WebSearchTool.ts new file mode 100644 index 00000000000..a338b98a185 --- /dev/null +++ b/src/core/tools/WebSearchTool.ts @@ -0,0 +1,195 @@ +import { type ClineSayTool } from "@roo-code/types" + +import { Task } from "../task/Task" +import { formatResponse } from "../prompts/responses" +import type { ToolUse } from "../../shared/tools" + +import { BaseTool, ToolCallbacks } from "./BaseTool" + +interface WebSearchParams { + query: string + max_results?: number | null +} + +type WebSearchResult = { + title: string + url: string + snippet?: string +} + +const DEFAULT_MAX_RESULTS = 5 +const MAX_RESULTS_LIMIT = 10 +const WEB_SEARCH_TIMEOUT_MS = 15000 + +function normalizeMaxResults(value?: number | null): number { + if (!value || Number.isNaN(value)) { + return DEFAULT_MAX_RESULTS + } + return Math.min(Math.max(Math.trunc(value), 1), MAX_RESULTS_LIMIT) +} + +function formatWebSearchResults(query: string, results: WebSearchResult[]): string { + if (results.length === 0) { + return `No web results found for "${query}".` + } + + const lines = results.map((result, index) => { + const header = `${index + 1}. ${result.title}` + const snippet = result.snippet ? `\n${result.snippet}` : "" + return `${header}\n${result.url}${snippet}` + }) + + return `Web search results for "${query}":\n\n${lines.join("\n\n")}` +} + +function splitTextSnippet(text?: string): { title: string; snippet?: string } { + if (!text) { + return { title: "Untitled result" } + } + + const [title, ...rest] = text.split(" - ") + const snippet = rest.length > 0 ? rest.join(" - ") : undefined + return { title: title.trim() || "Untitled result", snippet: snippet?.trim() || undefined } +} + +function extractResults(payload: any, maxResults: number): WebSearchResult[] { + const results: WebSearchResult[] = [] + + if (payload?.AbstractURL && payload?.AbstractText) { + results.push({ + title: payload.Heading || payload.AbstractText, + url: payload.AbstractURL, + snippet: payload.AbstractText, + }) + } + + const directResults: any[] = Array.isArray(payload?.Results) ? payload.Results : [] + for (const result of directResults) { + if (!result?.FirstURL || !result?.Text) { + continue + } + const { title, snippet } = splitTextSnippet(result.Text) + results.push({ + title, + url: result.FirstURL, + snippet, + }) + } + + const relatedTopics: any[] = Array.isArray(payload?.RelatedTopics) ? payload.RelatedTopics : [] + const queue = [...relatedTopics] + while (queue.length > 0) { + const topic = queue.shift() + if (!topic) { + continue + } + if (Array.isArray(topic.Topics)) { + queue.push(...topic.Topics) + continue + } + if (!topic.FirstURL || !topic.Text) { + continue + } + const { title, snippet } = splitTextSnippet(topic.Text) + results.push({ + title, + url: topic.FirstURL, + snippet, + }) + } + + return results.slice(0, maxResults) +} + +export class WebSearchTool extends BaseTool<"web_search"> { + readonly name = "web_search" as const + + parseLegacy(params: Partial>): WebSearchParams { + const maxResults = params.max_results ? Number.parseInt(params.max_results, 10) : undefined + + return { + query: params.query || "", + max_results: Number.isNaN(maxResults) ? undefined : maxResults, + } + } + + async execute(params: WebSearchParams, task: Task, callbacks: ToolCallbacks): Promise { + const { askApproval, handleError, pushToolResult, toolProtocol } = callbacks + const query = params.query + + if (!query) { + task.consecutiveMistakeCount++ + task.recordToolError("web_search") + task.didToolFailInCurrentTurn = true + pushToolResult(await task.sayAndCreateMissingParamError("web_search", "query")) + return + } + + const maxResults = normalizeMaxResults(params.max_results) + + try { + const controller = new AbortController() + const timeoutId = setTimeout(() => controller.abort(), WEB_SEARCH_TIMEOUT_MS) + try { + const url = new URL("https://api.duckduckgo.com/") + url.searchParams.set("q", query) + url.searchParams.set("format", "json") + url.searchParams.set("no_html", "1") + url.searchParams.set("skip_disambig", "1") + + const response = await fetch(url.toString(), { + signal: controller.signal, + headers: { + "User-Agent": "RooCode-WebSearch", + }, + }) + + if (!response.ok) { + throw new Error(`Web search request failed with status ${response.status}`) + } + + const payload = await response.json() + const results = extractResults(payload, maxResults) + const displayContent = formatWebSearchResults(query, results) + + const sharedMessageProps: ClineSayTool = { + tool: "webSearch", + query, + content: displayContent, + } + + const didApprove = await askApproval("tool", JSON.stringify(sharedMessageProps)) + if (!didApprove) { + pushToolResult(formatResponse.toolDenied(toolProtocol)) + return + } + + task.consecutiveMistakeCount = 0 + pushToolResult(JSON.stringify({ query, source: "duckduckgo", results }, null, 2)) + } finally { + clearTimeout(timeoutId) + } + } catch (error) { + await handleError("web_search", error as Error) + } + } + + override async handlePartial(task: Task, block: ToolUse<"web_search">): Promise { + const query = block.params.query + const maxResults = block.params.max_results + + const sharedMessageProps: ClineSayTool = { + tool: "webSearch", + query: this.removeClosingTag("query", query, block.partial), + content: "", + } + + if (maxResults) { + sharedMessageProps.content = `Results requested: ${this.removeClosingTag("max_results", maxResults, block.partial)}` + } + + await task.ask("tool", JSON.stringify(sharedMessageProps), block.partial).catch(() => {}) + } +} + +export const webSearchTool = new WebSearchTool() diff --git a/src/shared/tools.ts b/src/shared/tools.ts index f893a3d332e..499615fd585 100644 --- a/src/shared/tools.ts +++ b/src/shared/tools.ts @@ -63,6 +63,7 @@ export const toolParamNames = [ "task", "size", "query", + "max_results", "args", "start_line", "end_line", @@ -102,6 +103,7 @@ export type NativeToolArgs = { } browser_action: BrowserActionParams codebase_search: { query: string; path?: string } + web_search: { query: string; max_results?: number } fetch_instructions: { task: string } generate_image: GenerateImageParams run_slash_command: { command: string; args?: string } @@ -196,6 +198,11 @@ export interface BrowserActionToolUse extends ToolUse<"browser_action"> { params: Partial, "action" | "url" | "coordinate" | "text" | "size" | "path">> } +export interface WebSearchToolUse extends ToolUse<"web_search"> { + name: "web_search" + params: Partial, "query" | "max_results">> +} + export interface UseMcpToolToolUse extends ToolUse<"use_mcp_tool"> { name: "use_mcp_tool" params: Partial, "server_name" | "tool_name" | "arguments">> @@ -256,6 +263,7 @@ export const TOOL_DISPLAY_NAMES: Record = { search_files: "search files", list_files: "list files", browser_action: "use a browser", + web_search: "search the web", use_mcp_tool: "use mcp tools", access_mcp_resource: "access mcp resources", ask_followup_question: "ask questions", @@ -279,7 +287,7 @@ export const TOOL_GROUPS: Record = { customTools: ["search_and_replace", "search_replace", "edit_file", "apply_patch"], }, browser: { - tools: ["browser_action"], + tools: ["browser_action", "web_search"], }, command: { tools: ["execute_command"], diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index e36ef2811bb..c4e1e4e1321 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -769,6 +769,37 @@ export const ChatRowContent = ({ ) + case "webSearch": + return ( + <> +
+ {toolIcon("search")} + + {message.type === "ask" ? ( + {tool.query} }} + values={{ query: tool.query }} + /> + ) : ( + {tool.query} }} + values={{ query: tool.query }} + /> + )} + +
+
+ +
+ + ) case "switchMode": return ( <> diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index b583cf40d3c..f046f0ef4cb 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -480,5 +480,9 @@ "updated": "S'ha actualitzat la llista de tasques pendents", "completed": "Completat", "started": "Iniciat" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index 8e1826905fd..25fce2a4618 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -480,5 +480,9 @@ "updated": "Die To-Do-Liste wurde aktualisiert", "completed": "Abgeschlossen", "started": "Gestartet" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index 53ecf74da3a..16fa9573de3 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -472,5 +472,9 @@ "updated": "Updated the to-do list", "completed": "Completed", "started": "Started" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index b3d285a3596..1b179994d36 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -480,5 +480,9 @@ "updated": "Se actualizó la lista de tareas pendientes", "completed": "Completado", "started": "Iniciado" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index 1deda1e9c8f..f6cc98991c5 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -480,5 +480,9 @@ "updated": "La liste des tâches a été mise à jour", "completed": "Terminé", "started": "Commencé" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index 66e51859872..0f08403c1fd 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -480,5 +480,9 @@ "updated": "टू-डू सूची अपडेट की गई", "completed": "पूरा हुआ", "started": "शुरू हुआ" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index da795acc3ef..0defb9b44e8 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -486,5 +486,9 @@ "updated": "Memperbarui daftar to-do", "completed": "Selesai", "started": "Dimulai" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index 9629c2a5ad7..7d418ea149c 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -480,5 +480,9 @@ "updated": "Aggiornata la lista delle cose da fare", "completed": "Completato", "started": "Iniziato" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index b9981828173..848ad51ff8c 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -480,5 +480,9 @@ "updated": "To-Doリストを更新しました", "completed": "完了", "started": "開始" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index 0121586b548..5e211e1cbbb 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -480,5 +480,9 @@ "updated": "할 일 목록을 업데이트했습니다", "completed": "완료됨", "started": "시작됨" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index a2032aa3e33..a0f4188a88f 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -480,5 +480,9 @@ "updated": "De to-do-lijst is bijgewerkt", "completed": "Voltooid", "started": "Gestart" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index 5c4183a0ac0..7d3243c9343 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -480,5 +480,9 @@ "updated": "Zaktualizowano listę zadań do wykonania", "completed": "Ukończono", "started": "Rozpoczęto" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index eb2df5e8fc2..07d66ba3ad6 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -480,5 +480,9 @@ "updated": "A lista de tarefas foi atualizada", "completed": "Concluído", "started": "Iniciado" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index 85a144f31e9..523a0638990 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -481,5 +481,9 @@ "updated": "Список задач обновлен", "completed": "Завершено", "started": "Начато" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index 8bfeffea22b..d4b44c603d5 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -481,5 +481,9 @@ "updated": "Yapılacaklar listesi güncellendi", "completed": "Tamamlandı", "started": "Başladı" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index 76483e19d58..5cd284ca222 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -481,5 +481,9 @@ "updated": "Đã cập nhật danh sách công việc", "completed": "Đã hoàn thành", "started": "Đã bắt đầu" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index 26b874c2b0d..111a17cbe17 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -481,5 +481,9 @@ "updated": "已更新待办事项列表", "completed": "已完成", "started": "已开始" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } } diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index 0449b84a7ae..2bcc168a838 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -481,5 +481,9 @@ "updated": "已更新待辦事項列表", "completed": "已完成", "started": "已開始" + }, + "webSearch": { + "wantsToSearch": "Roo wants to search the web for {{query}}", + "didSearch": "Roo searched the web for {{query}}" } }