mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Add web search tool support
This commit is contained in:
parent
b514996208
commit
f215437872
33 changed files with 396 additions and 4 deletions
|
|
@ -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"]
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ export const toolNames = [
|
|||
"search_files",
|
||||
"list_files",
|
||||
"browser_action",
|
||||
"web_search",
|
||||
"use_mcp_tool",
|
||||
"access_mcp_resource",
|
||||
"ask_followup_question",
|
||||
|
|
|
|||
|
|
@ -676,6 +676,7 @@ export interface ClineSayTool {
|
|||
| "listFilesTopLevel"
|
||||
| "listFilesRecursive"
|
||||
| "searchFiles"
|
||||
| "webSearch"
|
||||
| "switchMode"
|
||||
| "newTask"
|
||||
| "finishTask"
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export function isReadOnlyToolAction(tool: ClineSayTool): boolean {
|
|||
"listFilesRecursive",
|
||||
"searchFiles",
|
||||
"codebaseSearch",
|
||||
"webSearch",
|
||||
"runSlashCommand",
|
||||
].includes(tool.tool)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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, (args: ToolArgs) => 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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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[]
|
||||
}
|
||||
|
|
|
|||
38
src/core/prompts/tools/native-tools/web_search.ts
Normal file
38
src/core/prompts/tools/native-tools/web_search.ts
Normal file
|
|
@ -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
|
||||
20
src/core/prompts/tools/web-search.ts
Normal file
20
src/core/prompts/tools/web-search.ts
Normal file
|
|
@ -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:
|
||||
<web_search>
|
||||
<query>Your search query</query>
|
||||
<max_results>5</max_results>
|
||||
</web_search>
|
||||
|
||||
Example:
|
||||
<web_search>
|
||||
<query>OpenAI Responses API web search tool</query>
|
||||
<max_results>3</max_results>
|
||||
</web_search>`
|
||||
}
|
||||
195
src/core/tools/WebSearchTool.ts
Normal file
195
src/core/tools/WebSearchTool.ts
Normal file
|
|
@ -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<Record<string, string>>): 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<void> {
|
||||
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<void> {
|
||||
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()
|
||||
|
|
@ -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<Pick<Record<ToolParamName, string>, "action" | "url" | "coordinate" | "text" | "size" | "path">>
|
||||
}
|
||||
|
||||
export interface WebSearchToolUse extends ToolUse<"web_search"> {
|
||||
name: "web_search"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "query" | "max_results">>
|
||||
}
|
||||
|
||||
export interface UseMcpToolToolUse extends ToolUse<"use_mcp_tool"> {
|
||||
name: "use_mcp_tool"
|
||||
params: Partial<Pick<Record<ToolParamName, string>, "server_name" | "tool_name" | "arguments">>
|
||||
|
|
@ -256,6 +263,7 @@ export const TOOL_DISPLAY_NAMES: Record<ToolName, string> = {
|
|||
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<ToolGroup, ToolGroupConfig> = {
|
|||
customTools: ["search_and_replace", "search_replace", "edit_file", "apply_patch"],
|
||||
},
|
||||
browser: {
|
||||
tools: ["browser_action"],
|
||||
tools: ["browser_action", "web_search"],
|
||||
},
|
||||
command: {
|
||||
tools: ["execute_command"],
|
||||
|
|
|
|||
|
|
@ -769,6 +769,37 @@ export const ChatRowContent = ({
|
|||
</div>
|
||||
</>
|
||||
)
|
||||
case "webSearch":
|
||||
return (
|
||||
<>
|
||||
<div style={headerStyle}>
|
||||
{toolIcon("search")}
|
||||
<span style={{ fontWeight: "bold" }}>
|
||||
{message.type === "ask" ? (
|
||||
<Trans
|
||||
i18nKey="chat:webSearch.wantsToSearch"
|
||||
components={{ code: <code className="font-medium">{tool.query}</code> }}
|
||||
values={{ query: tool.query }}
|
||||
/>
|
||||
) : (
|
||||
<Trans
|
||||
i18nKey="chat:webSearch.didSearch"
|
||||
components={{ code: <code className="font-medium">{tool.query}</code> }}
|
||||
values={{ query: tool.query }}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="pl-6">
|
||||
<CodeAccordian
|
||||
code={tool.content || ""}
|
||||
language="markdown"
|
||||
isExpanded={isExpanded}
|
||||
onToggleExpand={handleToggleExpand}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
case "switchMode":
|
||||
return (
|
||||
<>
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/ca/chat.json
generated
4
webview-ui/src/i18n/locales/ca/chat.json
generated
|
|
@ -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 <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/de/chat.json
generated
4
webview-ui/src/i18n/locales/de/chat.json
generated
|
|
@ -480,5 +480,9 @@
|
|||
"updated": "Die To-Do-Liste wurde aktualisiert",
|
||||
"completed": "Abgeschlossen",
|
||||
"started": "Gestartet"
|
||||
},
|
||||
"webSearch": {
|
||||
"wantsToSearch": "Roo wants to search the web for <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -472,5 +472,9 @@
|
|||
"updated": "Updated the to-do list",
|
||||
"completed": "Completed",
|
||||
"started": "Started"
|
||||
},
|
||||
"webSearch": {
|
||||
"wantsToSearch": "Roo wants to search the web for <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/es/chat.json
generated
4
webview-ui/src/i18n/locales/es/chat.json
generated
|
|
@ -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 <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/fr/chat.json
generated
4
webview-ui/src/i18n/locales/fr/chat.json
generated
|
|
@ -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 <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/hi/chat.json
generated
4
webview-ui/src/i18n/locales/hi/chat.json
generated
|
|
@ -480,5 +480,9 @@
|
|||
"updated": "टू-डू सूची अपडेट की गई",
|
||||
"completed": "पूरा हुआ",
|
||||
"started": "शुरू हुआ"
|
||||
},
|
||||
"webSearch": {
|
||||
"wantsToSearch": "Roo wants to search the web for <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/id/chat.json
generated
4
webview-ui/src/i18n/locales/id/chat.json
generated
|
|
@ -486,5 +486,9 @@
|
|||
"updated": "Memperbarui daftar to-do",
|
||||
"completed": "Selesai",
|
||||
"started": "Dimulai"
|
||||
},
|
||||
"webSearch": {
|
||||
"wantsToSearch": "Roo wants to search the web for <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/it/chat.json
generated
4
webview-ui/src/i18n/locales/it/chat.json
generated
|
|
@ -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 <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/ja/chat.json
generated
4
webview-ui/src/i18n/locales/ja/chat.json
generated
|
|
@ -480,5 +480,9 @@
|
|||
"updated": "To-Doリストを更新しました",
|
||||
"completed": "完了",
|
||||
"started": "開始"
|
||||
},
|
||||
"webSearch": {
|
||||
"wantsToSearch": "Roo wants to search the web for <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/ko/chat.json
generated
4
webview-ui/src/i18n/locales/ko/chat.json
generated
|
|
@ -480,5 +480,9 @@
|
|||
"updated": "할 일 목록을 업데이트했습니다",
|
||||
"completed": "완료됨",
|
||||
"started": "시작됨"
|
||||
},
|
||||
"webSearch": {
|
||||
"wantsToSearch": "Roo wants to search the web for <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/nl/chat.json
generated
4
webview-ui/src/i18n/locales/nl/chat.json
generated
|
|
@ -480,5 +480,9 @@
|
|||
"updated": "De to-do-lijst is bijgewerkt",
|
||||
"completed": "Voltooid",
|
||||
"started": "Gestart"
|
||||
},
|
||||
"webSearch": {
|
||||
"wantsToSearch": "Roo wants to search the web for <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/pl/chat.json
generated
4
webview-ui/src/i18n/locales/pl/chat.json
generated
|
|
@ -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 <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/pt-BR/chat.json
generated
4
webview-ui/src/i18n/locales/pt-BR/chat.json
generated
|
|
@ -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 <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/ru/chat.json
generated
4
webview-ui/src/i18n/locales/ru/chat.json
generated
|
|
@ -481,5 +481,9 @@
|
|||
"updated": "Список задач обновлен",
|
||||
"completed": "Завершено",
|
||||
"started": "Начато"
|
||||
},
|
||||
"webSearch": {
|
||||
"wantsToSearch": "Roo wants to search the web for <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/tr/chat.json
generated
4
webview-ui/src/i18n/locales/tr/chat.json
generated
|
|
@ -481,5 +481,9 @@
|
|||
"updated": "Yapılacaklar listesi güncellendi",
|
||||
"completed": "Tamamlandı",
|
||||
"started": "Başladı"
|
||||
},
|
||||
"webSearch": {
|
||||
"wantsToSearch": "Roo wants to search the web for <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/vi/chat.json
generated
4
webview-ui/src/i18n/locales/vi/chat.json
generated
|
|
@ -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 <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/zh-CN/chat.json
generated
4
webview-ui/src/i18n/locales/zh-CN/chat.json
generated
|
|
@ -481,5 +481,9 @@
|
|||
"updated": "已更新待办事项列表",
|
||||
"completed": "已完成",
|
||||
"started": "已开始"
|
||||
},
|
||||
"webSearch": {
|
||||
"wantsToSearch": "Roo wants to search the web for <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
4
webview-ui/src/i18n/locales/zh-TW/chat.json
generated
4
webview-ui/src/i18n/locales/zh-TW/chat.json
generated
|
|
@ -481,5 +481,9 @@
|
|||
"updated": "已更新待辦事項列表",
|
||||
"completed": "已完成",
|
||||
"started": "已開始"
|
||||
},
|
||||
"webSearch": {
|
||||
"wantsToSearch": "Roo wants to search the web for <code>{{query}}</code>",
|
||||
"didSearch": "Roo searched the web for <code>{{query}}</code>"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue