From c0c7878497bbe3580dfea0aef032ed1831c7b88c Mon Sep 17 00:00:00 2001 From: Will Li Date: Tue, 8 Jul 2025 01:16:18 -0700 Subject: [PATCH 01/12] working first version --- packages/types/src/global-settings.ts | 8 + src/core/prompts/responses.ts | 12 + src/core/timeout/TimeoutFallbackGenerator.ts | 358 ++++++++++++++++++ src/core/timeout/TimeoutFallbackHandler.ts | 75 ++++ src/core/timeout/TimeoutManager.ts | 199 ++++++++++ src/core/timeout/ToolExecutionWrapper.ts | 163 ++++++++ .../__tests__/ai-fallback-real.spec.ts | 234 ++++++++++++ .../timeout/__tests__/e2e-ai-test.spec.ts | 179 +++++++++ .../__tests__/timeout-integration.spec.ts | 167 ++++++++ .../__tests__/tool-injection-test.spec.ts | 62 +++ .../timeout/__tests__/ui-integration.spec.ts | 71 ++++ src/core/timeout/index.ts | 8 + src/core/tools/executeCommandTool.ts | 91 ++++- src/core/webview/ClineProvider.ts | 6 + src/core/webview/webviewMessageHandler.ts | 8 + src/shared/ExtensionMessage.ts | 2 + src/shared/WebviewMessage.ts | 2 + .../settings/AutoApproveSettings.tsx | 50 +++ .../src/components/settings/SettingsView.tsx | 6 + .../src/context/ExtensionStateContext.tsx | 26 ++ webview-ui/src/i18n/locales/en/settings.json | 12 + 21 files changed, 1736 insertions(+), 3 deletions(-) create mode 100644 src/core/timeout/TimeoutFallbackGenerator.ts create mode 100644 src/core/timeout/TimeoutFallbackHandler.ts create mode 100644 src/core/timeout/TimeoutManager.ts create mode 100644 src/core/timeout/ToolExecutionWrapper.ts create mode 100644 src/core/timeout/__tests__/ai-fallback-real.spec.ts create mode 100644 src/core/timeout/__tests__/e2e-ai-test.spec.ts create mode 100644 src/core/timeout/__tests__/timeout-integration.spec.ts create mode 100644 src/core/timeout/__tests__/tool-injection-test.spec.ts create mode 100644 src/core/timeout/__tests__/ui-integration.spec.ts create mode 100644 src/core/timeout/index.ts diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index 79a09ff017..130ba09b23 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -84,6 +84,10 @@ export const globalSettingsSchema = z.object({ terminalZdotdir: z.boolean().optional(), terminalCompressProgressBar: z.boolean().optional(), + // Timeout settings + toolExecutionTimeoutMs: z.number().min(1000).max(1800000).optional(), // 1s to 30min + timeoutFallbackEnabled: z.boolean().optional(), + rateLimitSeconds: z.number().optional(), diffEnabled: z.boolean().optional(), fuzzyMatchThreshold: z.number().optional(), @@ -226,6 +230,10 @@ export const EVALS_SETTINGS: RooCodeSettings = { enableCheckpoints: false, + // Timeout settings + toolExecutionTimeoutMs: 300000, // 5 minutes default + timeoutFallbackEnabled: false, + rateLimitSeconds: 0, maxOpenTabsContext: 20, maxWorkspaceFiles: 200, diff --git a/src/core/prompts/responses.ts b/src/core/prompts/responses.ts index 3f38789fdc..d2d513db57 100644 --- a/src/core/prompts/responses.ts +++ b/src/core/prompts/responses.ts @@ -15,6 +15,18 @@ export const formatResponse = { toolError: (error?: string) => `The tool execution failed with the following error:\n\n${error}\n`, + toolTimeout: (toolName: string, timeoutMs: number, executionTimeMs: number) => + `The ${toolName} operation timed out after ${Math.round(timeoutMs / 1000)} seconds and was automatically canceled. + + +Tool: ${toolName} +Configured Timeout: ${Math.round(timeoutMs / 1000)}s +Execution Time: ${Math.round(executionTimeMs / 1000)}s +Status: Canceled + + +The operation has been terminated to prevent system resource issues. Please consider one of the following approaches to complete your task.`, + rooIgnoreError: (path: string) => `Access to ${path} is blocked by the .rooignore file settings. You must try to continue in the task without using this file, or ask the user to update the .rooignore file.`, diff --git a/src/core/timeout/TimeoutFallbackGenerator.ts b/src/core/timeout/TimeoutFallbackGenerator.ts new file mode 100644 index 0000000000..2a26fd9b25 --- /dev/null +++ b/src/core/timeout/TimeoutFallbackGenerator.ts @@ -0,0 +1,358 @@ +import type { ToolName } from "@roo-code/types" +import type { Task } from "../task/Task" +import type { SingleCompletionHandler } from "../../api" + +export interface TimeoutFallbackContext { + toolName: ToolName + timeoutMs: number + executionTimeMs: number + toolParams?: Record + errorMessage?: string + taskContext?: { + currentStep?: string + previousActions?: string[] + workingDirectory?: string + } +} + +export interface TimeoutFallbackResult { + success: boolean + toolCall?: { + name: "ask_followup_question" + params: { + question: string + follow_up: string + } + } + error?: string +} + +/** + * Generates AI-powered fallback suggestions for timeout scenarios + */ +export class TimeoutFallbackGenerator { + /** + * Generate an AI-powered ask_followup_question tool call for timeout scenarios + */ + public static async generateAiFallback( + context: TimeoutFallbackContext, + task?: Task, + ): Promise { + // Try to use AI to generate contextual suggestions + if (task?.api && "completePrompt" in task.api) { + try { + const aiResult = await this.generateAiSuggestions(context, task.api as SingleCompletionHandler) + if (aiResult.success) { + return aiResult + } + } catch (error) { + // AI failed, fall through to static suggestions + } + } + + // Fallback to static suggestions if AI fails or is unavailable + const toolCall = this.generateStaticToolCall(context) + + return { + success: true, + toolCall, + } + } + + /** + * Generate AI-powered suggestions using the task's API handler + */ + private static async generateAiSuggestions( + context: TimeoutFallbackContext, + apiHandler: SingleCompletionHandler, + ): Promise { + try { + const prompt = this.createAiPrompt(context) + const aiResponse = await apiHandler.completePrompt(prompt) + + // Parse the AI response to extract suggestions + const suggestions = this.parseAiResponse(aiResponse) + + if (suggestions.length === 0) { + throw new Error("No valid suggestions generated by AI") + } + + const question = `The ${context.toolName} operation timed out after ${Math.round(context.timeoutMs / 1000)} seconds. How would you like to proceed?` + + const followUpXml = suggestions + .map((suggestion) => + suggestion.mode + ? `${suggestion.text}` + : `${suggestion.text}`, + ) + .join("\n") + + return { + success: true, + toolCall: { + name: "ask_followup_question", + params: { + question, + follow_up: followUpXml, + }, + }, + } + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : "Unknown error generating AI suggestions", + } + } + } + + /** + * Create a prompt for the AI to generate contextual timeout fallback suggestions + */ + private static createAiPrompt(context: TimeoutFallbackContext): string { + const { toolName, timeoutMs, executionTimeMs, toolParams, taskContext } = context + + const timeoutSeconds = Math.round(timeoutMs / 1000) + const executionSeconds = Math.round(executionTimeMs / 1000) + + let prompt = `A ${toolName} operation has timed out after ${timeoutSeconds} seconds (actual execution time: ${executionSeconds} seconds). + +Context: +- Tool: ${toolName} +- Timeout limit: ${timeoutSeconds}s +- Actual execution time: ${executionSeconds}s` + + // Add tool-specific context + if (toolParams) { + prompt += `\n- Parameters: ${JSON.stringify(toolParams, null, 2)}` + } + + // Add task context if available + if (taskContext) { + if (taskContext.currentStep) { + prompt += `\n- Current step: ${taskContext.currentStep}` + } + if (taskContext.workingDirectory) { + prompt += `\n- Working directory: ${taskContext.workingDirectory}` + } + } + + prompt += ` + +Generate exactly 3-4 specific, actionable suggestions for how to proceed after this timeout. Each suggestion should be: +1. Contextually relevant to the specific ${toolName} operation that timed out +2. Actionable and specific (not generic advice) +3. Focused on solving the immediate problem +4. Ordered by likelihood of success + +Format your response as a simple numbered list: +1. [First suggestion] +2. [Second suggestion] +3. [Third suggestion] +4. [Fourth suggestion (optional)] + +Focus on practical solutions like: +- Breaking the operation into smaller parts +- Using alternative tools or methods +- Adjusting parameters or settings +- Checking for underlying issues +- Optimizing the approach + +Keep each suggestion concise (under 80 characters) and actionable.` + + return prompt + } + + /** + * Parse AI response to extract suggestions + */ + private static parseAiResponse(response: string): Array<{ text: string; mode?: string }> { + const suggestions: Array<{ text: string; mode?: string }> = [] + + // Look for numbered list items + const lines = response.split("\n") + for (const line of lines) { + const trimmed = line.trim() + + // Match patterns like "1. suggestion", "2) suggestion", etc. + const match = trimmed.match(/^(\d+)[.)]\s*(.+)$/) + if (match && match[2]) { + const suggestionText = match[2].trim() + if (suggestionText.length > 0 && suggestionText.length <= 120) { + suggestions.push({ text: suggestionText }) + } + } + } + + // If no numbered list found, try to extract sentences + if (suggestions.length === 0) { + const sentences = response + .split(/[.!?]+/) + .map((s) => s.trim()) + .filter((s) => s.length > 10 && s.length <= 120) + for (let i = 0; i < Math.min(4, sentences.length); i++) { + suggestions.push({ text: sentences[i] }) + } + } + + return suggestions.slice(0, 4) // Limit to 4 suggestions + } + + /** + * Generate static fallback suggestions when AI is unavailable + */ + private static generateStaticToolCall(context: TimeoutFallbackContext): TimeoutFallbackResult["toolCall"] { + const suggestions = this.generateContextualSuggestions(context) + + const question = `The ${context.toolName} operation timed out after ${Math.round(context.timeoutMs / 1000)} seconds. How would you like to proceed?` + + const followUpXml = suggestions + .map((suggestion) => + suggestion.mode + ? `${suggestion.text}` + : `${suggestion.text}`, + ) + .join("\n") + + return { + name: "ask_followup_question", + params: { + question, + follow_up: followUpXml, + }, + } + } + + /** + * Generate contextual suggestions based on tool type and parameters + */ + private static generateContextualSuggestions( + context: TimeoutFallbackContext, + ): Array<{ text: string; mode?: string }> { + const { toolName, toolParams } = context + + switch (toolName) { + case "execute_command": + return this.generateCommandSuggestions(toolParams) + case "read_file": + return this.generateReadFileSuggestions(toolParams) + case "write_to_file": + return this.generateWriteFileSuggestions(toolParams) + case "browser_action": + return this.generateBrowserSuggestions(toolParams) + case "search_files": + return this.generateSearchSuggestions(toolParams) + default: + return this.generateGenericSuggestions(context) + } + } + + private static generateCommandSuggestions(params?: Record): Array<{ text: string; mode?: string }> { + const command = params?.command || "the command" + + return [ + { + text: `Break "${command}" into smaller, sequential steps that can complete faster`, + }, + { + text: `Run "${command}" in the background using '&' or 'nohup' to avoid blocking`, + }, + { + text: `Try an alternative approach or tool to accomplish the same goal`, + }, + { + text: `Increase the timeout setting if this operation legitimately needs more time`, + }, + ] + } + + private static generateReadFileSuggestions(params?: Record): Array<{ text: string; mode?: string }> { + const filePath = params?.path || "the file" + + return [ + { + text: `Read "${filePath}" in smaller chunks using line ranges`, + }, + { + text: `Check if "${filePath}" is accessible and not locked by another process`, + }, + { + text: `Use a different approach to access the file content`, + }, + { + text: `Increase the timeout if this is a legitimately large file`, + }, + ] + } + + private static generateWriteFileSuggestions(params?: Record): Array<{ text: string; mode?: string }> { + const filePath = params?.path || "the file" + + return [ + { + text: `Write to "${filePath}" incrementally using insert_content instead`, + }, + { + text: `Check if "${filePath}" is writable and not locked`, + }, + { + text: `Use apply_diff for targeted changes instead of full file replacement`, + }, + { + text: `Break the content into smaller write operations`, + }, + ] + } + + private static generateBrowserSuggestions(params?: Record): Array<{ text: string; mode?: string }> { + const action = params?.action || "browser action" + + return [ + { + text: `Simplify the "${action}" into smaller, more targeted steps`, + }, + { + text: `Wait for specific elements to load before proceeding`, + }, + { + text: `Use direct API calls instead of browser automation if possible`, + }, + { + text: `Reset the browser session and try again`, + }, + ] + } + + private static generateSearchSuggestions(params?: Record): Array<{ text: string; mode?: string }> { + return [ + { + text: `Narrow the search scope to specific directories`, + }, + { + text: `Use simpler search patterns or literal strings`, + }, + { + text: `Apply file type filters to reduce search space`, + }, + { + text: `Search incrementally in smaller batches`, + }, + ] + } + + private static generateGenericSuggestions(context: TimeoutFallbackContext): Array<{ text: string; mode?: string }> { + return [ + { + text: `Break the ${context.toolName} operation into smaller steps`, + }, + { + text: `Try an alternative approach to accomplish the same goal`, + }, + { + text: `Check system resources and try again`, + }, + { + text: `Increase the timeout setting for this operation`, + }, + ] + } +} diff --git a/src/core/timeout/TimeoutFallbackHandler.ts b/src/core/timeout/TimeoutFallbackHandler.ts new file mode 100644 index 0000000000..7e3044a3d7 --- /dev/null +++ b/src/core/timeout/TimeoutFallbackHandler.ts @@ -0,0 +1,75 @@ +import type { ToolName } from "@roo-code/types" +import { formatResponse } from "../prompts/responses" +import { + TimeoutFallbackGenerator, + type TimeoutFallbackContext, + type TimeoutFallbackResult, +} from "./TimeoutFallbackGenerator" +import type { Task } from "../task/Task" +import { parseAssistantMessage } from "../assistant-message/parseAssistantMessage" + +/** + * Generates AI-powered fallback suggestions for timeout scenarios + */ +export class TimeoutFallbackHandler { + /** + * Create a timeout response with AI-generated fallback question + */ + public static async createTimeoutResponse( + toolName: ToolName, + timeoutMs: number, + executionTimeMs: number, + context?: any, + task?: Task, + ): Promise { + const baseResponse = formatResponse.toolTimeout(toolName, timeoutMs, executionTimeMs) + + // Create context for AI fallback generation + const aiContext: TimeoutFallbackContext = { + toolName, + timeoutMs, + executionTimeMs, + toolParams: context, + taskContext: task + ? { + workingDirectory: task.cwd, + } + : undefined, + } + + // Generate AI-powered fallback (with static fallback if AI fails) + const aiResult = await TimeoutFallbackGenerator.generateAiFallback(aiContext, task) + + if (aiResult.success && aiResult.toolCall && task) { + // Inject the tool call directly into the assistant message content for proper execution + this.injectToolCallIntoMessageContent(aiResult.toolCall, task) + return baseResponse + } + + // This should rarely happen since generateAiFallback always provides static fallback + return `${baseResponse}\n\nThe operation timed out. Please consider breaking this into smaller steps or trying a different approach.` + } + + /** + * Inject a tool call directly into the assistant message content for proper parsing and execution + */ + private static injectToolCallIntoMessageContent(toolCall: TimeoutFallbackResult["toolCall"], task: Task): void { + if (toolCall?.name === "ask_followup_question" && toolCall.params) { + const { question, follow_up } = toolCall.params + + // Create the XML tool call string + const toolCallXml = ` +${question} + +${follow_up} + +` + + // Parse the tool call XML to create proper assistant message content + const parsedContent = parseAssistantMessage(toolCallXml) + + // Add the parsed tool call to the assistant message content + task.assistantMessageContent.push(...parsedContent) + } + } +} diff --git a/src/core/timeout/TimeoutManager.ts b/src/core/timeout/TimeoutManager.ts new file mode 100644 index 0000000000..28d361ef07 --- /dev/null +++ b/src/core/timeout/TimeoutManager.ts @@ -0,0 +1,199 @@ +import { EventEmitter } from "events" +import type { ToolName } from "@roo-code/types" + +export interface TimeoutConfig { + toolName: ToolName + timeoutMs: number + enableFallback: boolean + taskId?: string +} + +export interface TimeoutResult { + success: boolean + result?: T + timedOut: boolean + fallbackTriggered: boolean + error?: Error + executionTimeMs: number +} + +export interface TimeoutEvent { + toolName: ToolName + timeoutMs: number + executionTimeMs: number + taskId?: string + timestamp: number +} + +/** + * Manages timeouts for all tool executions with configurable fallback mechanisms + */ +export class TimeoutManager extends EventEmitter { + private static instance: TimeoutManager | undefined + private activeOperations = new Map() + /** + * Multiple timeout events can be run at once + * eg. running a command while reading a file + */ + private timeoutEvents: TimeoutEvent[] = [] + + private constructor() { + super() + } + + public static getInstance(): TimeoutManager { + if (!TimeoutManager.instance) { + TimeoutManager.instance = new TimeoutManager() + } + return TimeoutManager.instance + } + + /** + * Execute a function with timeout protection + */ + public async executeWithTimeout( + operation: (signal: AbortSignal) => Promise, + config: TimeoutConfig, + ): Promise> { + const operationId = this.generateOperationId(config.toolName, config.taskId) + const controller = new AbortController() + const startTime = Date.now() + + // Store the controller for potential cancellation + this.activeOperations.set(operationId, controller) + + try { + // Create timeout promise + const timeoutPromise = new Promise((_, reject) => { + const timeoutId = setTimeout(() => { + controller.abort() + reject(new Error(`Operation timed out after ${config.timeoutMs}ms`)) + }, config.timeoutMs) + + // Clean up timeout if operation completes + controller.signal.addEventListener("abort", () => { + clearTimeout(timeoutId) + }) + }) + + // Race between operation and timeout + const result = await Promise.race([operation(controller.signal), timeoutPromise]) + + const executionTimeMs = Date.now() - startTime + + return { + success: true, + result, + timedOut: false, + fallbackTriggered: false, + executionTimeMs, + } + } catch (error) { + const executionTimeMs = Date.now() - startTime + const timedOut = controller.signal.aborted + + if (timedOut) { + // Log timeout event + const timeoutEvent: TimeoutEvent = { + toolName: config.toolName, + timeoutMs: config.timeoutMs, + executionTimeMs, + taskId: config.taskId, + timestamp: Date.now(), + } + + this.timeoutEvents.push(timeoutEvent) + this.emit("timeout", timeoutEvent) + + return { + success: false, + timedOut: true, + fallbackTriggered: config.enableFallback, + error: error as Error, + executionTimeMs, + } + } + + return { + success: false, + timedOut: false, + fallbackTriggered: false, + error: error as Error, + executionTimeMs, + } + } finally { + // Clean up + this.activeOperations.delete(operationId) + } + } + + /** + * Cancel a specific operation by tool name and task ID + */ + public cancelOperation(toolName: ToolName, taskId?: string): boolean { + const operationId = this.generateOperationId(toolName, taskId) + const controller = this.activeOperations.get(operationId) + + if (controller) { + controller.abort() + this.activeOperations.delete(operationId) + return true + } + + return false + } + + /** + * Cancel all active operations + */ + public cancelAllOperations(): void { + for (const controller of this.activeOperations.values()) { + controller.abort() + } + this.activeOperations.clear() + } + + /** + * Get timeout events for debugging/monitoring + */ + public getTimeoutEvents(limit = 100): TimeoutEvent[] { + return this.timeoutEvents.slice(-limit) + } + + /** + * Clear timeout event history + */ + public clearTimeoutEvents(): void { + this.timeoutEvents = [] + } + + /** + * Get active operation count + */ + public getActiveOperationCount(): number { + return this.activeOperations.size + } + + /** + * Check if a specific operation is active + */ + public isOperationActive(toolName: ToolName, taskId?: string): boolean { + const operationId = this.generateOperationId(toolName, taskId) + return this.activeOperations.has(operationId) + } + + private generateOperationId(toolName: ToolName, taskId?: string): string { + return `${toolName}:${taskId || "default"}:${Date.now()}` + } + + /** + * Cleanup method for graceful shutdown + */ + public dispose(): void { + this.cancelAllOperations() + this.removeAllListeners() + this.timeoutEvents = [] + } +} + +export const timeoutManager = TimeoutManager.getInstance() diff --git a/src/core/timeout/ToolExecutionWrapper.ts b/src/core/timeout/ToolExecutionWrapper.ts new file mode 100644 index 0000000000..a67d10f2a5 --- /dev/null +++ b/src/core/timeout/ToolExecutionWrapper.ts @@ -0,0 +1,163 @@ +import type { ToolName } from "@roo-code/types" +import { timeoutManager, type TimeoutConfig, type TimeoutResult } from "./TimeoutManager" + +export interface ToolExecutionOptions { + toolName: ToolName + taskId?: string + timeoutMs?: number + enableFallback?: boolean +} + +/** + * Wrapper for executing tools with timeout protection + */ +export class ToolExecutionWrapper { + /** + * Execute a tool operation with timeout protection + */ + public static async execute( + operation: (signal: AbortSignal) => Promise, + options: ToolExecutionOptions, + defaultTimeoutMs = 300000, // 5 minutes default + ): Promise> { + const config: TimeoutConfig = { + toolName: options.toolName, + timeoutMs: options.timeoutMs ?? defaultTimeoutMs, + enableFallback: options.enableFallback ?? true, + taskId: options.taskId, + } + + return timeoutManager.executeWithTimeout(operation, config) + } + + /** + * Wrap a promise-based operation to support AbortSignal + */ + public static wrapPromise(promiseFactory: () => Promise, signal: AbortSignal): Promise { + return new Promise((resolve, reject) => { + // Check if already aborted + if (signal.aborted) { + reject(new Error("Operation was aborted before starting")) + return + } + + // Set up abort listener + const abortListener = () => { + reject(new Error("Operation was aborted")) + } + + signal.addEventListener("abort", abortListener) + + // Execute the operation + promiseFactory() + .then((result) => { + signal.removeEventListener("abort", abortListener) + resolve(result) + }) + .catch((error) => { + signal.removeEventListener("abort", abortListener) + reject(error) + }) + }) + } + + /** + * Wrap a callback-based operation to support AbortSignal + */ + public static wrapCallback( + operation: (callback: (error: Error | null, result?: T) => void, signal: AbortSignal) => void, + signal: AbortSignal, + ): Promise { + return new Promise((resolve, reject) => { + // Check if already aborted + if (signal.aborted) { + reject(new Error("Operation was aborted before starting")) + return + } + + // Set up abort listener + const abortListener = () => { + reject(new Error("Operation was aborted")) + } + + signal.addEventListener("abort", abortListener) + + // Execute the operation + operation((error, result) => { + signal.removeEventListener("abort", abortListener) + + if (error) { + reject(error) + } else { + resolve(result!) + } + }, signal) + }) + } + + /** + * Create an abortable delay + */ + public static delay(ms: number, signal: AbortSignal): Promise { + return new Promise((resolve, reject) => { + if (signal.aborted) { + reject(new Error("Delay was aborted before starting")) + return + } + + const timeoutId = setTimeout(() => { + signal.removeEventListener("abort", abortListener) + resolve() + }, ms) + + const abortListener = () => { + clearTimeout(timeoutId) + reject(new Error("Delay was aborted")) + } + + signal.addEventListener("abort", abortListener) + }) + } + + /** + * Execute multiple operations in parallel with timeout protection + */ + public static async executeParallel( + operations: Array<{ + operation: (signal: AbortSignal) => Promise + options: ToolExecutionOptions + }>, + defaultTimeoutMs = 300000, + ): Promise[]> { + const promises = operations.map(({ operation, options }) => + ToolExecutionWrapper.execute(operation, options, defaultTimeoutMs), + ) + + return Promise.all(promises) + } + + /** + * Execute operations in sequence with timeout protection + */ + public static async executeSequential( + operations: Array<{ + operation: (signal: AbortSignal) => Promise + options: ToolExecutionOptions + }>, + defaultTimeoutMs = 300000, + ): Promise[]> { + const results: TimeoutResult[] = [] + + for (const { operation, options } of operations) { + const result = await ToolExecutionWrapper.execute(operation, options, defaultTimeoutMs) + results.push(result) + + // Stop execution if any operation fails or times out + if (!result.success) { + break + } + } + + return results + } +} diff --git a/src/core/timeout/__tests__/ai-fallback-real.spec.ts b/src/core/timeout/__tests__/ai-fallback-real.spec.ts new file mode 100644 index 0000000000..021c02eb3f --- /dev/null +++ b/src/core/timeout/__tests__/ai-fallback-real.spec.ts @@ -0,0 +1,234 @@ +// npx vitest run src/core/timeout/__tests__/ai-fallback-real.spec.ts + +import { describe, test, expect, beforeEach, vitest } from "vitest" +import { TimeoutFallbackGenerator } from "../TimeoutFallbackGenerator" +import type { ApiHandler, SingleCompletionHandler } from "../../../api" +import type { Task } from "../../task/Task" + +// Create a mock API handler that extends ApiHandler and includes completePrompt +interface MockApiHandler extends ApiHandler, SingleCompletionHandler {} + +describe("TimeoutFallbackGenerator - Real AI Implementation", () => { + let mockApiHandler: MockApiHandler + let mockTask: Partial + + beforeEach(() => { + vitest.clearAllMocks() + + // Mock API handler that simulates real AI responses + mockApiHandler = { + createMessage: vitest.fn(), + getModel: vitest.fn().mockReturnValue({ id: "test-model", info: { maxTokens: 4096 } }), + countTokens: vitest.fn().mockResolvedValue(100), + completePrompt: vitest.fn(), + } + + // Mock task with API handler + mockTask = { + api: mockApiHandler, + } + }) + + test("should use AI to generate contextual suggestions when available", async () => { + // Mock AI response with numbered suggestions + const mockAiResponse = `Here are some suggestions for the timeout: + +1. Break the npm install command into smaller package installations +2. Clear npm cache and try again with npm cache clean --force +3. Use npm install --no-optional to skip optional dependencies +4. Check network connectivity and try with different registry` + + ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) + + const context = { + toolName: "execute_command" as const, + timeoutMs: 30000, + executionTimeMs: 35000, + toolParams: { command: "npm install" }, + } + + const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + expect(result.toolCall?.name).toBe("ask_followup_question") + expect(result.toolCall?.params.question).toContain("execute_command") + expect(result.toolCall?.params.question).toContain("30 seconds") + + // Check that AI-generated suggestions are included + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain("Break the npm install command into smaller package installations") + expect(followUp).toContain("Clear npm cache and try again") + expect(followUp).toContain("Use npm install --no-optional") + expect(followUp).toContain("Check network connectivity") + + // Verify AI was called with proper prompt + expect(mockApiHandler.completePrompt).toHaveBeenCalledWith( + expect.stringContaining("execute_command operation has timed out"), + ) + expect(mockApiHandler.completePrompt).toHaveBeenCalledWith(expect.stringContaining("npm install")) + }) + + test("should fallback to static suggestions when AI fails", async () => { + // Mock AI failure + ;(mockApiHandler.completePrompt as any).mockRejectedValueOnce(new Error("API Error")) + + const context = { + toolName: "execute_command" as const, + timeoutMs: 30000, + executionTimeMs: 35000, + toolParams: { command: "npm test" }, + } + + const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + expect(result.toolCall?.name).toBe("ask_followup_question") + + // Should contain static fallback suggestions + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain('Break "npm test" into smaller') + expect(followUp).toContain("background using") + expect(followUp).toContain("alternative approach") + expect(followUp).toContain("Increase the timeout") + }) + + test("should fallback to static suggestions when API handler is unavailable", async () => { + // Task without API handler + const taskWithoutApi = {} + + const context = { + toolName: "read_file" as const, + timeoutMs: 5000, + executionTimeMs: 6000, + toolParams: { path: "/large/file.txt" }, + } + + const result = await TimeoutFallbackGenerator.generateAiFallback(context, taskWithoutApi as Task) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + + // Should contain static fallback suggestions for read_file + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain('Read "/large/file.txt" in smaller chunks') + expect(followUp).toContain("accessible and not locked") + }) + + test("should parse AI response with different numbering formats", async () => { + // Test different numbering formats + const mockAiResponse = `Here are the suggestions: + +1) Try breaking the command into parts +2. Use a different approach +3) Check system resources +4. Increase timeout duration` + + ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) + + const context = { + toolName: "execute_command" as const, + timeoutMs: 10000, + executionTimeMs: 12000, + toolParams: { command: "build script" }, + } + + const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain("Try breaking the command into parts") + expect(followUp).toContain("Use a different approach") + expect(followUp).toContain("Check system resources") + expect(followUp).toContain("Increase timeout duration") + }) + + test("should handle AI response without numbered list", async () => { + // AI response without clear numbering + const mockAiResponse = `You could try splitting the operation. Another option is to check the network. Maybe increase the timeout. Consider using a different tool.` + + ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) + + const context = { + toolName: "browser_action" as const, + timeoutMs: 15000, + executionTimeMs: 16000, + toolParams: { action: "click" }, + } + + const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + const followUp = result.toolCall?.params.follow_up || "" + + // Should extract sentences as suggestions + expect(followUp).toContain("You could try splitting the operation") + expect(followUp).toContain("Another option is to check the network") + }) + + test("should include task context in AI prompt when available", async () => { + const mockAiResponse = `1. Try a different approach\n2. Check the working directory\n3. Break into steps` + ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) + + const context = { + toolName: "search_files" as const, + timeoutMs: 20000, + executionTimeMs: 22000, + toolParams: { path: "/project", regex: ".*\\.ts$" }, + taskContext: { + currentStep: "Finding TypeScript files", + workingDirectory: "/project/src", + previousActions: ["read package.json", "list files"], + }, + } + + const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + + // Verify the prompt included task context + const calledPrompt = (mockApiHandler.completePrompt as any).mock.calls[0][0] + expect(calledPrompt).toContain("Current step: Finding TypeScript files") + expect(calledPrompt).toContain("Working directory: /project/src") + expect(calledPrompt).toContain("search_files") + expect(calledPrompt).toContain("ts$") // Just check for the pattern ending + }) + + test("should limit suggestions to maximum of 4", async () => { + // AI response with many suggestions + const mockAiResponse = `Here are many suggestions: + +1. First suggestion +2. Second suggestion +3. Third suggestion +4. Fourth suggestion +5. Fifth suggestion +6. Sixth suggestion +7. Seventh suggestion` + + ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) + + const context = { + toolName: "write_to_file" as const, + timeoutMs: 8000, + executionTimeMs: 9000, + toolParams: { path: "/output.txt" }, + } + + const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + const followUp = result.toolCall?.params.follow_up || "" + + // Count the number of tags + const suggestCount = (followUp.match(//g) || []).length + expect(suggestCount).toBeLessThanOrEqual(4) + + // Should include first 4 suggestions + expect(followUp).toContain("First suggestion") + expect(followUp).toContain("Fourth suggestion") + // Should not include 5th and beyond + expect(followUp).not.toContain("Fifth suggestion") + }) +}) diff --git a/src/core/timeout/__tests__/e2e-ai-test.spec.ts b/src/core/timeout/__tests__/e2e-ai-test.spec.ts new file mode 100644 index 0000000000..7b1fe4d23e --- /dev/null +++ b/src/core/timeout/__tests__/e2e-ai-test.spec.ts @@ -0,0 +1,179 @@ +// End-to-end test to verify AI fallback generation works +// npx vitest run src/core/timeout/__tests__/e2e-ai-test.spec.ts + +import { describe, test, expect, beforeEach, vitest } from "vitest" +import { TimeoutFallbackGenerator } from "../TimeoutFallbackGenerator" +import type { ApiHandler, SingleCompletionHandler } from "../../../api" +import type { Task } from "../../task/Task" + +// Mock API handler that simulates a real AI provider +interface TestApiHandler extends ApiHandler, SingleCompletionHandler {} + +describe("TimeoutFallbackGenerator - End-to-End AI Test", () => { + test("should generate realistic AI suggestions for execute_command timeout", async () => { + // Create a realistic mock API handler + const mockApiHandler: TestApiHandler = { + createMessage: vitest.fn(), + getModel: vitest.fn().mockReturnValue({ id: "claude-3-sonnet", info: { maxTokens: 4096 } }), + countTokens: vitest.fn().mockResolvedValue(150), + completePrompt: vitest.fn().mockResolvedValue( + ` +Here are some suggestions for the npm install timeout: + +1. Clear npm cache with "npm cache clean --force" and retry +2. Break installation into smaller chunks by installing packages individually +3. Use "npm install --no-optional" to skip optional dependencies +4. Check network connectivity and try with a different registry + `.trim(), + ), + } + + const mockTask: Partial = { + api: mockApiHandler, + } + + const context = { + toolName: "execute_command" as const, + timeoutMs: 60000, + executionTimeMs: 65000, + toolParams: { + command: "npm install", + cwd: "/project", + }, + } + + const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + + // Verify the result structure + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + expect(result.toolCall?.name).toBe("ask_followup_question") + expect(result.toolCall?.params.question).toContain("execute_command") + expect(result.toolCall?.params.question).toContain("60 seconds") + + // Verify AI-generated suggestions are included + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain("Clear npm cache") + expect(followUp).toContain("Break installation into smaller chunks") + expect(followUp).toContain("no-optional") + expect(followUp).toContain("network connectivity") + + // Verify the AI was called with a proper prompt + expect(mockApiHandler.completePrompt).toHaveBeenCalledWith( + expect.stringContaining("execute_command operation has timed out"), + ) + expect(mockApiHandler.completePrompt).toHaveBeenCalledWith(expect.stringContaining("npm install")) + expect(mockApiHandler.completePrompt).toHaveBeenCalledWith(expect.stringContaining("60 seconds")) + }) + + test("should handle AI response with different formatting", async () => { + // Mock AI response with different numbering style + const mockApiHandler: TestApiHandler = { + createMessage: vitest.fn(), + getModel: vitest.fn().mockReturnValue({ id: "gpt-4", info: { maxTokens: 8192 } }), + countTokens: vitest.fn().mockResolvedValue(200), + completePrompt: vitest.fn().mockResolvedValue( + ` +Based on the search_files timeout, here are my recommendations: + +• Limit search to specific subdirectories instead of entire project +• Use more specific regex patterns to reduce matches +• Try list_files first to understand directory structure +• Consider breaking search into multiple smaller operations + `.trim(), + ), + } + + const mockTask: Partial = { + api: mockApiHandler, + } + + const context = { + toolName: "search_files" as const, + timeoutMs: 30000, + executionTimeMs: 32000, + toolParams: { + path: "/large-project", + regex: ".*", + file_pattern: "*.ts", + }, + } + + const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + + // Should extract suggestions even with bullet points + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain("Narrow the search scope") + expect(followUp).toContain("simpler search patterns") + expect(followUp).toContain("file type filters") + expect(followUp).toContain("incrementally in smaller batches") + }) + + test("should gracefully handle AI failure and use static fallback", async () => { + // Mock API handler that fails + const mockApiHandler: TestApiHandler = { + createMessage: vitest.fn(), + getModel: vitest.fn().mockReturnValue({ id: "test-model", info: { maxTokens: 4096 } }), + countTokens: vitest.fn().mockResolvedValue(100), + completePrompt: vitest.fn().mockRejectedValue(new Error("API rate limit exceeded")), + } + + const mockTask: Partial = { + api: mockApiHandler, + } + + const context = { + toolName: "read_file" as const, + timeoutMs: 10000, + executionTimeMs: 12000, + toolParams: { + path: "/very/large/file.log", + }, + } + + const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + + // Should contain static fallback suggestions for read_file + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain('Read "/very/large/file.log" in smaller chunks') + expect(followUp).toContain("accessible and not locked") + expect(followUp).toContain("different approach") + expect(followUp).toContain("Increase the timeout") + + // Verify AI was attempted but failed gracefully + expect(mockApiHandler.completePrompt).toHaveBeenCalled() + }) + + test("should work without task API handler", async () => { + // Task without API handler + const mockTask: Partial = {} + + const context = { + toolName: "browser_action" as const, + timeoutMs: 15000, + executionTimeMs: 16500, + toolParams: { + action: "click", + coordinate: "450,300", + }, + } + + const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + + // Should contain static fallback suggestions for browser_action + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain('Simplify the "click"') + expect(followUp).toContain("Wait for specific elements") + expect(followUp).toContain("direct API calls") + expect(followUp).toContain("Reset the browser session") + }) +}) diff --git a/src/core/timeout/__tests__/timeout-integration.spec.ts b/src/core/timeout/__tests__/timeout-integration.spec.ts new file mode 100644 index 0000000000..c31a6a4134 --- /dev/null +++ b/src/core/timeout/__tests__/timeout-integration.spec.ts @@ -0,0 +1,167 @@ +// npx vitest run src/core/timeout/__tests__/timeout-integration.spec.ts + +import { describe, test, expect, beforeEach, vitest } from "vitest" +import { TimeoutManager } from "../TimeoutManager" +import { ToolExecutionWrapper } from "../ToolExecutionWrapper" +import { TimeoutFallbackHandler } from "../TimeoutFallbackHandler" +import type { Task } from "../../task/Task" + +describe("Timeout Integration Tests", () => { + beforeEach(() => { + vitest.clearAllMocks() + }) + + test("TimeoutManager should handle basic timeout operations", async () => { + const manager = TimeoutManager.getInstance() + + // Test successful operation within timeout + const result = await manager.executeWithTimeout( + async () => { + await new Promise((resolve) => setTimeout(resolve, 10)) + return "success" + }, + { + toolName: "execute_command", + timeoutMs: 100, + enableFallback: true, + }, + ) + + expect(result.success).toBe(true) + expect(result.result).toBe("success") + expect(result.timedOut).toBe(false) + }) + + test("TimeoutManager should handle timeout scenarios", async () => { + const manager = TimeoutManager.getInstance() + + // Test operation that times out + const result = await manager.executeWithTimeout( + async () => { + await new Promise((resolve) => setTimeout(resolve, 200)) + return "should not reach here" + }, + { + toolName: "execute_command", + timeoutMs: 50, + enableFallback: true, + }, + ) + + expect(result.success).toBe(false) + expect(result.timedOut).toBe(true) + expect(result.error?.message).toContain("Operation timed out") + }) + + test("ToolExecutionWrapper should wrap operations correctly", async () => { + const mockOperation = vitest.fn().mockImplementation(async (signal: AbortSignal) => { + // Simulate checking abort signal + if (signal.aborted) { + throw new Error("Operation was aborted") + } + await new Promise((resolve) => setTimeout(resolve, 10)) + return [false, "test result"] + }) + + const result = await ToolExecutionWrapper.execute( + mockOperation, + { + toolName: "execute_command", + taskId: "test-task", + timeoutMs: 100, + enableFallback: true, + }, + 100, + ) + + expect(result.success).toBe(true) + expect(result.result).toEqual([false, "test result"]) + expect(mockOperation).toHaveBeenCalledWith(expect.any(AbortSignal)) + }) + + test("ToolExecutionWrapper should handle timeout with fallback", async () => { + const mockOperation = vitest.fn().mockImplementation(async () => { + await new Promise((resolve) => setTimeout(resolve, 200)) + return [false, "should not reach here"] + }) + + const result = await ToolExecutionWrapper.execute( + mockOperation, + { + toolName: "execute_command", + taskId: "test-task", + timeoutMs: 50, + enableFallback: true, + }, + 50, + ) + + expect(result.success).toBe(false) + expect(result.timedOut).toBe(true) + expect(result.fallbackTriggered).toBe(true) + }) + + test("TimeoutFallbackHandler should create AI-powered responses", async () => { + // Create a mock task to test tool injection + const mockTask = { + assistantMessageContent: [], + cwd: "/test/dir", + } as unknown as Task + + const response = await TimeoutFallbackHandler.createTimeoutResponse( + "execute_command", + 5000, + 6000, + { command: "npm install" }, + mockTask, + ) + + // The response should contain the basic timeout information + expect(response).toContain("execute_command") + expect(response).toContain("5 seconds") + expect(response).toContain("6s") + expect(response.length).toBeGreaterThan(50) + + // The AI-generated tool call should be injected into the task's assistant message content + const toolUseBlock = mockTask.assistantMessageContent.find((block) => block.type === "tool_use") + expect(toolUseBlock).toBeDefined() + if (toolUseBlock?.type === "tool_use") { + expect(toolUseBlock.name).toBe("ask_followup_question") + expect(toolUseBlock.params?.question).toContain("timed out") + } + }) + + test("AbortSignal should be properly handled", async () => { + const mockOperation = vitest.fn().mockImplementation(async (signal: AbortSignal) => { + // Simulate a long-running operation that checks abort signal + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + if (signal.aborted) { + reject(new Error("Operation was aborted")) + } else { + resolve("success") + } + }, 100) + + signal.addEventListener("abort", () => { + clearTimeout(timeout) + reject(new Error("Operation was aborted")) + }) + }) + }) + + const result = await ToolExecutionWrapper.execute( + mockOperation, + { + toolName: "execute_command", + taskId: "test-task", + timeoutMs: 50, // Shorter timeout to trigger abort + enableFallback: false, + }, + 50, + ) + + expect(result.success).toBe(false) + expect(result.timedOut).toBe(true) + }) +}) diff --git a/src/core/timeout/__tests__/tool-injection-test.spec.ts b/src/core/timeout/__tests__/tool-injection-test.spec.ts new file mode 100644 index 0000000000..1098fd0c73 --- /dev/null +++ b/src/core/timeout/__tests__/tool-injection-test.spec.ts @@ -0,0 +1,62 @@ +import { describe, test, expect, vi, beforeEach } from "vitest" +import { TimeoutFallbackHandler } from "../TimeoutFallbackHandler" +import { Task } from "../../task/Task" + +describe("Tool Call Injection Test", () => { + let mockTask: Task + + beforeEach(() => { + // Create a minimal mock task with assistantMessageContent array + mockTask = { + assistantMessageContent: [], + cwd: "/test/dir", + } as unknown as Task + }) + + test("should inject ask_followup_question tool call into assistant message content", async () => { + // Mock the TimeoutFallbackGenerator to return a successful AI result + const mockAiResult = { + success: true, + toolCall: { + name: "ask_followup_question", + params: { + question: "What would you like to do next?", + follow_up: "Try a different approachBreak into smaller steps", + }, + }, + } + + // Mock the generateAiFallback method + vi.doMock("../TimeoutFallbackGenerator", () => ({ + TimeoutFallbackGenerator: { + generateAiFallback: vi.fn().mockResolvedValue(mockAiResult), + }, + })) + + // Call createTimeoutResponse + const response = await TimeoutFallbackHandler.createTimeoutResponse( + "execute_command", + 5000, + 6000, + { command: "npm install" }, + mockTask, + ) + + // Check that the response is just the base timeout message + expect(response).toContain("timed out after 5 seconds") + expect(response).toContain("Execution Time: 6s") + + // Check that the tool call was injected into assistantMessageContent + // The XML parser might create multiple blocks (text + tool_use), so find the tool_use block + const toolUseBlock = mockTask.assistantMessageContent.find((block) => block.type === "tool_use") + expect(toolUseBlock).toBeDefined() + expect(toolUseBlock?.type).toBe("tool_use") + expect(toolUseBlock?.name).toBe("ask_followup_question") + expect(toolUseBlock?.params?.question).toBeDefined() + expect(toolUseBlock?.params?.follow_up).toBeDefined() + + // Verify the question contains timeout information + expect(toolUseBlock?.params?.question).toContain("timed out") + expect(toolUseBlock?.params?.question).toContain("5 seconds") + }) +}) diff --git a/src/core/timeout/__tests__/ui-integration.spec.ts b/src/core/timeout/__tests__/ui-integration.spec.ts new file mode 100644 index 0000000000..f44610a857 --- /dev/null +++ b/src/core/timeout/__tests__/ui-integration.spec.ts @@ -0,0 +1,71 @@ +import { describe, it, expect, vi } from "vitest" +import { TimeoutFallbackGenerator } from "../TimeoutFallbackGenerator" +import { TimeoutFallbackHandler } from "../TimeoutFallbackHandler" + +describe("UI Integration - AI Timeout Fallbacks", () => { + it("should generate AI fallbacks using static method", async () => { + const context = { + toolName: "execute_command" as const, + timeoutMs: 30000, + executionTimeMs: 25000, + toolParams: { command: "npm install" }, + } + + const result = await TimeoutFallbackGenerator.generateAiFallback(context) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + expect(result.toolCall?.name).toBe("ask_followup_question") + expect(result.toolCall?.params.question).toContain("execute_command") + }) + + it("should create timeout response with AI fallbacks", async () => { + const response = await TimeoutFallbackHandler.createTimeoutResponse("execute_command", 30000, 25000, { + command: "npm install", + }) + + expect(response).toContain("execute_command") + expect(response).toContain("timed out") + expect(response.length).toBeGreaterThan(100) // Should contain substantial content + }) + + it("should create timeout response when AI fallbacks fail", async () => { + const response = await TimeoutFallbackHandler.createTimeoutResponse("execute_command", 30000, 25000, { + command: "npm install", + }) + + expect(response).toContain("execute_command") + expect(response).toContain("timed out") + expect(response.length).toBeGreaterThan(50) // Should contain basic timeout message + }) + + it("should validate UI setting flow", () => { + // This test validates that timeout settings can be toggled + const settings = { + timeoutFallbackEnabled: true, + toolExecutionTimeoutMs: 30000, + } + + // Simulate UI toggle + settings.timeoutFallbackEnabled = false + expect(settings.timeoutFallbackEnabled).toBe(false) + + // Simulate timeout duration change + settings.toolExecutionTimeoutMs = 60000 + expect(settings.toolExecutionTimeoutMs).toBe(60000) + }) + + it("should handle different tool types with AI fallbacks", async () => { + const commandResponse = await TimeoutFallbackHandler.createTimeoutResponse("execute_command", 30000, 25000, { + command: "npm test", + }) + + const browserResponse = await TimeoutFallbackHandler.createTimeoutResponse("browser_action", 30000, 25000, { + action: "click", + }) + + expect(commandResponse).toContain("execute_command") + expect(browserResponse).toContain("browser_action") + expect(commandResponse).not.toEqual(browserResponse) + }) +}) diff --git a/src/core/timeout/index.ts b/src/core/timeout/index.ts new file mode 100644 index 0000000000..a13e152e60 --- /dev/null +++ b/src/core/timeout/index.ts @@ -0,0 +1,8 @@ +export { TimeoutManager, timeoutManager } from "./TimeoutManager" +export { ToolExecutionWrapper } from "./ToolExecutionWrapper" +export { TimeoutFallbackHandler } from "./TimeoutFallbackHandler" +export { TimeoutFallbackGenerator } from "./TimeoutFallbackGenerator" + +export type { TimeoutConfig, TimeoutResult, TimeoutEvent } from "./TimeoutManager" +export type { ToolExecutionOptions } from "./ToolExecutionWrapper" +export type { TimeoutFallbackContext, TimeoutFallbackResult } from "./TimeoutFallbackGenerator" diff --git a/src/core/tools/executeCommandTool.ts b/src/core/tools/executeCommandTool.ts index 795beccc06..f1ca671143 100644 --- a/src/core/tools/executeCommandTool.ts +++ b/src/core/tools/executeCommandTool.ts @@ -14,6 +14,7 @@ import { unescapeHtmlEntities } from "../../utils/text-normalization" import { ExitCodeDetails, RooTerminalCallbacks, RooTerminalProcess } from "../../integrations/terminal/types" import { TerminalRegistry } from "../../integrations/terminal/TerminalRegistry" import { Terminal } from "../../integrations/terminal/Terminal" +import { ToolExecutionWrapper, TimeoutFallbackHandler } from "../timeout" class ShellIntegrationError extends Error {} @@ -60,7 +61,11 @@ export async function executeCommandTool( const executionId = cline.lastMessageTs?.toString() ?? Date.now().toString() const clineProvider = await cline.providerRef.deref() const clineProviderState = await clineProvider?.getState() - const { terminalOutputLineLimit = 500, terminalShellIntegrationDisabled = false } = clineProviderState ?? {} + const { + terminalOutputLineLimit = 500, + terminalShellIntegrationDisabled = false, + toolExecutionTimeoutMs = 300000, // 5 minutes default + } = clineProviderState ?? {} const options: ExecuteCommandOptions = { executionId, @@ -68,6 +73,7 @@ export async function executeCommandTool( customCwd, terminalShellIntegrationDisabled, terminalOutputLineLimit, + timeoutMs: toolExecutionTimeoutMs, } try { @@ -113,6 +119,7 @@ export type ExecuteCommandOptions = { customCwd?: string terminalShellIntegrationDisabled?: boolean terminalOutputLineLimit?: number + timeoutMs?: number } export async function executeCommand( @@ -123,7 +130,66 @@ export async function executeCommand( customCwd, terminalShellIntegrationDisabled = false, terminalOutputLineLimit = 500, + timeoutMs, }: ExecuteCommandOptions, +): Promise<[boolean, ToolResponse]> { + // Get timeout from settings if not provided + const clineProvider = await cline.providerRef.deref() + const clineProviderState = await clineProvider?.getState() + const defaultTimeoutMs = clineProviderState?.toolExecutionTimeoutMs ?? 300000 // 5 minutes default + const actualTimeoutMs = timeoutMs ?? defaultTimeoutMs + const timeoutFallbackEnabled = clineProviderState?.timeoutFallbackEnabled ?? true + + // Wrap the command execution with timeout + const timeoutResult = await ToolExecutionWrapper.execute( + async (signal: AbortSignal) => { + return executeCommandInternal(cline, { + executionId, + command, + customCwd, + terminalShellIntegrationDisabled, + terminalOutputLineLimit, + signal, + }) + }, + { + toolName: "execute_command", + taskId: cline.taskId, + timeoutMs: actualTimeoutMs, + enableFallback: timeoutFallbackEnabled, + }, + actualTimeoutMs, + ) + + // Handle timeout result + if (timeoutResult.timedOut && timeoutResult.fallbackTriggered) { + const fallbackResponse = await TimeoutFallbackHandler.createTimeoutResponse( + "execute_command", + actualTimeoutMs, + timeoutResult.executionTimeMs, + { command }, + cline, + ) + return [false, fallbackResponse] + } + + if (!timeoutResult.success) { + return [false, formatResponse.toolError(timeoutResult.error?.message)] + } + + return timeoutResult.result! +} + +async function executeCommandInternal( + cline: Task, + { + executionId, + command, + customCwd, + terminalShellIntegrationDisabled = false, + terminalOutputLineLimit = 500, + signal, + }: ExecuteCommandOptions & { signal: AbortSignal }, ): Promise<[boolean, ToolResponse]> { let workingDir: string @@ -211,8 +277,27 @@ export async function executeCommand( const process = terminal.runCommand(command, callbacks) cline.terminalProcess = process - await process - cline.terminalProcess = undefined + // Handle abort signal for timeout cancellation + const abortHandler = () => { + if (process && typeof process.abort === "function") { + process.abort() + } + cline.terminalProcess = undefined + } + + if (signal.aborted) { + abortHandler() + throw new Error("Command execution was cancelled due to timeout") + } + + signal.addEventListener("abort", abortHandler) + + try { + await process + } finally { + signal.removeEventListener("abort", abortHandler) + cline.terminalProcess = undefined + } if (shellIntegrationError) { throw new ShellIntegrationError(shellIntegrationError) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 8eb2e70a8c..3530d98c5d 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1409,6 +1409,8 @@ export class ClineProvider profileThresholds, alwaysAllowFollowupQuestions, followupAutoApproveTimeoutMs, + toolExecutionTimeoutMs, + timeoutFallbackEnabled, } = await this.getState() const telemetryKey = process.env.POSTHOG_API_KEY @@ -1522,6 +1524,8 @@ export class ClineProvider hasOpenedModeSelector: this.getGlobalState("hasOpenedModeSelector") ?? false, alwaysAllowFollowupQuestions: alwaysAllowFollowupQuestions ?? false, followupAutoApproveTimeoutMs: followupAutoApproveTimeoutMs ?? 60000, + toolExecutionTimeoutMs: toolExecutionTimeoutMs ?? 300000, + timeoutFallbackEnabled: timeoutFallbackEnabled ?? false, } } @@ -1634,6 +1638,8 @@ export class ClineProvider terminalZshP10k: stateValues.terminalZshP10k ?? false, terminalZdotdir: stateValues.terminalZdotdir ?? false, terminalCompressProgressBar: stateValues.terminalCompressProgressBar ?? true, + toolExecutionTimeoutMs: stateValues.toolExecutionTimeoutMs ?? 300000, // 5 minutes default + timeoutFallbackEnabled: stateValues.timeoutFallbackEnabled ?? false, mode: stateValues.mode ?? defaultModeSlug, language: stateValues.language ?? formatLanguage(vscode.env.language), mcpEnabled: stateValues.mcpEnabled ?? true, diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index b8e21e6040..9e819de01d 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -877,6 +877,14 @@ export const webviewMessageHandler = async ( await updateGlobalState("terminalOutputLineLimit", message.value) await provider.postStateToWebview() break + case "toolExecutionTimeoutMs": + await updateGlobalState("toolExecutionTimeoutMs", message.value) + await provider.postStateToWebview() + break + case "timeoutFallbackEnabled": + await updateGlobalState("timeoutFallbackEnabled", message.bool) + await provider.postStateToWebview() + break case "terminalShellIntegrationTimeout": await updateGlobalState("terminalShellIntegrationTimeout", message.value) await provider.postStateToWebview() diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 953c0c1070..8b89a5e3a5 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -227,6 +227,8 @@ export type ExtensionState = Pick< | "codebaseIndexConfig" | "codebaseIndexModels" | "profileThresholds" + | "toolExecutionTimeoutMs" + | "timeoutFallbackEnabled" > & { version: string clineMessages: ClineMessage[] diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index 89fa21b7b7..cbb26e9d2f 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -120,6 +120,8 @@ export interface WebviewMessage { | "terminalZshP10k" | "terminalZdotdir" | "terminalCompressProgressBar" + | "toolExecutionTimeoutMs" + | "timeoutFallbackEnabled" | "mcpEnabled" | "enableMcpServerCreation" | "searchCommits" diff --git a/webview-ui/src/components/settings/AutoApproveSettings.tsx b/webview-ui/src/components/settings/AutoApproveSettings.tsx index 71283a833b..f5685bacba 100644 --- a/webview-ui/src/components/settings/AutoApproveSettings.tsx +++ b/webview-ui/src/components/settings/AutoApproveSettings.tsx @@ -28,6 +28,8 @@ type AutoApproveSettingsProps = HTMLAttributes & { alwaysAllowFollowupQuestions?: boolean followupAutoApproveTimeoutMs?: number allowedCommands?: string[] + timeoutFallbackEnabled?: boolean + toolExecutionTimeoutMs?: number setCachedStateField: SetCachedStateField< | "alwaysAllowReadOnly" | "alwaysAllowReadOnlyOutsideWorkspace" @@ -46,6 +48,8 @@ type AutoApproveSettingsProps = HTMLAttributes & { | "followupAutoApproveTimeoutMs" | "allowedCommands" | "alwaysAllowUpdateTodoList" + | "timeoutFallbackEnabled" + | "toolExecutionTimeoutMs" > } @@ -66,6 +70,8 @@ export const AutoApproveSettings = ({ alwaysAllowFollowupQuestions, followupAutoApproveTimeoutMs = 60000, allowedCommands, + timeoutFallbackEnabled, + toolExecutionTimeoutMs, setCachedStateField, ...props }: AutoApproveSettingsProps) => { @@ -292,6 +298,50 @@ export const AutoApproveSettings = ({ )} + + {/* TIMEOUT SETTINGS */} +
+
+ +
{t("settings:autoApprove.timeout.label")}
+
+ + {/* Enable timeout handling */} +
+ setCachedStateField("timeoutFallbackEnabled", e.target.checked)} + data-testid="timeout-fallback-enabled-checkbox"> + + {t("settings:autoApprove.timeout.timeoutFallbackEnabled.label")} + + +
+ {t("settings:autoApprove.timeout.timeoutFallbackEnabled.description")} +
+
+ + {/* Tool execution timeout duration */} +
+
+ {t("settings:autoApprove.timeout.toolExecutionTimeoutMs.label")} +
+ setCachedStateField("toolExecutionTimeoutMs", parseInt(e.target.value))} + disabled={!timeoutFallbackEnabled} + className="w-32" + data-testid="tool-execution-timeout-input" + /> +
+ {t("settings:autoApprove.timeout.toolExecutionTimeoutMs.description")} +
+
+
) diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx index 3ece8146af..fcb026ebb9 100644 --- a/webview-ui/src/components/settings/SettingsView.tsx +++ b/webview-ui/src/components/settings/SettingsView.tsx @@ -176,6 +176,8 @@ const SettingsView = forwardRef(({ onDone, t profileThresholds, alwaysAllowFollowupQuestions, followupAutoApproveTimeoutMs, + timeoutFallbackEnabled, + toolExecutionTimeoutMs, } = cachedState const apiConfiguration = useMemo(() => cachedState.apiConfiguration ?? {}, [cachedState.apiConfiguration]) @@ -315,6 +317,8 @@ const SettingsView = forwardRef(({ onDone, t vscode.postMessage({ type: "alwaysAllowSubtasks", bool: alwaysAllowSubtasks }) vscode.postMessage({ type: "alwaysAllowFollowupQuestions", bool: alwaysAllowFollowupQuestions }) vscode.postMessage({ type: "followupAutoApproveTimeoutMs", value: followupAutoApproveTimeoutMs }) + vscode.postMessage({ type: "timeoutFallbackEnabled", bool: timeoutFallbackEnabled }) + vscode.postMessage({ type: "toolExecutionTimeoutMs", value: toolExecutionTimeoutMs }) vscode.postMessage({ type: "condensingApiConfigId", text: condensingApiConfigId || "" }) vscode.postMessage({ type: "updateCondensingPrompt", text: customCondensingPrompt || "" }) vscode.postMessage({ type: "updateSupportPrompt", values: customSupportPrompts || {} }) @@ -608,6 +612,8 @@ const SettingsView = forwardRef(({ onDone, t alwaysAllowFollowupQuestions={alwaysAllowFollowupQuestions} followupAutoApproveTimeoutMs={followupAutoApproveTimeoutMs} allowedCommands={allowedCommands} + timeoutFallbackEnabled={timeoutFallbackEnabled} + toolExecutionTimeoutMs={toolExecutionTimeoutMs} setCachedStateField={setCachedStateField} /> )} diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index df7cee5627..1bc78e3634 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -44,6 +44,10 @@ export interface ExtensionStateContextType extends ExtensionState { setAlwaysAllowFollowupQuestions: (value: boolean) => void // Setter for the new property followupAutoApproveTimeoutMs: number | undefined // Timeout in ms for auto-approving follow-up questions setFollowupAutoApproveTimeoutMs: (value: number) => void // Setter for the timeout + timeoutFallbackEnabled?: boolean // New property for timeout fallback enabled + setTimeoutFallbackEnabled: (value: boolean) => void // Setter for timeout fallback enabled + toolExecutionTimeoutMs?: number // New property for tool execution timeout + setToolExecutionTimeoutMs: (value: number) => void // Setter for tool execution timeout condensingApiConfigId?: string setCondensingApiConfigId: (value: string) => void customCondensingPrompt?: string @@ -224,6 +228,9 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode }, codebaseIndexModels: { ollama: {}, openai: {} }, alwaysAllowUpdateTodoList: true, + // Timeout settings + timeoutFallbackEnabled: false, // Default to disabled + toolExecutionTimeoutMs: 300000, // 5 minutes default }) const [didHydrateState, setDidHydrateState] = useState(false) @@ -237,6 +244,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode const [marketplaceItems, setMarketplaceItems] = useState([]) const [alwaysAllowFollowupQuestions, setAlwaysAllowFollowupQuestions] = useState(false) // Add state for follow-up questions auto-approve const [followupAutoApproveTimeoutMs, setFollowupAutoApproveTimeoutMs] = useState(undefined) // Will be set from global settings + const [timeoutFallbackEnabled, setTimeoutFallbackEnabledState] = useState(false) // Add state for timeout fallback enabled + const [toolExecutionTimeoutMs, setToolExecutionTimeoutMsState] = useState(300000) // Add state for tool execution timeout (5 minutes default) const [marketplaceInstalledMetadata, setMarketplaceInstalledMetadata] = useState({ project: {}, global: {}, @@ -274,6 +283,13 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode if ((newState as any).followupAutoApproveTimeoutMs !== undefined) { setFollowupAutoApproveTimeoutMs((newState as any).followupAutoApproveTimeoutMs) } + // Update timeout settings if present in state message + if ((newState as any).timeoutFallbackEnabled !== undefined) { + setTimeoutFallbackEnabledState((newState as any).timeoutFallbackEnabled) + } + if ((newState as any).toolExecutionTimeoutMs !== undefined) { + setToolExecutionTimeoutMsState((newState as any).toolExecutionTimeoutMs) + } // Handle marketplace data if present in state message if (newState.marketplaceItems !== undefined) { setMarketplaceItems(newState.marketplaceItems) @@ -373,6 +389,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode profileThresholds: state.profileThresholds ?? {}, alwaysAllowFollowupQuestions, followupAutoApproveTimeoutMs, + timeoutFallbackEnabled, + toolExecutionTimeoutMs, setExperimentEnabled: (id, enabled) => setState((prevState) => ({ ...prevState, experiments: { ...prevState.experiments, [id]: enabled } })), setApiConfiguration, @@ -466,6 +484,14 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setAlwaysAllowUpdateTodoList: (value) => { setState((prevState) => ({ ...prevState, alwaysAllowUpdateTodoList: value })) }, + setTimeoutFallbackEnabled: (value) => { + setState((prevState) => ({ ...prevState, timeoutFallbackEnabled: value })) + setTimeoutFallbackEnabledState(value) + }, + setToolExecutionTimeoutMs: (value) => { + setState((prevState) => ({ ...prevState, toolExecutionTimeoutMs: value })) + setToolExecutionTimeoutMsState(value) + }, } return {children} diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index ea7191f224..5b200778bb 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -170,6 +170,18 @@ "title": "Max Requests", "description": "Automatically make this many API requests before asking for approval to continue with the task.", "unlimited": "Unlimited" + }, + "timeout": { + "label": "Timeout", + "description": "Configure how Roo handles tool operations that exceed their timeout limits", + "timeoutFallbackEnabled": { + "label": "Enable timeout handling", + "description": "Enable automatic timeout detection and fallback suggestions for long-running operations" + }, + "toolExecutionTimeoutMs": { + "label": "Tool execution timeout (ms)", + "description": "Maximum time to wait for tool operations before triggering timeout handling (1000-1800000ms)" + } } }, "providers": { From 28ab1c20caf860ed3815c254963098a4d287ce97 Mon Sep 17 00:00:00 2001 From: Will Li Date: Tue, 8 Jul 2025 08:48:49 -0700 Subject: [PATCH 02/12] display error and refactor --- packages/types/src/message.ts | 2 + .../timeout-fallback-responses.spec.ts | 135 ++++++++++ .../__tests__/timeout-fallback.spec.ts | 134 +++++++++ .../prompts/instructions/timeout-fallback.ts | 106 ++++++++ src/core/prompts/responses.ts | 136 ++++++++++ src/core/timeout/TimeoutFallbackGenerator.ts | 254 +----------------- src/core/timeout/TimeoutFallbackHandler.ts | 14 +- .../__tests__/timeout-integration.spec.ts | 1 + src/core/timeout/index.ts | 3 +- webview-ui/src/components/chat/ChatRow.tsx | 5 + webview-ui/src/i18n/locales/en/chat.json | 1 + 11 files changed, 543 insertions(+), 248 deletions(-) create mode 100644 src/core/prompts/__tests__/timeout-fallback-responses.spec.ts create mode 100644 src/core/prompts/instructions/__tests__/timeout-fallback.spec.ts create mode 100644 src/core/prompts/instructions/timeout-fallback.ts diff --git a/packages/types/src/message.ts b/packages/types/src/message.ts index 49d5203c66..9493ada3c3 100644 --- a/packages/types/src/message.ts +++ b/packages/types/src/message.ts @@ -80,6 +80,7 @@ export type ClineAsk = z.infer * - `condense_context`: Context condensation/summarization has started * - `condense_context_error`: Error occurred during context condensation * - `codebase_search_result`: Results from searching the codebase + * - `tool_timeout`: Indicates a tool operation has timed out */ export const clineSays = [ "error", @@ -107,6 +108,7 @@ export const clineSays = [ "condense_context_error", "codebase_search_result", "user_edit_todos", + "tool_timeout", ] as const export const clineSaySchema = z.enum(clineSays) diff --git a/src/core/prompts/__tests__/timeout-fallback-responses.spec.ts b/src/core/prompts/__tests__/timeout-fallback-responses.spec.ts new file mode 100644 index 0000000000..30b53f1581 --- /dev/null +++ b/src/core/prompts/__tests__/timeout-fallback-responses.spec.ts @@ -0,0 +1,135 @@ +import { describe, it, expect } from "vitest" +import { formatResponse } from "../responses" + +describe("timeout fallback responses", () => { + describe("generateContextualSuggestions", () => { + it("should generate execute_command suggestions", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateContextualSuggestions( + "execute_command", + { command: "npm install" }, + ) + + expect(suggestions).toHaveLength(4) + expect(suggestions[0].text).toContain("npm install") + expect(suggestions[0].text).toContain("smaller, sequential steps") + }) + + it("should generate read_file suggestions", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateContextualSuggestions("read_file", { + path: "/large/file.txt", + }) + + expect(suggestions).toHaveLength(4) + expect(suggestions[0].text).toContain("/large/file.txt") + expect(suggestions[0].text).toContain("smaller chunks") + }) + + it("should generate write_to_file suggestions", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateContextualSuggestions( + "write_to_file", + { path: "/output/file.js" }, + ) + + expect(suggestions).toHaveLength(4) + expect(suggestions[0].text).toContain("/output/file.js") + expect(suggestions[0].text).toContain("insert_content") + }) + + it("should generate browser_action suggestions", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateContextualSuggestions( + "browser_action", + { action: "click" }, + ) + + expect(suggestions).toHaveLength(4) + expect(suggestions[0].text).toContain("click") + expect(suggestions[0].text).toContain("smaller, more targeted steps") + }) + + it("should generate search_files suggestions", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateContextualSuggestions( + "search_files", + { regex: "complex.*pattern" }, + ) + + expect(suggestions).toHaveLength(4) + expect(suggestions[0].text).toContain("Narrow the search scope") + }) + + it("should generate generic suggestions for unknown tools", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateContextualSuggestions( + "unknown_tool" as any, + ) + + expect(suggestions).toHaveLength(4) + expect(suggestions[0].text).toContain("unknown_tool operation") + expect(suggestions[0].text).toContain("smaller steps") + }) + }) + + describe("individual suggestion generators", () => { + it("should generate command suggestions with default command name", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateCommandSuggestions() + + expect(suggestions).toHaveLength(4) + expect(suggestions[0].text).toContain("the command") + }) + + it("should generate read file suggestions with default file name", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateReadFileSuggestions() + + expect(suggestions).toHaveLength(4) + expect(suggestions[0].text).toContain("the file") + }) + + it("should generate write file suggestions with default file name", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateWriteFileSuggestions() + + expect(suggestions).toHaveLength(4) + expect(suggestions[0].text).toContain("the file") + }) + + it("should generate browser suggestions with default action name", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateBrowserSuggestions() + + expect(suggestions).toHaveLength(4) + expect(suggestions[0].text).toContain("browser action") + }) + + it("should generate search suggestions", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateSearchSuggestions() + + expect(suggestions).toHaveLength(4) + expect(suggestions[0].text).toContain("Narrow the search scope") + }) + + it("should generate generic suggestions", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateGenericSuggestions("new_task") + + expect(suggestions).toHaveLength(4) + expect(suggestions[0].text).toContain("new_task operation") + }) + }) + + describe("suggestion structure", () => { + it("should return suggestions with text property", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateGenericSuggestions("new_task") + + suggestions.forEach((suggestion) => { + expect(suggestion).toHaveProperty("text") + expect(typeof suggestion.text).toBe("string") + expect(suggestion.text.length).toBeGreaterThan(0) + }) + }) + + it("should optionally include mode property", () => { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateGenericSuggestions("new_task") + + suggestions.forEach((suggestion) => { + if (suggestion.mode) { + expect(typeof suggestion.mode).toBe("string") + } + }) + }) + }) +}) diff --git a/src/core/prompts/instructions/__tests__/timeout-fallback.spec.ts b/src/core/prompts/instructions/__tests__/timeout-fallback.spec.ts new file mode 100644 index 0000000000..4e941d1208 --- /dev/null +++ b/src/core/prompts/instructions/__tests__/timeout-fallback.spec.ts @@ -0,0 +1,134 @@ +import { describe, it, expect } from "vitest" +import { + createTimeoutFallbackPrompt, + parseTimeoutFallbackResponse, + type TimeoutFallbackContext, +} from "../timeout-fallback" + +describe("timeout-fallback", () => { + describe("createTimeoutFallbackPrompt", () => { + it("should create a basic prompt with required context", () => { + const context: TimeoutFallbackContext = { + toolName: "execute_command", + timeoutMs: 30000, + executionTimeMs: 32000, + } + + const prompt = createTimeoutFallbackPrompt(context) + + expect(prompt).toContain("execute_command operation has timed out after 30 seconds") + expect(prompt).toContain("actual execution time: 32 seconds") + expect(prompt).toContain("Tool: execute_command") + expect(prompt).toContain("Generate exactly 3-4 specific, actionable suggestions") + }) + + it("should include tool parameters when provided", () => { + const context: TimeoutFallbackContext = { + toolName: "read_file", + timeoutMs: 15000, + executionTimeMs: 16000, + toolParams: { + path: "/large/file.txt", + line_range: "1-10000", + }, + } + + const prompt = createTimeoutFallbackPrompt(context) + + expect(prompt).toContain("Parameters:") + expect(prompt).toContain("/large/file.txt") + expect(prompt).toContain("1-10000") + }) + + it("should include task context when provided", () => { + const context: TimeoutFallbackContext = { + toolName: "write_to_file", + timeoutMs: 20000, + executionTimeMs: 22000, + taskContext: { + currentStep: "Creating configuration file", + workingDirectory: "/project/config", + }, + } + + const prompt = createTimeoutFallbackPrompt(context) + + expect(prompt).toContain("Current step: Creating configuration file") + expect(prompt).toContain("Working directory: /project/config") + }) + }) + + describe("parseTimeoutFallbackResponse", () => { + it("should parse numbered list responses", () => { + const response = `Here are the suggestions: +1. Break the command into smaller parts +2. Use background execution with nohup +3. Try an alternative approach +4. Increase the timeout setting` + + const suggestions = parseTimeoutFallbackResponse(response) + + expect(suggestions).toHaveLength(4) + expect(suggestions[0].text).toBe("Break the command into smaller parts") + expect(suggestions[1].text).toBe("Use background execution with nohup") + expect(suggestions[2].text).toBe("Try an alternative approach") + expect(suggestions[3].text).toBe("Increase the timeout setting") + }) + + it("should parse numbered list with parentheses", () => { + const response = `Suggestions: +1) Check file permissions +2) Use smaller chunks +3) Try a different tool` + + const suggestions = parseTimeoutFallbackResponse(response) + + expect(suggestions).toHaveLength(3) + expect(suggestions[0].text).toBe("Check file permissions") + expect(suggestions[1].text).toBe("Use smaller chunks") + expect(suggestions[2].text).toBe("Try a different tool") + }) + + it("should fallback to sentence parsing when no numbered list found", () => { + const response = `You should try breaking the operation into smaller parts. Consider using an alternative approach. Check system resources and try again.` + + const suggestions = parseTimeoutFallbackResponse(response) + + expect(suggestions.length).toBeGreaterThan(0) + expect(suggestions[0].text).toBe("You should try breaking the operation into smaller parts") + }) + + it("should limit suggestions to 4 items", () => { + const response = `1. First suggestion +2. Second suggestion +3. Third suggestion +4. Fourth suggestion +5. Fifth suggestion +6. Sixth suggestion` + + const suggestions = parseTimeoutFallbackResponse(response) + + expect(suggestions).toHaveLength(4) + }) + + it("should filter out suggestions that are too long", () => { + const response = `1. Good suggestion +2. This is a very long suggestion that exceeds the maximum character limit and should be filtered out because it's too verbose +3. Another good suggestion` + + const suggestions = parseTimeoutFallbackResponse(response) + + expect(suggestions).toHaveLength(2) + expect(suggestions[0].text).toBe("Good suggestion") + expect(suggestions[1].text).toBe("Another good suggestion") + }) + + it("should return empty array for invalid responses", () => { + const response = "" + + const suggestions = parseTimeoutFallbackResponse(response) + + expect(suggestions).toHaveLength(0) + }) + }) +}) diff --git a/src/core/prompts/instructions/timeout-fallback.ts b/src/core/prompts/instructions/timeout-fallback.ts new file mode 100644 index 0000000000..a77b1e8a9a --- /dev/null +++ b/src/core/prompts/instructions/timeout-fallback.ts @@ -0,0 +1,106 @@ +import type { ToolName } from "@roo-code/types" + +export interface TimeoutFallbackContext { + toolName: ToolName + timeoutMs: number + executionTimeMs: number + toolParams?: Record + errorMessage?: string + taskContext?: { + currentStep?: string + previousActions?: string[] + workingDirectory?: string + } +} + +/** + * Create a prompt for the AI to generate contextual timeout fallback suggestions + */ +export function createTimeoutFallbackPrompt(context: TimeoutFallbackContext): string { + const { toolName, timeoutMs, executionTimeMs, toolParams, taskContext } = context + + const timeoutSeconds = Math.round(timeoutMs / 1000) + const executionSeconds = Math.round(executionTimeMs / 1000) + + let prompt = `A ${toolName} operation has timed out after ${timeoutSeconds} seconds (actual execution time: ${executionSeconds} seconds). + +Context: +- Tool: ${toolName} +- Timeout limit: ${timeoutSeconds}s +- Actual execution time: ${executionSeconds}s` + + // Add tool-specific context + if (toolParams) { + prompt += `\n- Parameters: ${JSON.stringify(toolParams, null, 2)}` + } + + // Add task context if available + if (taskContext) { + if (taskContext.currentStep) { + prompt += `\n- Current step: ${taskContext.currentStep}` + } + if (taskContext.workingDirectory) { + prompt += `\n- Working directory: ${taskContext.workingDirectory}` + } + } + + prompt += ` + +Generate exactly 3-4 specific, actionable suggestions for how to proceed after this timeout. Each suggestion should be: +1. Contextually relevant to the specific ${toolName} operation that timed out +2. Actionable and specific (not generic advice) +3. Focused on solving the immediate problem +4. Ordered by likelihood of success + +Format your response as a simple numbered list: +1. [First suggestion] +2. [Second suggestion] +3. [Third suggestion] +4. [Fourth suggestion (optional)] + +Focus on practical solutions like: +- Breaking the operation into smaller parts +- Using alternative tools or methods +- Adjusting parameters or settings +- Checking for underlying issues +- Optimizing the approach + +Keep each suggestion concise (under 80 characters) and actionable.` + + return prompt +} + +/** + * Parse AI response to extract suggestions + */ +export function parseTimeoutFallbackResponse(response: string): Array<{ text: string; mode?: string }> { + const suggestions: Array<{ text: string; mode?: string }> = [] + + // Look for numbered list items + const lines = response.split("\n") + for (const line of lines) { + const trimmed = line.trim() + + // Match patterns like "1. suggestion", "2) suggestion", etc. + const match = trimmed.match(/^(\d+)[.)]\s*(.+)$/) + if (match && match[2]) { + const suggestionText = match[2].trim() + if (suggestionText.length > 0 && suggestionText.length <= 120) { + suggestions.push({ text: suggestionText }) + } + } + } + + // If no numbered list found, try to extract sentences + if (suggestions.length === 0) { + const sentences = response + .split(/[.!?]+/) + .map((s) => s.trim()) + .filter((s) => s.length > 10 && s.length <= 120) + for (let i = 0; i < Math.min(4, sentences.length); i++) { + suggestions.push({ text: sentences[i] }) + } + } + + return suggestions.slice(0, 4) // Limit to 4 suggestions +} diff --git a/src/core/prompts/responses.ts b/src/core/prompts/responses.ts index d2d513db57..f3c629101b 100644 --- a/src/core/prompts/responses.ts +++ b/src/core/prompts/responses.ts @@ -3,6 +3,7 @@ import * as path from "path" import * as diff from "diff" import { RooIgnoreController, LOCK_TEXT_SYMBOL } from "../ignore/RooIgnoreController" import { RooProtectedController } from "../protect/RooProtectedController" +import type { ToolName } from "@roo-code/types" export const formatResponse = { toolDenied: () => `The user denied this operation.`, @@ -185,6 +186,141 @@ Otherwise, if you have not completed the task and do not need additional informa const prettyPatchLines = lines.slice(4) return prettyPatchLines.join("\n") }, + + /** + * Generate contextual timeout fallback suggestions based on tool type and parameters + */ + timeoutFallbackSuggestions: { + generateContextualSuggestions: ( + toolName: ToolName, + toolParams?: Record, + ): Array<{ text: string; mode?: string }> => { + switch (toolName) { + case "execute_command": + return formatResponse.timeoutFallbackSuggestions.generateCommandSuggestions(toolParams) + case "read_file": + return formatResponse.timeoutFallbackSuggestions.generateReadFileSuggestions(toolParams) + case "write_to_file": + return formatResponse.timeoutFallbackSuggestions.generateWriteFileSuggestions(toolParams) + case "browser_action": + return formatResponse.timeoutFallbackSuggestions.generateBrowserSuggestions(toolParams) + case "search_files": + return formatResponse.timeoutFallbackSuggestions.generateSearchSuggestions(toolParams) + default: + return formatResponse.timeoutFallbackSuggestions.generateGenericSuggestions(toolName) + } + }, + + generateCommandSuggestions: (params?: Record): Array<{ text: string; mode?: string }> => { + const command = params?.command || "the command" + + return [ + { + text: `Break "${command}" into smaller, sequential steps that can complete faster`, + }, + { + text: `Run "${command}" in the background using '&' or 'nohup' to avoid blocking`, + }, + { + text: `Try an alternative approach or tool to accomplish the same goal`, + }, + { + text: `Increase the timeout setting if this operation legitimately needs more time`, + }, + ] + }, + + generateReadFileSuggestions: (params?: Record): Array<{ text: string; mode?: string }> => { + const filePath = params?.path || "the file" + + return [ + { + text: `Read "${filePath}" in smaller chunks using line ranges`, + }, + { + text: `Check if "${filePath}" is accessible and not locked by another process`, + }, + { + text: `Use a different approach to access the file content`, + }, + { + text: `Increase the timeout if this is a legitimately large file`, + }, + ] + }, + + generateWriteFileSuggestions: (params?: Record): Array<{ text: string; mode?: string }> => { + const filePath = params?.path || "the file" + + return [ + { + text: `Write to "${filePath}" incrementally using insert_content instead`, + }, + { + text: `Check if "${filePath}" is writable and not locked`, + }, + { + text: `Use apply_diff for targeted changes instead of full file replacement`, + }, + { + text: `Break the content into smaller write operations`, + }, + ] + }, + + generateBrowserSuggestions: (params?: Record): Array<{ text: string; mode?: string }> => { + const action = params?.action || "browser action" + + return [ + { + text: `Simplify the "${action}" into smaller, more targeted steps`, + }, + { + text: `Wait for specific elements to load before proceeding`, + }, + { + text: `Use direct API calls instead of browser automation if possible`, + }, + { + text: `Reset the browser session and try again`, + }, + ] + }, + + generateSearchSuggestions: (params?: Record): Array<{ text: string; mode?: string }> => { + return [ + { + text: `Narrow the search scope to specific directories`, + }, + { + text: `Use simpler search patterns or literal strings`, + }, + { + text: `Apply file type filters to reduce search space`, + }, + { + text: `Search incrementally in smaller batches`, + }, + ] + }, + + generateGenericSuggestions: (toolName: ToolName): Array<{ text: string; mode?: string }> => { + return [ + { + text: `Break the ${toolName} operation into smaller steps`, + }, + { + text: `Try an alternative approach to accomplish the same goal`, + }, + { + text: `Check system resources and try again`, + }, + { + text: `Increase the timeout setting for this operation`, + }, + ] + }, + }, } // to avoid circular dependency diff --git a/src/core/timeout/TimeoutFallbackGenerator.ts b/src/core/timeout/TimeoutFallbackGenerator.ts index 2a26fd9b25..ffc1c29390 100644 --- a/src/core/timeout/TimeoutFallbackGenerator.ts +++ b/src/core/timeout/TimeoutFallbackGenerator.ts @@ -1,19 +1,12 @@ import type { ToolName } from "@roo-code/types" import type { Task } from "../task/Task" import type { SingleCompletionHandler } from "../../api" - -export interface TimeoutFallbackContext { - toolName: ToolName - timeoutMs: number - executionTimeMs: number - toolParams?: Record - errorMessage?: string - taskContext?: { - currentStep?: string - previousActions?: string[] - workingDirectory?: string - } -} +import { + createTimeoutFallbackPrompt, + parseTimeoutFallbackResponse, + type TimeoutFallbackContext, +} from "../prompts/instructions/timeout-fallback" +import { formatResponse } from "../prompts/responses" export interface TimeoutFallbackResult { success: boolean @@ -67,11 +60,11 @@ export class TimeoutFallbackGenerator { apiHandler: SingleCompletionHandler, ): Promise { try { - const prompt = this.createAiPrompt(context) + const prompt = createTimeoutFallbackPrompt(context) const aiResponse = await apiHandler.completePrompt(prompt) // Parse the AI response to extract suggestions - const suggestions = this.parseAiResponse(aiResponse) + const suggestions = parseTimeoutFallbackResponse(aiResponse) if (suggestions.length === 0) { throw new Error("No valid suggestions generated by AI") @@ -105,103 +98,14 @@ export class TimeoutFallbackGenerator { } } - /** - * Create a prompt for the AI to generate contextual timeout fallback suggestions - */ - private static createAiPrompt(context: TimeoutFallbackContext): string { - const { toolName, timeoutMs, executionTimeMs, toolParams, taskContext } = context - - const timeoutSeconds = Math.round(timeoutMs / 1000) - const executionSeconds = Math.round(executionTimeMs / 1000) - - let prompt = `A ${toolName} operation has timed out after ${timeoutSeconds} seconds (actual execution time: ${executionSeconds} seconds). - -Context: -- Tool: ${toolName} -- Timeout limit: ${timeoutSeconds}s -- Actual execution time: ${executionSeconds}s` - - // Add tool-specific context - if (toolParams) { - prompt += `\n- Parameters: ${JSON.stringify(toolParams, null, 2)}` - } - - // Add task context if available - if (taskContext) { - if (taskContext.currentStep) { - prompt += `\n- Current step: ${taskContext.currentStep}` - } - if (taskContext.workingDirectory) { - prompt += `\n- Working directory: ${taskContext.workingDirectory}` - } - } - - prompt += ` - -Generate exactly 3-4 specific, actionable suggestions for how to proceed after this timeout. Each suggestion should be: -1. Contextually relevant to the specific ${toolName} operation that timed out -2. Actionable and specific (not generic advice) -3. Focused on solving the immediate problem -4. Ordered by likelihood of success - -Format your response as a simple numbered list: -1. [First suggestion] -2. [Second suggestion] -3. [Third suggestion] -4. [Fourth suggestion (optional)] - -Focus on practical solutions like: -- Breaking the operation into smaller parts -- Using alternative tools or methods -- Adjusting parameters or settings -- Checking for underlying issues -- Optimizing the approach - -Keep each suggestion concise (under 80 characters) and actionable.` - - return prompt - } - - /** - * Parse AI response to extract suggestions - */ - private static parseAiResponse(response: string): Array<{ text: string; mode?: string }> { - const suggestions: Array<{ text: string; mode?: string }> = [] - - // Look for numbered list items - const lines = response.split("\n") - for (const line of lines) { - const trimmed = line.trim() - - // Match patterns like "1. suggestion", "2) suggestion", etc. - const match = trimmed.match(/^(\d+)[.)]\s*(.+)$/) - if (match && match[2]) { - const suggestionText = match[2].trim() - if (suggestionText.length > 0 && suggestionText.length <= 120) { - suggestions.push({ text: suggestionText }) - } - } - } - - // If no numbered list found, try to extract sentences - if (suggestions.length === 0) { - const sentences = response - .split(/[.!?]+/) - .map((s) => s.trim()) - .filter((s) => s.length > 10 && s.length <= 120) - for (let i = 0; i < Math.min(4, sentences.length); i++) { - suggestions.push({ text: sentences[i] }) - } - } - - return suggestions.slice(0, 4) // Limit to 4 suggestions - } - /** * Generate static fallback suggestions when AI is unavailable */ private static generateStaticToolCall(context: TimeoutFallbackContext): TimeoutFallbackResult["toolCall"] { - const suggestions = this.generateContextualSuggestions(context) + const suggestions = formatResponse.timeoutFallbackSuggestions.generateContextualSuggestions( + context.toolName, + context.toolParams, + ) const question = `The ${context.toolName} operation timed out after ${Math.round(context.timeoutMs / 1000)} seconds. How would you like to proceed?` @@ -221,138 +125,4 @@ Keep each suggestion concise (under 80 characters) and actionable.` }, } } - - /** - * Generate contextual suggestions based on tool type and parameters - */ - private static generateContextualSuggestions( - context: TimeoutFallbackContext, - ): Array<{ text: string; mode?: string }> { - const { toolName, toolParams } = context - - switch (toolName) { - case "execute_command": - return this.generateCommandSuggestions(toolParams) - case "read_file": - return this.generateReadFileSuggestions(toolParams) - case "write_to_file": - return this.generateWriteFileSuggestions(toolParams) - case "browser_action": - return this.generateBrowserSuggestions(toolParams) - case "search_files": - return this.generateSearchSuggestions(toolParams) - default: - return this.generateGenericSuggestions(context) - } - } - - private static generateCommandSuggestions(params?: Record): Array<{ text: string; mode?: string }> { - const command = params?.command || "the command" - - return [ - { - text: `Break "${command}" into smaller, sequential steps that can complete faster`, - }, - { - text: `Run "${command}" in the background using '&' or 'nohup' to avoid blocking`, - }, - { - text: `Try an alternative approach or tool to accomplish the same goal`, - }, - { - text: `Increase the timeout setting if this operation legitimately needs more time`, - }, - ] - } - - private static generateReadFileSuggestions(params?: Record): Array<{ text: string; mode?: string }> { - const filePath = params?.path || "the file" - - return [ - { - text: `Read "${filePath}" in smaller chunks using line ranges`, - }, - { - text: `Check if "${filePath}" is accessible and not locked by another process`, - }, - { - text: `Use a different approach to access the file content`, - }, - { - text: `Increase the timeout if this is a legitimately large file`, - }, - ] - } - - private static generateWriteFileSuggestions(params?: Record): Array<{ text: string; mode?: string }> { - const filePath = params?.path || "the file" - - return [ - { - text: `Write to "${filePath}" incrementally using insert_content instead`, - }, - { - text: `Check if "${filePath}" is writable and not locked`, - }, - { - text: `Use apply_diff for targeted changes instead of full file replacement`, - }, - { - text: `Break the content into smaller write operations`, - }, - ] - } - - private static generateBrowserSuggestions(params?: Record): Array<{ text: string; mode?: string }> { - const action = params?.action || "browser action" - - return [ - { - text: `Simplify the "${action}" into smaller, more targeted steps`, - }, - { - text: `Wait for specific elements to load before proceeding`, - }, - { - text: `Use direct API calls instead of browser automation if possible`, - }, - { - text: `Reset the browser session and try again`, - }, - ] - } - - private static generateSearchSuggestions(params?: Record): Array<{ text: string; mode?: string }> { - return [ - { - text: `Narrow the search scope to specific directories`, - }, - { - text: `Use simpler search patterns or literal strings`, - }, - { - text: `Apply file type filters to reduce search space`, - }, - { - text: `Search incrementally in smaller batches`, - }, - ] - } - - private static generateGenericSuggestions(context: TimeoutFallbackContext): Array<{ text: string; mode?: string }> { - return [ - { - text: `Break the ${context.toolName} operation into smaller steps`, - }, - { - text: `Try an alternative approach to accomplish the same goal`, - }, - { - text: `Check system resources and try again`, - }, - { - text: `Increase the timeout setting for this operation`, - }, - ] - } } diff --git a/src/core/timeout/TimeoutFallbackHandler.ts b/src/core/timeout/TimeoutFallbackHandler.ts index 7e3044a3d7..0fd266c440 100644 --- a/src/core/timeout/TimeoutFallbackHandler.ts +++ b/src/core/timeout/TimeoutFallbackHandler.ts @@ -1,10 +1,7 @@ import type { ToolName } from "@roo-code/types" import { formatResponse } from "../prompts/responses" -import { - TimeoutFallbackGenerator, - type TimeoutFallbackContext, - type TimeoutFallbackResult, -} from "./TimeoutFallbackGenerator" +import type { TimeoutFallbackContext } from "../prompts/instructions/timeout-fallback" +import { TimeoutFallbackGenerator, type TimeoutFallbackResult } from "./TimeoutFallbackGenerator" import type { Task } from "../task/Task" import { parseAssistantMessage } from "../assistant-message/parseAssistantMessage" @@ -24,6 +21,13 @@ export class TimeoutFallbackHandler { ): Promise { const baseResponse = formatResponse.toolTimeout(toolName, timeoutMs, executionTimeMs) + // Create a timeout message for display in the chat + if (task) { + await task.say("tool_timeout", "", undefined, false, undefined, undefined, { + isNonInteractive: true, + }) + } + // Create context for AI fallback generation const aiContext: TimeoutFallbackContext = { toolName, diff --git a/src/core/timeout/__tests__/timeout-integration.spec.ts b/src/core/timeout/__tests__/timeout-integration.spec.ts index c31a6a4134..027677500a 100644 --- a/src/core/timeout/__tests__/timeout-integration.spec.ts +++ b/src/core/timeout/__tests__/timeout-integration.spec.ts @@ -106,6 +106,7 @@ describe("Timeout Integration Tests", () => { const mockTask = { assistantMessageContent: [], cwd: "/test/dir", + say: vitest.fn().mockResolvedValue(undefined), } as unknown as Task const response = await TimeoutFallbackHandler.createTimeoutResponse( diff --git a/src/core/timeout/index.ts b/src/core/timeout/index.ts index a13e152e60..8b1f080c71 100644 --- a/src/core/timeout/index.ts +++ b/src/core/timeout/index.ts @@ -5,4 +5,5 @@ export { TimeoutFallbackGenerator } from "./TimeoutFallbackGenerator" export type { TimeoutConfig, TimeoutResult, TimeoutEvent } from "./TimeoutManager" export type { ToolExecutionOptions } from "./ToolExecutionWrapper" -export type { TimeoutFallbackContext, TimeoutFallbackResult } from "./TimeoutFallbackGenerator" +export type { TimeoutFallbackResult } from "./TimeoutFallbackGenerator" +export type { TimeoutFallbackContext } from "../prompts/instructions/timeout-fallback" diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index 9c90da503f..ae19d3bb2a 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -258,6 +258,11 @@ export const ChatRowContent = ({ />, {t("chat:questions.hasQuestion")}, ] + case "tool_timeout": + return [ + , + {t("chat:toolTimeout")}, + ] default: return [null, null] } diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index ea4f8920f5..15f3039d1e 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -230,6 +230,7 @@ "hasQuestion": "Roo has a question:" }, "taskCompleted": "Task Completed", + "toolTimeout": "Tool Timeout", "error": "Error", "diffError": { "title": "Edit Unsuccessful" From 1c22fbbde5212c45dbc8ab1fb5f367059ecfc75a Mon Sep 17 00:00:00 2001 From: Will Li Date: Wed, 9 Jul 2025 06:25:56 -0700 Subject: [PATCH 03/12] always ask followup --- src/core/timeout/TimeoutFallbackHandler.ts | 36 ++++----- .../__tests__/timeout-integration.spec.ts | 19 +++-- .../__tests__/tool-injection-test.spec.ts | 78 +++++++++++++------ 3 files changed, 80 insertions(+), 53 deletions(-) diff --git a/src/core/timeout/TimeoutFallbackHandler.ts b/src/core/timeout/TimeoutFallbackHandler.ts index 0fd266c440..b87dd8ca01 100644 --- a/src/core/timeout/TimeoutFallbackHandler.ts +++ b/src/core/timeout/TimeoutFallbackHandler.ts @@ -3,7 +3,6 @@ import { formatResponse } from "../prompts/responses" import type { TimeoutFallbackContext } from "../prompts/instructions/timeout-fallback" import { TimeoutFallbackGenerator, type TimeoutFallbackResult } from "./TimeoutFallbackGenerator" import type { Task } from "../task/Task" -import { parseAssistantMessage } from "../assistant-message/parseAssistantMessage" /** * Generates AI-powered fallback suggestions for timeout scenarios @@ -44,36 +43,27 @@ export class TimeoutFallbackHandler { // Generate AI-powered fallback (with static fallback if AI fails) const aiResult = await TimeoutFallbackGenerator.generateAiFallback(aiContext, task) - if (aiResult.success && aiResult.toolCall && task) { - // Inject the tool call directly into the assistant message content for proper execution - this.injectToolCallIntoMessageContent(aiResult.toolCall, task) - return baseResponse - } + if (aiResult.success && aiResult.toolCall) { + // Instead of injecting the tool call, we'll return a response that instructs + // the model to ask a follow-up question in its next message + const { question, follow_up } = aiResult.toolCall.params - // This should rarely happen since generateAiFallback always provides static fallback - return `${baseResponse}\n\nThe operation timed out. Please consider breaking this into smaller steps or trying a different approach.` - } + // Format the response to explicitly instruct the model to ask the follow-up question + return `${baseResponse} - /** - * Inject a tool call directly into the assistant message content for proper parsing and execution - */ - private static injectToolCallIntoMessageContent(toolCall: TimeoutFallbackResult["toolCall"], task: Task): void { - if (toolCall?.name === "ask_followup_question" && toolCall.params) { - const { question, follow_up } = toolCall.params +The operation timed out. You MUST now use the ask_followup_question tool with the following parameters: - // Create the XML tool call string - const toolCallXml = ` + ${question} ${follow_up} -` - - // Parse the tool call XML to create proper assistant message content - const parsedContent = parseAssistantMessage(toolCallXml) + - // Add the parsed tool call to the assistant message content - task.assistantMessageContent.push(...parsedContent) +This is required to help the user decide how to proceed after the timeout.` } + + // This should rarely happen since generateAiFallback always provides static fallback + return `${baseResponse}\n\nThe operation timed out. Please consider breaking this into smaller steps or trying a different approach.` } } diff --git a/src/core/timeout/__tests__/timeout-integration.spec.ts b/src/core/timeout/__tests__/timeout-integration.spec.ts index 027677500a..5bd741e51c 100644 --- a/src/core/timeout/__tests__/timeout-integration.spec.ts +++ b/src/core/timeout/__tests__/timeout-integration.spec.ts @@ -123,13 +123,18 @@ describe("Timeout Integration Tests", () => { expect(response).toContain("6s") expect(response.length).toBeGreaterThan(50) - // The AI-generated tool call should be injected into the task's assistant message content - const toolUseBlock = mockTask.assistantMessageContent.find((block) => block.type === "tool_use") - expect(toolUseBlock).toBeDefined() - if (toolUseBlock?.type === "tool_use") { - expect(toolUseBlock.name).toBe("ask_followup_question") - expect(toolUseBlock.params?.question).toContain("timed out") - } + // The response should now contain instructions to use ask_followup_question + expect(response).toContain("You MUST now use the ask_followup_question tool") + expect(response).toContain("") + expect(response).toContain("") + expect(response).toContain("timed out") + expect(response).toContain("") + expect(response).toContain("") + expect(response).toContain("") + expect(response).toContain("") + + // Verify that assistantMessageContent was NOT modified + expect(mockTask.assistantMessageContent).toHaveLength(0) }) test("AbortSignal should be properly handled", async () => { diff --git a/src/core/timeout/__tests__/tool-injection-test.spec.ts b/src/core/timeout/__tests__/tool-injection-test.spec.ts index 1098fd0c73..8208139f03 100644 --- a/src/core/timeout/__tests__/tool-injection-test.spec.ts +++ b/src/core/timeout/__tests__/tool-injection-test.spec.ts @@ -1,8 +1,11 @@ import { describe, test, expect, vi, beforeEach } from "vitest" import { TimeoutFallbackHandler } from "../TimeoutFallbackHandler" +import { TimeoutFallbackGenerator, type TimeoutFallbackResult } from "../TimeoutFallbackGenerator" import { Task } from "../../task/Task" -describe("Tool Call Injection Test", () => { +vi.mock("../TimeoutFallbackGenerator") + +describe("Tool Call Response Test", () => { let mockTask: Task beforeEach(() => { @@ -10,28 +13,28 @@ describe("Tool Call Injection Test", () => { mockTask = { assistantMessageContent: [], cwd: "/test/dir", + say: vi.fn(), } as unknown as Task + + vi.clearAllMocks() }) - test("should inject ask_followup_question tool call into assistant message content", async () => { + test("should return response with ask_followup_question tool instructions", async () => { // Mock the TimeoutFallbackGenerator to return a successful AI result - const mockAiResult = { + const mockAiResult: TimeoutFallbackResult = { success: true, toolCall: { name: "ask_followup_question", params: { - question: "What would you like to do next?", - follow_up: "Try a different approachBreak into smaller steps", + question: "The execute_command operation timed out after 5 seconds. How would you like to proceed?", + follow_up: + "Try a different approach\nBreak into smaller steps", }, }, } // Mock the generateAiFallback method - vi.doMock("../TimeoutFallbackGenerator", () => ({ - TimeoutFallbackGenerator: { - generateAiFallback: vi.fn().mockResolvedValue(mockAiResult), - }, - })) + vi.mocked(TimeoutFallbackGenerator.generateAiFallback).mockResolvedValue(mockAiResult) // Call createTimeoutResponse const response = await TimeoutFallbackHandler.createTimeoutResponse( @@ -42,21 +45,50 @@ describe("Tool Call Injection Test", () => { mockTask, ) - // Check that the response is just the base timeout message + // Check that the response contains the base timeout message expect(response).toContain("timed out after 5 seconds") expect(response).toContain("Execution Time: 6s") - // Check that the tool call was injected into assistantMessageContent - // The XML parser might create multiple blocks (text + tool_use), so find the tool_use block - const toolUseBlock = mockTask.assistantMessageContent.find((block) => block.type === "tool_use") - expect(toolUseBlock).toBeDefined() - expect(toolUseBlock?.type).toBe("tool_use") - expect(toolUseBlock?.name).toBe("ask_followup_question") - expect(toolUseBlock?.params?.question).toBeDefined() - expect(toolUseBlock?.params?.follow_up).toBeDefined() - - // Verify the question contains timeout information - expect(toolUseBlock?.params?.question).toContain("timed out") - expect(toolUseBlock?.params?.question).toContain("5 seconds") + // Check that the response includes instructions to use ask_followup_question + expect(response).toContain("You MUST now use the ask_followup_question tool") + expect(response).toContain("") + expect(response).toContain(`${mockAiResult.toolCall?.params.question}`) + expect(response).toContain("") + expect(response).toContain(mockAiResult.toolCall?.params.follow_up) + expect(response).toContain("") + expect(response).toContain("") + expect(response).toContain("This is required to help the user decide how to proceed after the timeout.") + + // Verify that assistantMessageContent was NOT modified + expect(mockTask.assistantMessageContent).toHaveLength(0) + }) + + test("should return fallback message when AI generation fails", async () => { + // Mock the generateAiFallback to return a failure + vi.mocked(TimeoutFallbackGenerator.generateAiFallback).mockResolvedValue({ + success: false, + error: "AI generation failed", + }) + + // Call createTimeoutResponse + const response = await TimeoutFallbackHandler.createTimeoutResponse( + "execute_command", + 5000, + 6000, + { command: "npm install" }, + mockTask, + ) + + // Check that the response contains the base timeout message + expect(response).toContain("timed out after 5 seconds") + expect(response).toContain("Execution Time: 6s") + + // Check that the response contains the fallback message + expect(response).toContain( + "The operation timed out. Please consider breaking this into smaller steps or trying a different approach.", + ) + + // Should not contain ask_followup_question instructions + expect(response).not.toContain("ask_followup_question") }) }) From 21360b0d4e019ce4ff5ad494aa347c1e4228b707 Mon Sep 17 00:00:00 2001 From: Will Li Date: Wed, 9 Jul 2025 06:47:02 -0700 Subject: [PATCH 04/12] shorten execution path --- src/core/timeout/TimeoutFallbackGenerator.ts | 128 ----------------- src/core/timeout/TimeoutFallbackHandler.ts | 136 ++++++++++++++++-- .../__tests__/ai-fallback-real.spec.ts | 18 +-- .../timeout/__tests__/e2e-ai-test.spec.ts | 12 +- .../__tests__/tool-injection-test.spec.ts | 14 +- .../timeout/__tests__/ui-integration.spec.ts | 3 +- src/core/timeout/index.ts | 3 +- 7 files changed, 153 insertions(+), 161 deletions(-) delete mode 100644 src/core/timeout/TimeoutFallbackGenerator.ts diff --git a/src/core/timeout/TimeoutFallbackGenerator.ts b/src/core/timeout/TimeoutFallbackGenerator.ts deleted file mode 100644 index ffc1c29390..0000000000 --- a/src/core/timeout/TimeoutFallbackGenerator.ts +++ /dev/null @@ -1,128 +0,0 @@ -import type { ToolName } from "@roo-code/types" -import type { Task } from "../task/Task" -import type { SingleCompletionHandler } from "../../api" -import { - createTimeoutFallbackPrompt, - parseTimeoutFallbackResponse, - type TimeoutFallbackContext, -} from "../prompts/instructions/timeout-fallback" -import { formatResponse } from "../prompts/responses" - -export interface TimeoutFallbackResult { - success: boolean - toolCall?: { - name: "ask_followup_question" - params: { - question: string - follow_up: string - } - } - error?: string -} - -/** - * Generates AI-powered fallback suggestions for timeout scenarios - */ -export class TimeoutFallbackGenerator { - /** - * Generate an AI-powered ask_followup_question tool call for timeout scenarios - */ - public static async generateAiFallback( - context: TimeoutFallbackContext, - task?: Task, - ): Promise { - // Try to use AI to generate contextual suggestions - if (task?.api && "completePrompt" in task.api) { - try { - const aiResult = await this.generateAiSuggestions(context, task.api as SingleCompletionHandler) - if (aiResult.success) { - return aiResult - } - } catch (error) { - // AI failed, fall through to static suggestions - } - } - - // Fallback to static suggestions if AI fails or is unavailable - const toolCall = this.generateStaticToolCall(context) - - return { - success: true, - toolCall, - } - } - - /** - * Generate AI-powered suggestions using the task's API handler - */ - private static async generateAiSuggestions( - context: TimeoutFallbackContext, - apiHandler: SingleCompletionHandler, - ): Promise { - try { - const prompt = createTimeoutFallbackPrompt(context) - const aiResponse = await apiHandler.completePrompt(prompt) - - // Parse the AI response to extract suggestions - const suggestions = parseTimeoutFallbackResponse(aiResponse) - - if (suggestions.length === 0) { - throw new Error("No valid suggestions generated by AI") - } - - const question = `The ${context.toolName} operation timed out after ${Math.round(context.timeoutMs / 1000)} seconds. How would you like to proceed?` - - const followUpXml = suggestions - .map((suggestion) => - suggestion.mode - ? `${suggestion.text}` - : `${suggestion.text}`, - ) - .join("\n") - - return { - success: true, - toolCall: { - name: "ask_followup_question", - params: { - question, - follow_up: followUpXml, - }, - }, - } - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : "Unknown error generating AI suggestions", - } - } - } - - /** - * Generate static fallback suggestions when AI is unavailable - */ - private static generateStaticToolCall(context: TimeoutFallbackContext): TimeoutFallbackResult["toolCall"] { - const suggestions = formatResponse.timeoutFallbackSuggestions.generateContextualSuggestions( - context.toolName, - context.toolParams, - ) - - const question = `The ${context.toolName} operation timed out after ${Math.round(context.timeoutMs / 1000)} seconds. How would you like to proceed?` - - const followUpXml = suggestions - .map((suggestion) => - suggestion.mode - ? `${suggestion.text}` - : `${suggestion.text}`, - ) - .join("\n") - - return { - name: "ask_followup_question", - params: { - question, - follow_up: followUpXml, - }, - } - } -} diff --git a/src/core/timeout/TimeoutFallbackHandler.ts b/src/core/timeout/TimeoutFallbackHandler.ts index b87dd8ca01..5aaa2c62f1 100644 --- a/src/core/timeout/TimeoutFallbackHandler.ts +++ b/src/core/timeout/TimeoutFallbackHandler.ts @@ -1,15 +1,32 @@ import type { ToolName } from "@roo-code/types" -import { formatResponse } from "../prompts/responses" -import type { TimeoutFallbackContext } from "../prompts/instructions/timeout-fallback" -import { TimeoutFallbackGenerator, type TimeoutFallbackResult } from "./TimeoutFallbackGenerator" import type { Task } from "../task/Task" +import type { SingleCompletionHandler } from "../../api" +import { + createTimeoutFallbackPrompt, + parseTimeoutFallbackResponse, + type TimeoutFallbackContext, +} from "../prompts/instructions/timeout-fallback" +import { formatResponse } from "../prompts/responses" + +export interface TimeoutFallbackResult { + success: boolean + toolCall?: { + name: "ask_followup_question" + params: { + question: string + follow_up: string + } + } + error?: string +} /** - * Generates AI-powered fallback suggestions for timeout scenarios + * Unified timeout fallback handler that generates AI-powered fallback suggestions + * and creates timeout responses in a single optimized flow */ export class TimeoutFallbackHandler { /** - * Create a timeout response with AI-generated fallback question + * Create a timeout response with AI-generated fallback question in a single optimized query */ public static async createTimeoutResponse( toolName: ToolName, @@ -40,12 +57,11 @@ export class TimeoutFallbackHandler { : undefined, } - // Generate AI-powered fallback (with static fallback if AI fails) - const aiResult = await TimeoutFallbackGenerator.generateAiFallback(aiContext, task) + // Generate AI-powered fallback (with static fallback if AI fails) in a single call + const aiResult = await this.generateAiFallback(aiContext, task) if (aiResult.success && aiResult.toolCall) { - // Instead of injecting the tool call, we'll return a response that instructs - // the model to ask a follow-up question in its next message + // Return a response that instructs the model to ask a follow-up question const { question, follow_up } = aiResult.toolCall.params // Format the response to explicitly instruct the model to ask the follow-up question @@ -66,4 +82,106 @@ This is required to help the user decide how to proceed after the timeout.` // This should rarely happen since generateAiFallback always provides static fallback return `${baseResponse}\n\nThe operation timed out. Please consider breaking this into smaller steps or trying a different approach.` } + + /** + * Generate an AI-powered ask_followup_question tool call for timeout scenarios + */ + public static async generateAiFallback( + context: TimeoutFallbackContext, + task?: Task, + ): Promise { + // Try to use AI to generate contextual suggestions + if (task?.api && "completePrompt" in task.api) { + try { + const aiResult = await this.generateAiSuggestions(context, task.api as SingleCompletionHandler) + if (aiResult.success) { + return aiResult + } + } catch (error) { + // AI failed, fall through to static suggestions + } + } + + // Fallback to static suggestions if AI fails or is unavailable + const toolCall = this.generateStaticToolCall(context) + + return { + success: true, + toolCall, + } + } + + /** + * Generate AI-powered suggestions using the task's API handler + */ + private static async generateAiSuggestions( + context: TimeoutFallbackContext, + apiHandler: SingleCompletionHandler, + ): Promise { + try { + const prompt = createTimeoutFallbackPrompt(context) + const aiResponse = await apiHandler.completePrompt(prompt) + + // Parse the AI response to extract suggestions + const suggestions = parseTimeoutFallbackResponse(aiResponse) + + if (suggestions.length === 0) { + throw new Error("No valid suggestions generated by AI") + } + + const question = `The ${context.toolName} operation timed out after ${Math.round(context.timeoutMs / 1000)} seconds. How would you like to proceed?` + + const followUpXml = suggestions + .map((suggestion) => + suggestion.mode + ? `${suggestion.text}` + : `${suggestion.text}`, + ) + .join("\n") + + return { + success: true, + toolCall: { + name: "ask_followup_question", + params: { + question, + follow_up: followUpXml, + }, + }, + } + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : "Unknown error generating AI suggestions", + } + } + } + + /** + * Generate static fallback suggestions when AI is unavailable + */ + private static generateStaticToolCall(context: TimeoutFallbackContext): TimeoutFallbackResult["toolCall"] { + const suggestions = formatResponse.timeoutFallbackSuggestions.generateContextualSuggestions( + context.toolName, + context.toolParams, + ) + + const question = `The ${context.toolName} operation timed out after ${Math.round(context.timeoutMs / 1000)} seconds. How would you like to proceed?` + + const followUpXml = suggestions + .map((suggestion) => + suggestion.mode + ? `${suggestion.text}` + : `${suggestion.text}`, + ) + .join("\n") + + return { + name: "ask_followup_question", + params: { + question, + follow_up: followUpXml, + }, + } + } } diff --git a/src/core/timeout/__tests__/ai-fallback-real.spec.ts b/src/core/timeout/__tests__/ai-fallback-real.spec.ts index 021c02eb3f..7b378a2b01 100644 --- a/src/core/timeout/__tests__/ai-fallback-real.spec.ts +++ b/src/core/timeout/__tests__/ai-fallback-real.spec.ts @@ -1,14 +1,14 @@ // npx vitest run src/core/timeout/__tests__/ai-fallback-real.spec.ts import { describe, test, expect, beforeEach, vitest } from "vitest" -import { TimeoutFallbackGenerator } from "../TimeoutFallbackGenerator" +import { TimeoutFallbackHandler } from "../TimeoutFallbackHandler" import type { ApiHandler, SingleCompletionHandler } from "../../../api" import type { Task } from "../../task/Task" // Create a mock API handler that extends ApiHandler and includes completePrompt interface MockApiHandler extends ApiHandler, SingleCompletionHandler {} -describe("TimeoutFallbackGenerator - Real AI Implementation", () => { +describe("TimeoutFallbackHandler - Real AI Implementation", () => { let mockApiHandler: MockApiHandler let mockTask: Partial @@ -47,7 +47,7 @@ describe("TimeoutFallbackGenerator - Real AI Implementation", () => { toolParams: { command: "npm install" }, } - const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) expect(result.success).toBe(true) expect(result.toolCall).toBeDefined() @@ -80,7 +80,7 @@ describe("TimeoutFallbackGenerator - Real AI Implementation", () => { toolParams: { command: "npm test" }, } - const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) expect(result.success).toBe(true) expect(result.toolCall).toBeDefined() @@ -105,7 +105,7 @@ describe("TimeoutFallbackGenerator - Real AI Implementation", () => { toolParams: { path: "/large/file.txt" }, } - const result = await TimeoutFallbackGenerator.generateAiFallback(context, taskWithoutApi as Task) + const result = await TimeoutFallbackHandler.generateAiFallback(context, taskWithoutApi as Task) expect(result.success).toBe(true) expect(result.toolCall).toBeDefined() @@ -134,7 +134,7 @@ describe("TimeoutFallbackGenerator - Real AI Implementation", () => { toolParams: { command: "build script" }, } - const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) expect(result.success).toBe(true) const followUp = result.toolCall?.params.follow_up || "" @@ -157,7 +157,7 @@ describe("TimeoutFallbackGenerator - Real AI Implementation", () => { toolParams: { action: "click" }, } - const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) expect(result.success).toBe(true) const followUp = result.toolCall?.params.follow_up || "" @@ -183,7 +183,7 @@ describe("TimeoutFallbackGenerator - Real AI Implementation", () => { }, } - const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) expect(result.success).toBe(true) @@ -216,7 +216,7 @@ describe("TimeoutFallbackGenerator - Real AI Implementation", () => { toolParams: { path: "/output.txt" }, } - const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) expect(result.success).toBe(true) const followUp = result.toolCall?.params.follow_up || "" diff --git a/src/core/timeout/__tests__/e2e-ai-test.spec.ts b/src/core/timeout/__tests__/e2e-ai-test.spec.ts index 7b1fe4d23e..40bd9e5406 100644 --- a/src/core/timeout/__tests__/e2e-ai-test.spec.ts +++ b/src/core/timeout/__tests__/e2e-ai-test.spec.ts @@ -2,14 +2,14 @@ // npx vitest run src/core/timeout/__tests__/e2e-ai-test.spec.ts import { describe, test, expect, beforeEach, vitest } from "vitest" -import { TimeoutFallbackGenerator } from "../TimeoutFallbackGenerator" +import { TimeoutFallbackHandler } from "../TimeoutFallbackHandler" import type { ApiHandler, SingleCompletionHandler } from "../../../api" import type { Task } from "../../task/Task" // Mock API handler that simulates a real AI provider interface TestApiHandler extends ApiHandler, SingleCompletionHandler {} -describe("TimeoutFallbackGenerator - End-to-End AI Test", () => { +describe("TimeoutFallbackHandler - End-to-End AI Test", () => { test("should generate realistic AI suggestions for execute_command timeout", async () => { // Create a realistic mock API handler const mockApiHandler: TestApiHandler = { @@ -42,7 +42,7 @@ Here are some suggestions for the npm install timeout: }, } - const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) // Verify the result structure expect(result.success).toBe(true) @@ -99,7 +99,7 @@ Based on the search_files timeout, here are my recommendations: }, } - const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) expect(result.success).toBe(true) expect(result.toolCall).toBeDefined() @@ -134,7 +134,7 @@ Based on the search_files timeout, here are my recommendations: }, } - const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) expect(result.success).toBe(true) expect(result.toolCall).toBeDefined() @@ -164,7 +164,7 @@ Based on the search_files timeout, here are my recommendations: }, } - const result = await TimeoutFallbackGenerator.generateAiFallback(context, mockTask as Task) + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) expect(result.success).toBe(true) expect(result.toolCall).toBeDefined() diff --git a/src/core/timeout/__tests__/tool-injection-test.spec.ts b/src/core/timeout/__tests__/tool-injection-test.spec.ts index 8208139f03..49c9d0d225 100644 --- a/src/core/timeout/__tests__/tool-injection-test.spec.ts +++ b/src/core/timeout/__tests__/tool-injection-test.spec.ts @@ -1,9 +1,13 @@ import { describe, test, expect, vi, beforeEach } from "vitest" import { TimeoutFallbackHandler } from "../TimeoutFallbackHandler" -import { TimeoutFallbackGenerator, type TimeoutFallbackResult } from "../TimeoutFallbackGenerator" +import { type TimeoutFallbackResult } from "../TimeoutFallbackHandler" import { Task } from "../../task/Task" -vi.mock("../TimeoutFallbackGenerator") +// Import the real module first +import { TimeoutFallbackHandler as RealTimeoutFallbackHandler } from "../TimeoutFallbackHandler" + +// Mock only the generateAiFallback method +vi.spyOn(RealTimeoutFallbackHandler, "generateAiFallback") describe("Tool Call Response Test", () => { let mockTask: Task @@ -20,7 +24,7 @@ describe("Tool Call Response Test", () => { }) test("should return response with ask_followup_question tool instructions", async () => { - // Mock the TimeoutFallbackGenerator to return a successful AI result + // Mock the TimeoutFallbackHandler to return a successful AI result const mockAiResult: TimeoutFallbackResult = { success: true, toolCall: { @@ -34,7 +38,7 @@ describe("Tool Call Response Test", () => { } // Mock the generateAiFallback method - vi.mocked(TimeoutFallbackGenerator.generateAiFallback).mockResolvedValue(mockAiResult) + vi.mocked(RealTimeoutFallbackHandler.generateAiFallback).mockResolvedValue(mockAiResult) // Call createTimeoutResponse const response = await TimeoutFallbackHandler.createTimeoutResponse( @@ -65,7 +69,7 @@ describe("Tool Call Response Test", () => { test("should return fallback message when AI generation fails", async () => { // Mock the generateAiFallback to return a failure - vi.mocked(TimeoutFallbackGenerator.generateAiFallback).mockResolvedValue({ + vi.mocked(RealTimeoutFallbackHandler.generateAiFallback).mockResolvedValue({ success: false, error: "AI generation failed", }) diff --git a/src/core/timeout/__tests__/ui-integration.spec.ts b/src/core/timeout/__tests__/ui-integration.spec.ts index f44610a857..8065aa12ed 100644 --- a/src/core/timeout/__tests__/ui-integration.spec.ts +++ b/src/core/timeout/__tests__/ui-integration.spec.ts @@ -1,5 +1,4 @@ import { describe, it, expect, vi } from "vitest" -import { TimeoutFallbackGenerator } from "../TimeoutFallbackGenerator" import { TimeoutFallbackHandler } from "../TimeoutFallbackHandler" describe("UI Integration - AI Timeout Fallbacks", () => { @@ -11,7 +10,7 @@ describe("UI Integration - AI Timeout Fallbacks", () => { toolParams: { command: "npm install" }, } - const result = await TimeoutFallbackGenerator.generateAiFallback(context) + const result = await TimeoutFallbackHandler.generateAiFallback(context) expect(result.success).toBe(true) expect(result.toolCall).toBeDefined() diff --git a/src/core/timeout/index.ts b/src/core/timeout/index.ts index 8b1f080c71..ad808bc1ca 100644 --- a/src/core/timeout/index.ts +++ b/src/core/timeout/index.ts @@ -1,9 +1,8 @@ export { TimeoutManager, timeoutManager } from "./TimeoutManager" export { ToolExecutionWrapper } from "./ToolExecutionWrapper" export { TimeoutFallbackHandler } from "./TimeoutFallbackHandler" -export { TimeoutFallbackGenerator } from "./TimeoutFallbackGenerator" export type { TimeoutConfig, TimeoutResult, TimeoutEvent } from "./TimeoutManager" export type { ToolExecutionOptions } from "./ToolExecutionWrapper" -export type { TimeoutFallbackResult } from "./TimeoutFallbackGenerator" +export type { TimeoutFallbackResult } from "./TimeoutFallbackHandler" export type { TimeoutFallbackContext } from "../prompts/instructions/timeout-fallback" From adc1573b096206d18f58899a1a849451e97d4938 Mon Sep 17 00:00:00 2001 From: Will Li Date: Wed, 9 Jul 2025 08:12:45 -0700 Subject: [PATCH 05/12] refactor and fixed copy --- packages/types/src/global-settings.ts | 2 +- src/core/timeout/TimeoutManager.ts | 26 +- src/core/timeout/ToolExecutionWrapper.ts | 133 +---- .../__tests__/ai-fallback-real.spec.ts | 234 -------- .../timeout/__tests__/e2e-ai-test.spec.ts | 179 ------ .../__tests__/timeout-fallback.spec.ts | 554 ++++++++++++++++++ .../__tests__/timeout-integration.spec.ts | 379 +++++++----- .../timeout/__tests__/timeout-manager.spec.ts | 178 ++++++ .../__tests__/tool-injection-test.spec.ts | 98 ---- .../timeout/__tests__/ui-integration.spec.ts | 70 --- src/core/tools/executeCommandTool.ts | 6 +- src/core/webview/ClineProvider.ts | 4 +- .../settings/AutoApproveSettings.tsx | 2 +- .../src/context/ExtensionStateContext.tsx | 6 +- webview-ui/src/i18n/locales/en/chat.json | 2 +- webview-ui/src/i18n/locales/en/settings.json | 2 +- 16 files changed, 999 insertions(+), 876 deletions(-) delete mode 100644 src/core/timeout/__tests__/ai-fallback-real.spec.ts delete mode 100644 src/core/timeout/__tests__/e2e-ai-test.spec.ts create mode 100644 src/core/timeout/__tests__/timeout-fallback.spec.ts create mode 100644 src/core/timeout/__tests__/timeout-manager.spec.ts delete mode 100644 src/core/timeout/__tests__/tool-injection-test.spec.ts delete mode 100644 src/core/timeout/__tests__/ui-integration.spec.ts diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index 130ba09b23..618a6c9cd8 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -231,7 +231,7 @@ export const EVALS_SETTINGS: RooCodeSettings = { enableCheckpoints: false, // Timeout settings - toolExecutionTimeoutMs: 300000, // 5 minutes default + toolExecutionTimeoutMs: 60000, // 1 minute default timeoutFallbackEnabled: false, rateLimitSeconds: 0, diff --git a/src/core/timeout/TimeoutManager.ts b/src/core/timeout/TimeoutManager.ts index 28d361ef07..72af1beb49 100644 --- a/src/core/timeout/TimeoutManager.ts +++ b/src/core/timeout/TimeoutManager.ts @@ -32,10 +32,10 @@ export class TimeoutManager extends EventEmitter { private static instance: TimeoutManager | undefined private activeOperations = new Map() /** - * Multiple timeout events can be run at once - * eg. running a command while reading a file + * Assumes there is only on active tool-- does not timeout edge cases + * like "Proceed While Running" */ - private timeoutEvents: TimeoutEvent[] = [] + private lastTimeoutEvent: TimeoutEvent | null = null private constructor() { super() @@ -93,7 +93,7 @@ export class TimeoutManager extends EventEmitter { const timedOut = controller.signal.aborted if (timedOut) { - // Log timeout event + // Store the last timeout event const timeoutEvent: TimeoutEvent = { toolName: config.toolName, timeoutMs: config.timeoutMs, @@ -102,7 +102,7 @@ export class TimeoutManager extends EventEmitter { timestamp: Date.now(), } - this.timeoutEvents.push(timeoutEvent) + this.lastTimeoutEvent = timeoutEvent this.emit("timeout", timeoutEvent) return { @@ -154,17 +154,17 @@ export class TimeoutManager extends EventEmitter { } /** - * Get timeout events for debugging/monitoring + * Get the last timeout event */ - public getTimeoutEvents(limit = 100): TimeoutEvent[] { - return this.timeoutEvents.slice(-limit) + public getLastTimeoutEvent(): TimeoutEvent | null { + return this.lastTimeoutEvent } /** - * Clear timeout event history + * Clear the last timeout event */ - public clearTimeoutEvents(): void { - this.timeoutEvents = [] + public clearLastTimeoutEvent(): void { + this.lastTimeoutEvent = null } /** @@ -183,7 +183,7 @@ export class TimeoutManager extends EventEmitter { } private generateOperationId(toolName: ToolName, taskId?: string): string { - return `${toolName}:${taskId || "default"}:${Date.now()}` + return `${toolName}:${taskId || "default"}` } /** @@ -192,7 +192,7 @@ export class TimeoutManager extends EventEmitter { public dispose(): void { this.cancelAllOperations() this.removeAllListeners() - this.timeoutEvents = [] + this.lastTimeoutEvent = null } } diff --git a/src/core/timeout/ToolExecutionWrapper.ts b/src/core/timeout/ToolExecutionWrapper.ts index a67d10f2a5..50ac9c765f 100644 --- a/src/core/timeout/ToolExecutionWrapper.ts +++ b/src/core/timeout/ToolExecutionWrapper.ts @@ -18,7 +18,7 @@ export class ToolExecutionWrapper { public static async execute( operation: (signal: AbortSignal) => Promise, options: ToolExecutionOptions, - defaultTimeoutMs = 300000, // 5 minutes default + defaultTimeoutMs = 60000, // 1 minute default ): Promise> { const config: TimeoutConfig = { toolName: options.toolName, @@ -29,135 +29,4 @@ export class ToolExecutionWrapper { return timeoutManager.executeWithTimeout(operation, config) } - - /** - * Wrap a promise-based operation to support AbortSignal - */ - public static wrapPromise(promiseFactory: () => Promise, signal: AbortSignal): Promise { - return new Promise((resolve, reject) => { - // Check if already aborted - if (signal.aborted) { - reject(new Error("Operation was aborted before starting")) - return - } - - // Set up abort listener - const abortListener = () => { - reject(new Error("Operation was aborted")) - } - - signal.addEventListener("abort", abortListener) - - // Execute the operation - promiseFactory() - .then((result) => { - signal.removeEventListener("abort", abortListener) - resolve(result) - }) - .catch((error) => { - signal.removeEventListener("abort", abortListener) - reject(error) - }) - }) - } - - /** - * Wrap a callback-based operation to support AbortSignal - */ - public static wrapCallback( - operation: (callback: (error: Error | null, result?: T) => void, signal: AbortSignal) => void, - signal: AbortSignal, - ): Promise { - return new Promise((resolve, reject) => { - // Check if already aborted - if (signal.aborted) { - reject(new Error("Operation was aborted before starting")) - return - } - - // Set up abort listener - const abortListener = () => { - reject(new Error("Operation was aborted")) - } - - signal.addEventListener("abort", abortListener) - - // Execute the operation - operation((error, result) => { - signal.removeEventListener("abort", abortListener) - - if (error) { - reject(error) - } else { - resolve(result!) - } - }, signal) - }) - } - - /** - * Create an abortable delay - */ - public static delay(ms: number, signal: AbortSignal): Promise { - return new Promise((resolve, reject) => { - if (signal.aborted) { - reject(new Error("Delay was aborted before starting")) - return - } - - const timeoutId = setTimeout(() => { - signal.removeEventListener("abort", abortListener) - resolve() - }, ms) - - const abortListener = () => { - clearTimeout(timeoutId) - reject(new Error("Delay was aborted")) - } - - signal.addEventListener("abort", abortListener) - }) - } - - /** - * Execute multiple operations in parallel with timeout protection - */ - public static async executeParallel( - operations: Array<{ - operation: (signal: AbortSignal) => Promise - options: ToolExecutionOptions - }>, - defaultTimeoutMs = 300000, - ): Promise[]> { - const promises = operations.map(({ operation, options }) => - ToolExecutionWrapper.execute(operation, options, defaultTimeoutMs), - ) - - return Promise.all(promises) - } - - /** - * Execute operations in sequence with timeout protection - */ - public static async executeSequential( - operations: Array<{ - operation: (signal: AbortSignal) => Promise - options: ToolExecutionOptions - }>, - defaultTimeoutMs = 300000, - ): Promise[]> { - const results: TimeoutResult[] = [] - - for (const { operation, options } of operations) { - const result = await ToolExecutionWrapper.execute(operation, options, defaultTimeoutMs) - results.push(result) - - // Stop execution if any operation fails or times out - if (!result.success) { - break - } - } - - return results - } } diff --git a/src/core/timeout/__tests__/ai-fallback-real.spec.ts b/src/core/timeout/__tests__/ai-fallback-real.spec.ts deleted file mode 100644 index 7b378a2b01..0000000000 --- a/src/core/timeout/__tests__/ai-fallback-real.spec.ts +++ /dev/null @@ -1,234 +0,0 @@ -// npx vitest run src/core/timeout/__tests__/ai-fallback-real.spec.ts - -import { describe, test, expect, beforeEach, vitest } from "vitest" -import { TimeoutFallbackHandler } from "../TimeoutFallbackHandler" -import type { ApiHandler, SingleCompletionHandler } from "../../../api" -import type { Task } from "../../task/Task" - -// Create a mock API handler that extends ApiHandler and includes completePrompt -interface MockApiHandler extends ApiHandler, SingleCompletionHandler {} - -describe("TimeoutFallbackHandler - Real AI Implementation", () => { - let mockApiHandler: MockApiHandler - let mockTask: Partial - - beforeEach(() => { - vitest.clearAllMocks() - - // Mock API handler that simulates real AI responses - mockApiHandler = { - createMessage: vitest.fn(), - getModel: vitest.fn().mockReturnValue({ id: "test-model", info: { maxTokens: 4096 } }), - countTokens: vitest.fn().mockResolvedValue(100), - completePrompt: vitest.fn(), - } - - // Mock task with API handler - mockTask = { - api: mockApiHandler, - } - }) - - test("should use AI to generate contextual suggestions when available", async () => { - // Mock AI response with numbered suggestions - const mockAiResponse = `Here are some suggestions for the timeout: - -1. Break the npm install command into smaller package installations -2. Clear npm cache and try again with npm cache clean --force -3. Use npm install --no-optional to skip optional dependencies -4. Check network connectivity and try with different registry` - - ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) - - const context = { - toolName: "execute_command" as const, - timeoutMs: 30000, - executionTimeMs: 35000, - toolParams: { command: "npm install" }, - } - - const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) - - expect(result.success).toBe(true) - expect(result.toolCall).toBeDefined() - expect(result.toolCall?.name).toBe("ask_followup_question") - expect(result.toolCall?.params.question).toContain("execute_command") - expect(result.toolCall?.params.question).toContain("30 seconds") - - // Check that AI-generated suggestions are included - const followUp = result.toolCall?.params.follow_up || "" - expect(followUp).toContain("Break the npm install command into smaller package installations") - expect(followUp).toContain("Clear npm cache and try again") - expect(followUp).toContain("Use npm install --no-optional") - expect(followUp).toContain("Check network connectivity") - - // Verify AI was called with proper prompt - expect(mockApiHandler.completePrompt).toHaveBeenCalledWith( - expect.stringContaining("execute_command operation has timed out"), - ) - expect(mockApiHandler.completePrompt).toHaveBeenCalledWith(expect.stringContaining("npm install")) - }) - - test("should fallback to static suggestions when AI fails", async () => { - // Mock AI failure - ;(mockApiHandler.completePrompt as any).mockRejectedValueOnce(new Error("API Error")) - - const context = { - toolName: "execute_command" as const, - timeoutMs: 30000, - executionTimeMs: 35000, - toolParams: { command: "npm test" }, - } - - const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) - - expect(result.success).toBe(true) - expect(result.toolCall).toBeDefined() - expect(result.toolCall?.name).toBe("ask_followup_question") - - // Should contain static fallback suggestions - const followUp = result.toolCall?.params.follow_up || "" - expect(followUp).toContain('Break "npm test" into smaller') - expect(followUp).toContain("background using") - expect(followUp).toContain("alternative approach") - expect(followUp).toContain("Increase the timeout") - }) - - test("should fallback to static suggestions when API handler is unavailable", async () => { - // Task without API handler - const taskWithoutApi = {} - - const context = { - toolName: "read_file" as const, - timeoutMs: 5000, - executionTimeMs: 6000, - toolParams: { path: "/large/file.txt" }, - } - - const result = await TimeoutFallbackHandler.generateAiFallback(context, taskWithoutApi as Task) - - expect(result.success).toBe(true) - expect(result.toolCall).toBeDefined() - - // Should contain static fallback suggestions for read_file - const followUp = result.toolCall?.params.follow_up || "" - expect(followUp).toContain('Read "/large/file.txt" in smaller chunks') - expect(followUp).toContain("accessible and not locked") - }) - - test("should parse AI response with different numbering formats", async () => { - // Test different numbering formats - const mockAiResponse = `Here are the suggestions: - -1) Try breaking the command into parts -2. Use a different approach -3) Check system resources -4. Increase timeout duration` - - ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) - - const context = { - toolName: "execute_command" as const, - timeoutMs: 10000, - executionTimeMs: 12000, - toolParams: { command: "build script" }, - } - - const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) - - expect(result.success).toBe(true) - const followUp = result.toolCall?.params.follow_up || "" - expect(followUp).toContain("Try breaking the command into parts") - expect(followUp).toContain("Use a different approach") - expect(followUp).toContain("Check system resources") - expect(followUp).toContain("Increase timeout duration") - }) - - test("should handle AI response without numbered list", async () => { - // AI response without clear numbering - const mockAiResponse = `You could try splitting the operation. Another option is to check the network. Maybe increase the timeout. Consider using a different tool.` - - ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) - - const context = { - toolName: "browser_action" as const, - timeoutMs: 15000, - executionTimeMs: 16000, - toolParams: { action: "click" }, - } - - const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) - - expect(result.success).toBe(true) - const followUp = result.toolCall?.params.follow_up || "" - - // Should extract sentences as suggestions - expect(followUp).toContain("You could try splitting the operation") - expect(followUp).toContain("Another option is to check the network") - }) - - test("should include task context in AI prompt when available", async () => { - const mockAiResponse = `1. Try a different approach\n2. Check the working directory\n3. Break into steps` - ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) - - const context = { - toolName: "search_files" as const, - timeoutMs: 20000, - executionTimeMs: 22000, - toolParams: { path: "/project", regex: ".*\\.ts$" }, - taskContext: { - currentStep: "Finding TypeScript files", - workingDirectory: "/project/src", - previousActions: ["read package.json", "list files"], - }, - } - - const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) - - expect(result.success).toBe(true) - - // Verify the prompt included task context - const calledPrompt = (mockApiHandler.completePrompt as any).mock.calls[0][0] - expect(calledPrompt).toContain("Current step: Finding TypeScript files") - expect(calledPrompt).toContain("Working directory: /project/src") - expect(calledPrompt).toContain("search_files") - expect(calledPrompt).toContain("ts$") // Just check for the pattern ending - }) - - test("should limit suggestions to maximum of 4", async () => { - // AI response with many suggestions - const mockAiResponse = `Here are many suggestions: - -1. First suggestion -2. Second suggestion -3. Third suggestion -4. Fourth suggestion -5. Fifth suggestion -6. Sixth suggestion -7. Seventh suggestion` - - ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) - - const context = { - toolName: "write_to_file" as const, - timeoutMs: 8000, - executionTimeMs: 9000, - toolParams: { path: "/output.txt" }, - } - - const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) - - expect(result.success).toBe(true) - const followUp = result.toolCall?.params.follow_up || "" - - // Count the number of tags - const suggestCount = (followUp.match(//g) || []).length - expect(suggestCount).toBeLessThanOrEqual(4) - - // Should include first 4 suggestions - expect(followUp).toContain("First suggestion") - expect(followUp).toContain("Fourth suggestion") - // Should not include 5th and beyond - expect(followUp).not.toContain("Fifth suggestion") - }) -}) diff --git a/src/core/timeout/__tests__/e2e-ai-test.spec.ts b/src/core/timeout/__tests__/e2e-ai-test.spec.ts deleted file mode 100644 index 40bd9e5406..0000000000 --- a/src/core/timeout/__tests__/e2e-ai-test.spec.ts +++ /dev/null @@ -1,179 +0,0 @@ -// End-to-end test to verify AI fallback generation works -// npx vitest run src/core/timeout/__tests__/e2e-ai-test.spec.ts - -import { describe, test, expect, beforeEach, vitest } from "vitest" -import { TimeoutFallbackHandler } from "../TimeoutFallbackHandler" -import type { ApiHandler, SingleCompletionHandler } from "../../../api" -import type { Task } from "../../task/Task" - -// Mock API handler that simulates a real AI provider -interface TestApiHandler extends ApiHandler, SingleCompletionHandler {} - -describe("TimeoutFallbackHandler - End-to-End AI Test", () => { - test("should generate realistic AI suggestions for execute_command timeout", async () => { - // Create a realistic mock API handler - const mockApiHandler: TestApiHandler = { - createMessage: vitest.fn(), - getModel: vitest.fn().mockReturnValue({ id: "claude-3-sonnet", info: { maxTokens: 4096 } }), - countTokens: vitest.fn().mockResolvedValue(150), - completePrompt: vitest.fn().mockResolvedValue( - ` -Here are some suggestions for the npm install timeout: - -1. Clear npm cache with "npm cache clean --force" and retry -2. Break installation into smaller chunks by installing packages individually -3. Use "npm install --no-optional" to skip optional dependencies -4. Check network connectivity and try with a different registry - `.trim(), - ), - } - - const mockTask: Partial = { - api: mockApiHandler, - } - - const context = { - toolName: "execute_command" as const, - timeoutMs: 60000, - executionTimeMs: 65000, - toolParams: { - command: "npm install", - cwd: "/project", - }, - } - - const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) - - // Verify the result structure - expect(result.success).toBe(true) - expect(result.toolCall).toBeDefined() - expect(result.toolCall?.name).toBe("ask_followup_question") - expect(result.toolCall?.params.question).toContain("execute_command") - expect(result.toolCall?.params.question).toContain("60 seconds") - - // Verify AI-generated suggestions are included - const followUp = result.toolCall?.params.follow_up || "" - expect(followUp).toContain("Clear npm cache") - expect(followUp).toContain("Break installation into smaller chunks") - expect(followUp).toContain("no-optional") - expect(followUp).toContain("network connectivity") - - // Verify the AI was called with a proper prompt - expect(mockApiHandler.completePrompt).toHaveBeenCalledWith( - expect.stringContaining("execute_command operation has timed out"), - ) - expect(mockApiHandler.completePrompt).toHaveBeenCalledWith(expect.stringContaining("npm install")) - expect(mockApiHandler.completePrompt).toHaveBeenCalledWith(expect.stringContaining("60 seconds")) - }) - - test("should handle AI response with different formatting", async () => { - // Mock AI response with different numbering style - const mockApiHandler: TestApiHandler = { - createMessage: vitest.fn(), - getModel: vitest.fn().mockReturnValue({ id: "gpt-4", info: { maxTokens: 8192 } }), - countTokens: vitest.fn().mockResolvedValue(200), - completePrompt: vitest.fn().mockResolvedValue( - ` -Based on the search_files timeout, here are my recommendations: - -• Limit search to specific subdirectories instead of entire project -• Use more specific regex patterns to reduce matches -• Try list_files first to understand directory structure -• Consider breaking search into multiple smaller operations - `.trim(), - ), - } - - const mockTask: Partial = { - api: mockApiHandler, - } - - const context = { - toolName: "search_files" as const, - timeoutMs: 30000, - executionTimeMs: 32000, - toolParams: { - path: "/large-project", - regex: ".*", - file_pattern: "*.ts", - }, - } - - const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) - - expect(result.success).toBe(true) - expect(result.toolCall).toBeDefined() - - // Should extract suggestions even with bullet points - const followUp = result.toolCall?.params.follow_up || "" - expect(followUp).toContain("Narrow the search scope") - expect(followUp).toContain("simpler search patterns") - expect(followUp).toContain("file type filters") - expect(followUp).toContain("incrementally in smaller batches") - }) - - test("should gracefully handle AI failure and use static fallback", async () => { - // Mock API handler that fails - const mockApiHandler: TestApiHandler = { - createMessage: vitest.fn(), - getModel: vitest.fn().mockReturnValue({ id: "test-model", info: { maxTokens: 4096 } }), - countTokens: vitest.fn().mockResolvedValue(100), - completePrompt: vitest.fn().mockRejectedValue(new Error("API rate limit exceeded")), - } - - const mockTask: Partial = { - api: mockApiHandler, - } - - const context = { - toolName: "read_file" as const, - timeoutMs: 10000, - executionTimeMs: 12000, - toolParams: { - path: "/very/large/file.log", - }, - } - - const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) - - expect(result.success).toBe(true) - expect(result.toolCall).toBeDefined() - - // Should contain static fallback suggestions for read_file - const followUp = result.toolCall?.params.follow_up || "" - expect(followUp).toContain('Read "/very/large/file.log" in smaller chunks') - expect(followUp).toContain("accessible and not locked") - expect(followUp).toContain("different approach") - expect(followUp).toContain("Increase the timeout") - - // Verify AI was attempted but failed gracefully - expect(mockApiHandler.completePrompt).toHaveBeenCalled() - }) - - test("should work without task API handler", async () => { - // Task without API handler - const mockTask: Partial = {} - - const context = { - toolName: "browser_action" as const, - timeoutMs: 15000, - executionTimeMs: 16500, - toolParams: { - action: "click", - coordinate: "450,300", - }, - } - - const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) - - expect(result.success).toBe(true) - expect(result.toolCall).toBeDefined() - - // Should contain static fallback suggestions for browser_action - const followUp = result.toolCall?.params.follow_up || "" - expect(followUp).toContain('Simplify the "click"') - expect(followUp).toContain("Wait for specific elements") - expect(followUp).toContain("direct API calls") - expect(followUp).toContain("Reset the browser session") - }) -}) diff --git a/src/core/timeout/__tests__/timeout-fallback.spec.ts b/src/core/timeout/__tests__/timeout-fallback.spec.ts new file mode 100644 index 0000000000..d835bbf6ac --- /dev/null +++ b/src/core/timeout/__tests__/timeout-fallback.spec.ts @@ -0,0 +1,554 @@ +// npx vitest run src/core/timeout/__tests__/timeout-fallback.spec.ts + +import { describe, test, expect, beforeEach, vitest } from "vitest" +import { TimeoutFallbackHandler } from "../TimeoutFallbackHandler" +import type { TimeoutFallbackResult } from "../TimeoutFallbackHandler" +import type { ApiHandler, SingleCompletionHandler } from "../../../api" +import type { Task } from "../../task/Task" + +// Create a mock API handler that extends ApiHandler and includes completePrompt +interface MockApiHandler extends ApiHandler, SingleCompletionHandler {} + +describe("TimeoutFallbackHandler", () => { + let mockApiHandler: MockApiHandler + let mockTask: Partial + + beforeEach(() => { + vitest.clearAllMocks() + + // Mock API handler that simulates real AI responses + mockApiHandler = { + createMessage: vitest.fn(), + getModel: vitest.fn().mockReturnValue({ id: "test-model", info: { maxTokens: 4096 } }), + countTokens: vitest.fn().mockResolvedValue(100), + completePrompt: vitest.fn(), + } + + // Mock task with API handler + mockTask = { + api: mockApiHandler, + assistantMessageContent: [], + cwd: "/test/dir", + say: vitest.fn(), + } + }) + + describe("AI Fallback Generation", () => { + test("should use AI to generate contextual suggestions when available", async () => { + // Mock AI response with numbered suggestions + const mockAiResponse = `Here are some suggestions for the timeout: + +1. Break the npm install command into smaller package installations +2. Clear npm cache and try again with npm cache clean --force +3. Use npm install --no-optional to skip optional dependencies +4. Check network connectivity and try with different registry` + + ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) + + const context = { + toolName: "execute_command" as const, + timeoutMs: 30000, + executionTimeMs: 35000, + toolParams: { command: "npm install" }, + } + + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + expect(result.toolCall?.name).toBe("ask_followup_question") + expect(result.toolCall?.params.question).toContain("execute_command") + expect(result.toolCall?.params.question).toContain("30 seconds") + + // Check that AI-generated suggestions are included + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain("Break the npm install command into smaller package installations") + expect(followUp).toContain("Clear npm cache and try again") + expect(followUp).toContain("Use npm install --no-optional") + expect(followUp).toContain("Check network connectivity") + + // Verify AI was called with proper prompt + expect(mockApiHandler.completePrompt).toHaveBeenCalledWith( + expect.stringContaining("execute_command operation has timed out"), + ) + expect(mockApiHandler.completePrompt).toHaveBeenCalledWith(expect.stringContaining("npm install")) + }) + + test("should fallback to static suggestions when AI fails", async () => { + // Mock AI failure + ;(mockApiHandler.completePrompt as any).mockRejectedValueOnce(new Error("API Error")) + + const context = { + toolName: "execute_command" as const, + timeoutMs: 30000, + executionTimeMs: 35000, + toolParams: { command: "npm test" }, + } + + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + expect(result.toolCall?.name).toBe("ask_followup_question") + + // Should contain static fallback suggestions + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain('Break "npm test" into smaller') + expect(followUp).toContain("background using") + expect(followUp).toContain("alternative approach") + expect(followUp).toContain("Increase the timeout") + }) + + test("should fallback to static suggestions when API handler is unavailable", async () => { + // Task without API handler + const taskWithoutApi = {} + + const context = { + toolName: "read_file" as const, + timeoutMs: 5000, + executionTimeMs: 6000, + toolParams: { path: "/large/file.txt" }, + } + + const result = await TimeoutFallbackHandler.generateAiFallback(context, taskWithoutApi as Task) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + + // Should contain static fallback suggestions for read_file + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain('Read "/large/file.txt" in smaller chunks') + expect(followUp).toContain("accessible and not locked") + }) + + test("should parse AI response with different numbering formats", async () => { + // Test different numbering formats + const mockAiResponse = `Here are the suggestions: + +1) Try breaking the command into parts +2. Use a different approach +3) Check system resources +4. Increase timeout duration` + + ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) + + const context = { + toolName: "execute_command" as const, + timeoutMs: 10000, + executionTimeMs: 12000, + toolParams: { command: "build script" }, + } + + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain("Try breaking the command into parts") + expect(followUp).toContain("Use a different approach") + expect(followUp).toContain("Check system resources") + expect(followUp).toContain("Increase timeout duration") + }) + + test("should handle AI response without numbered list", async () => { + // AI response without clear numbering + const mockAiResponse = `You could try splitting the operation. Another option is to check the network. Maybe increase the timeout. Consider using a different tool.` + + ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) + + const context = { + toolName: "browser_action" as const, + timeoutMs: 15000, + executionTimeMs: 16000, + toolParams: { action: "click" }, + } + + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + const followUp = result.toolCall?.params.follow_up || "" + + // Should extract sentences as suggestions + expect(followUp).toContain("You could try splitting the operation") + expect(followUp).toContain("Another option is to check the network") + }) + + test("should include task context in AI prompt when available", async () => { + const mockAiResponse = `1. Try a different approach\n2. Check the working directory\n3. Break into steps` + ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) + + const context = { + toolName: "search_files" as const, + timeoutMs: 20000, + executionTimeMs: 22000, + toolParams: { path: "/project", regex: ".*\\.ts$" }, + taskContext: { + currentStep: "Finding TypeScript files", + workingDirectory: "/project/src", + previousActions: ["read package.json", "list files"], + }, + } + + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + + // Verify the prompt included task context + const calledPrompt = (mockApiHandler.completePrompt as any).mock.calls[0][0] + expect(calledPrompt).toContain("Current step: Finding TypeScript files") + expect(calledPrompt).toContain("Working directory: /project/src") + expect(calledPrompt).toContain("search_files") + expect(calledPrompt).toContain("ts$") // Just check for the pattern ending + }) + + test("should limit suggestions to maximum of 4", async () => { + // AI response with many suggestions + const mockAiResponse = `Here are many suggestions: + +1. First suggestion +2. Second suggestion +3. Third suggestion +4. Fourth suggestion +5. Fifth suggestion +6. Sixth suggestion +7. Seventh suggestion` + + ;(mockApiHandler.completePrompt as any).mockResolvedValueOnce(mockAiResponse) + + const context = { + toolName: "write_to_file" as const, + timeoutMs: 8000, + executionTimeMs: 9000, + toolParams: { path: "/output.txt" }, + } + + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) + + expect(result.success).toBe(true) + const followUp = result.toolCall?.params.follow_up || "" + + // Count the number of tags + const suggestCount = (followUp.match(//g) || []).length + expect(suggestCount).toBeLessThanOrEqual(4) + + // Should include first 4 suggestions + expect(followUp).toContain("First suggestion") + expect(followUp).toContain("Fourth suggestion") + // Should not include 5th and beyond + expect(followUp).not.toContain("Fifth suggestion") + }) + }) + + describe("End-to-End AI Tests", () => { + test("should generate realistic AI suggestions for execute_command timeout", async () => { + // Create a realistic mock API handler + const testApiHandler: MockApiHandler = { + createMessage: vitest.fn(), + getModel: vitest.fn().mockReturnValue({ id: "claude-3-sonnet", info: { maxTokens: 4096 } }), + countTokens: vitest.fn().mockResolvedValue(150), + completePrompt: vitest.fn().mockResolvedValue( + ` +Here are some suggestions for the npm install timeout: + +1. Clear npm cache with "npm cache clean --force" and retry +2. Break installation into smaller chunks by installing packages individually +3. Use "npm install --no-optional" to skip optional dependencies +4. Check network connectivity and try with a different registry + `.trim(), + ), + } + + const testTask: Partial = { + api: testApiHandler, + } + + const context = { + toolName: "execute_command" as const, + timeoutMs: 60000, + executionTimeMs: 65000, + toolParams: { + command: "npm install", + cwd: "/project", + }, + } + + const result = await TimeoutFallbackHandler.generateAiFallback(context, testTask as Task) + + // Verify the result structure + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + expect(result.toolCall?.name).toBe("ask_followup_question") + expect(result.toolCall?.params.question).toContain("execute_command") + expect(result.toolCall?.params.question).toContain("60 seconds") + + // Verify AI-generated suggestions are included + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain("Clear npm cache") + expect(followUp).toContain("Break installation into smaller chunks") + expect(followUp).toContain("no-optional") + expect(followUp).toContain("network connectivity") + + // Verify the AI was called with a proper prompt + expect(testApiHandler.completePrompt).toHaveBeenCalledWith( + expect.stringContaining("execute_command operation has timed out"), + ) + expect(testApiHandler.completePrompt).toHaveBeenCalledWith(expect.stringContaining("npm install")) + expect(testApiHandler.completePrompt).toHaveBeenCalledWith(expect.stringContaining("60 seconds")) + }) + + test("should handle AI response with different formatting", async () => { + // Mock AI response with different numbering style + const testApiHandler: MockApiHandler = { + createMessage: vitest.fn(), + getModel: vitest.fn().mockReturnValue({ id: "gpt-4", info: { maxTokens: 8192 } }), + countTokens: vitest.fn().mockResolvedValue(200), + completePrompt: vitest.fn().mockResolvedValue( + ` +Based on the search_files timeout, here are my recommendations: + +• Limit search to specific subdirectories instead of entire project +• Use more specific regex patterns to reduce matches +• Try list_files first to understand directory structure +• Consider breaking search into multiple smaller operations + `.trim(), + ), + } + + const testTask: Partial = { + api: testApiHandler, + } + + const context = { + toolName: "search_files" as const, + timeoutMs: 30000, + executionTimeMs: 32000, + toolParams: { + path: "/large-project", + regex: ".*", + file_pattern: "*.ts", + }, + } + + const result = await TimeoutFallbackHandler.generateAiFallback(context, testTask as Task) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + + // Should extract suggestions even with bullet points + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain("Narrow the search scope") + expect(followUp).toContain("simpler search patterns") + expect(followUp).toContain("file type filters") + expect(followUp).toContain("incrementally in smaller batches") + }) + + test("should gracefully handle AI failure and use static fallback", async () => { + // Mock API handler that fails + const testApiHandler: MockApiHandler = { + createMessage: vitest.fn(), + getModel: vitest.fn().mockReturnValue({ id: "test-model", info: { maxTokens: 4096 } }), + countTokens: vitest.fn().mockResolvedValue(100), + completePrompt: vitest.fn().mockRejectedValue(new Error("API rate limit exceeded")), + } + + const testTask: Partial = { + api: testApiHandler, + } + + const context = { + toolName: "read_file" as const, + timeoutMs: 10000, + executionTimeMs: 12000, + toolParams: { + path: "/very/large/file.log", + }, + } + + const result = await TimeoutFallbackHandler.generateAiFallback(context, testTask as Task) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + + // Should contain static fallback suggestions for read_file + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain('Read "/very/large/file.log" in smaller chunks') + expect(followUp).toContain("accessible and not locked") + expect(followUp).toContain("different approach") + expect(followUp).toContain("Increase the timeout") + + // Verify AI was attempted but failed gracefully + expect(testApiHandler.completePrompt).toHaveBeenCalled() + }) + + test("should work without task API handler", async () => { + // Task without API handler + const testTask: Partial = {} + + const context = { + toolName: "browser_action" as const, + timeoutMs: 15000, + executionTimeMs: 16500, + toolParams: { + action: "click", + coordinate: "450,300", + }, + } + + const result = await TimeoutFallbackHandler.generateAiFallback(context, testTask as Task) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + + // Should contain static fallback suggestions for browser_action + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain('Simplify the "click"') + expect(followUp).toContain("Wait for specific elements") + expect(followUp).toContain("direct API calls") + expect(followUp).toContain("Reset the browser session") + }) + }) + + describe("Tool Call Response Generation", () => { + test("should return response with ask_followup_question tool instructions", async () => { + // Mock the TimeoutFallbackHandler to return a successful AI result + const mockAiResult: TimeoutFallbackResult = { + success: true, + toolCall: { + name: "ask_followup_question", + params: { + question: + "The execute_command operation timed out after 5 seconds. How would you like to proceed?", + follow_up: + "Try a different approach\nBreak into smaller steps", + }, + }, + } + + // Spy on the generateAiFallback method + const generateSpy = vitest.spyOn(TimeoutFallbackHandler, "generateAiFallback") + generateSpy.mockResolvedValue(mockAiResult) + + // Call createTimeoutResponse + const response = await TimeoutFallbackHandler.createTimeoutResponse( + "execute_command", + 5000, + 6000, + { command: "npm install" }, + mockTask as Task, + ) + + // Check that the response contains the base timeout message + expect(response).toContain("timed out after 5 seconds") + expect(response).toContain("Execution Time: 6s") + + // Check that the response includes instructions to use ask_followup_question + expect(response).toContain("You MUST now use the ask_followup_question tool") + expect(response).toContain("") + expect(response).toContain(`${mockAiResult.toolCall?.params.question}`) + expect(response).toContain("") + expect(response).toContain(mockAiResult.toolCall?.params.follow_up) + expect(response).toContain("") + expect(response).toContain("") + expect(response).toContain("This is required to help the user decide how to proceed after the timeout.") + + // Verify that assistantMessageContent was NOT modified + expect(mockTask.assistantMessageContent).toHaveLength(0) + + generateSpy.mockRestore() + }) + + test("should return fallback message when AI generation fails", async () => { + // Spy on the generateAiFallback method to return a failure + const generateSpy = vitest.spyOn(TimeoutFallbackHandler, "generateAiFallback") + generateSpy.mockResolvedValue({ + success: false, + error: "AI generation failed", + }) + + // Call createTimeoutResponse + const response = await TimeoutFallbackHandler.createTimeoutResponse( + "execute_command", + 5000, + 6000, + { command: "npm install" }, + mockTask as Task, + ) + + // Check that the response contains the base timeout message + expect(response).toContain("timed out after 5 seconds") + expect(response).toContain("Execution Time: 6s") + + // Check that the response contains the fallback message + expect(response).toContain( + "The operation timed out. Please consider breaking this into smaller steps or trying a different approach.", + ) + + // Should not contain ask_followup_question instructions + expect(response).not.toContain("ask_followup_question") + + generateSpy.mockRestore() + }) + }) + + describe("UI Integration", () => { + test("should generate AI fallbacks using static method", async () => { + const context = { + toolName: "execute_command" as const, + timeoutMs: 30000, + executionTimeMs: 25000, + toolParams: { command: "npm install" }, + } + + const result = await TimeoutFallbackHandler.generateAiFallback(context) + + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + expect(result.toolCall?.name).toBe("ask_followup_question") + expect(result.toolCall?.params.question).toContain("execute_command") + }) + + test("should create timeout response with AI fallbacks", async () => { + const response = await TimeoutFallbackHandler.createTimeoutResponse("execute_command", 30000, 25000, { + command: "npm install", + }) + + expect(response).toContain("execute_command") + expect(response).toContain("timed out") + expect(response.length).toBeGreaterThan(100) // Should contain substantial content + }) + + test("should handle different tool types with AI fallbacks", async () => { + const commandResponse = await TimeoutFallbackHandler.createTimeoutResponse( + "execute_command", + 30000, + 25000, + { + command: "npm test", + }, + ) + + const browserResponse = await TimeoutFallbackHandler.createTimeoutResponse("browser_action", 30000, 25000, { + action: "click", + }) + + expect(commandResponse).toContain("execute_command") + expect(browserResponse).toContain("browser_action") + expect(commandResponse).not.toEqual(browserResponse) + }) + + test("should validate UI setting flow", () => { + // This test validates that timeout settings can be toggled + const settings = { + timeoutFallbackEnabled: true, + toolExecutionTimeoutMs: 30000, + } + + // Simulate UI toggle + settings.timeoutFallbackEnabled = false + expect(settings.timeoutFallbackEnabled).toBe(false) + + // Simulate timeout duration change + settings.toolExecutionTimeoutMs = 60000 + expect(settings.toolExecutionTimeoutMs).toBe(60000) + }) + }) +}) diff --git a/src/core/timeout/__tests__/timeout-integration.spec.ts b/src/core/timeout/__tests__/timeout-integration.spec.ts index 5bd741e51c..acc9161486 100644 --- a/src/core/timeout/__tests__/timeout-integration.spec.ts +++ b/src/core/timeout/__tests__/timeout-integration.spec.ts @@ -11,163 +11,264 @@ describe("Timeout Integration Tests", () => { vitest.clearAllMocks() }) - test("TimeoutManager should handle basic timeout operations", async () => { - const manager = TimeoutManager.getInstance() + describe("TimeoutManager Integration", () => { + test("should handle basic timeout operations", async () => { + const manager = TimeoutManager.getInstance() - // Test successful operation within timeout - const result = await manager.executeWithTimeout( - async () => { - await new Promise((resolve) => setTimeout(resolve, 10)) - return "success" - }, - { - toolName: "execute_command", - timeoutMs: 100, - enableFallback: true, - }, - ) - - expect(result.success).toBe(true) - expect(result.result).toBe("success") - expect(result.timedOut).toBe(false) - }) + // Test successful operation within timeout + const result = await manager.executeWithTimeout( + async () => { + await new Promise((resolve) => setTimeout(resolve, 10)) + return "success" + }, + { + toolName: "execute_command", + timeoutMs: 100, + enableFallback: true, + }, + ) - test("TimeoutManager should handle timeout scenarios", async () => { - const manager = TimeoutManager.getInstance() + expect(result.success).toBe(true) + expect(result.result).toBe("success") + expect(result.timedOut).toBe(false) + }) - // Test operation that times out - const result = await manager.executeWithTimeout( - async () => { - await new Promise((resolve) => setTimeout(resolve, 200)) - return "should not reach here" - }, - { - toolName: "execute_command", - timeoutMs: 50, - enableFallback: true, - }, - ) - - expect(result.success).toBe(false) - expect(result.timedOut).toBe(true) - expect(result.error?.message).toContain("Operation timed out") + test("should handle timeout scenarios", async () => { + const manager = TimeoutManager.getInstance() + + // Test operation that times out + const result = await manager.executeWithTimeout( + async () => { + await new Promise((resolve) => setTimeout(resolve, 200)) + return "should not reach here" + }, + { + toolName: "execute_command", + timeoutMs: 50, + enableFallback: true, + }, + ) + + expect(result.success).toBe(false) + expect(result.timedOut).toBe(true) + expect(result.error?.message).toContain("Operation timed out") + }) }) - test("ToolExecutionWrapper should wrap operations correctly", async () => { - const mockOperation = vitest.fn().mockImplementation(async (signal: AbortSignal) => { - // Simulate checking abort signal - if (signal.aborted) { - throw new Error("Operation was aborted") - } - await new Promise((resolve) => setTimeout(resolve, 10)) - return [false, "test result"] + describe("ToolExecutionWrapper Integration", () => { + test("should wrap operations correctly", async () => { + const mockOperation = vitest.fn().mockImplementation(async (signal: AbortSignal) => { + // Simulate checking abort signal + if (signal.aborted) { + throw new Error("Operation was aborted") + } + await new Promise((resolve) => setTimeout(resolve, 10)) + return [false, "test result"] + }) + + const result = await ToolExecutionWrapper.execute( + mockOperation, + { + toolName: "execute_command", + taskId: "test-task", + timeoutMs: 100, + enableFallback: true, + }, + 100, + ) + + expect(result.success).toBe(true) + expect(result.result).toEqual([false, "test result"]) + expect(mockOperation).toHaveBeenCalledWith(expect.any(AbortSignal)) }) - const result = await ToolExecutionWrapper.execute( - mockOperation, - { - toolName: "execute_command", - taskId: "test-task", - timeoutMs: 100, - enableFallback: true, - }, - 100, - ) - - expect(result.success).toBe(true) - expect(result.result).toEqual([false, "test result"]) - expect(mockOperation).toHaveBeenCalledWith(expect.any(AbortSignal)) - }) + test("should handle timeout with fallback", async () => { + const mockOperation = vitest.fn().mockImplementation(async () => { + await new Promise((resolve) => setTimeout(resolve, 200)) + return [false, "should not reach here"] + }) - test("ToolExecutionWrapper should handle timeout with fallback", async () => { - const mockOperation = vitest.fn().mockImplementation(async () => { - await new Promise((resolve) => setTimeout(resolve, 200)) - return [false, "should not reach here"] + const result = await ToolExecutionWrapper.execute( + mockOperation, + { + toolName: "execute_command", + taskId: "test-task", + timeoutMs: 50, + enableFallback: true, + }, + 50, + ) + + expect(result.success).toBe(false) + expect(result.timedOut).toBe(true) + expect(result.fallbackTriggered).toBe(true) }) + }) + + describe("TimeoutFallbackHandler Integration", () => { + test("should create AI-powered responses", async () => { + // Create a mock task to test tool injection + const mockTask = { + assistantMessageContent: [], + cwd: "/test/dir", + say: vitest.fn().mockResolvedValue(undefined), + } as unknown as Task + + const response = await TimeoutFallbackHandler.createTimeoutResponse( + "execute_command", + 5000, + 6000, + { command: "npm install" }, + mockTask, + ) + + // The response should contain the basic timeout information + expect(response).toContain("execute_command") + expect(response).toContain("5 seconds") + expect(response).toContain("6s") + expect(response.length).toBeGreaterThan(50) - const result = await ToolExecutionWrapper.execute( - mockOperation, - { - toolName: "execute_command", - taskId: "test-task", - timeoutMs: 50, - enableFallback: true, - }, - 50, - ) - - expect(result.success).toBe(false) - expect(result.timedOut).toBe(true) - expect(result.fallbackTriggered).toBe(true) + // The response should now contain instructions to use ask_followup_question + expect(response).toContain("You MUST now use the ask_followup_question tool") + expect(response).toContain("") + expect(response).toContain("") + expect(response).toContain("timed out") + expect(response).toContain("") + expect(response).toContain("") + expect(response).toContain("") + expect(response).toContain("") + + // Verify that assistantMessageContent was NOT modified + expect(mockTask.assistantMessageContent).toHaveLength(0) + }) }) - test("TimeoutFallbackHandler should create AI-powered responses", async () => { - // Create a mock task to test tool injection - const mockTask = { - assistantMessageContent: [], - cwd: "/test/dir", - say: vitest.fn().mockResolvedValue(undefined), - } as unknown as Task - - const response = await TimeoutFallbackHandler.createTimeoutResponse( - "execute_command", - 5000, - 6000, - { command: "npm install" }, - mockTask, - ) - - // The response should contain the basic timeout information - expect(response).toContain("execute_command") - expect(response).toContain("5 seconds") - expect(response).toContain("6s") - expect(response.length).toBeGreaterThan(50) - - // The response should now contain instructions to use ask_followup_question - expect(response).toContain("You MUST now use the ask_followup_question tool") - expect(response).toContain("") - expect(response).toContain("") - expect(response).toContain("timed out") - expect(response).toContain("") - expect(response).toContain("") - expect(response).toContain("") - expect(response).toContain("") - - // Verify that assistantMessageContent was NOT modified - expect(mockTask.assistantMessageContent).toHaveLength(0) + describe("AbortSignal Integration", () => { + test("should be properly handled", async () => { + const mockOperation = vitest.fn().mockImplementation(async (signal: AbortSignal) => { + // Simulate a long-running operation that checks abort signal + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + if (signal.aborted) { + reject(new Error("Operation was aborted")) + } else { + resolve("success") + } + }, 100) + + signal.addEventListener("abort", () => { + clearTimeout(timeout) + reject(new Error("Operation was aborted")) + }) + }) + }) + + const result = await ToolExecutionWrapper.execute( + mockOperation, + { + toolName: "execute_command", + taskId: "test-task", + timeoutMs: 50, // Shorter timeout to trigger abort + enableFallback: false, + }, + 50, + ) + + expect(result.success).toBe(false) + expect(result.timedOut).toBe(true) + }) }) - test("AbortSignal should be properly handled", async () => { - const mockOperation = vitest.fn().mockImplementation(async (signal: AbortSignal) => { - // Simulate a long-running operation that checks abort signal - return new Promise((resolve, reject) => { - const timeout = setTimeout(() => { - if (signal.aborted) { + describe("Cross-Component Integration", () => { + test("should coordinate between TimeoutManager and ToolExecutionWrapper", async () => { + const manager = TimeoutManager.getInstance() + + const mockOperation = vitest.fn().mockImplementation(async (signal: AbortSignal) => { + // Simulate operation that respects abort signal + await new Promise((resolve, reject) => { + const timeout = setTimeout(resolve, 150) + signal.addEventListener("abort", () => { + clearTimeout(timeout) reject(new Error("Operation was aborted")) - } else { - resolve("success") - } - }, 100) - - signal.addEventListener("abort", () => { - clearTimeout(timeout) - reject(new Error("Operation was aborted")) + }) }) + return [false, "completed"] }) + + // Use ToolExecutionWrapper directly + const result = await ToolExecutionWrapper.execute( + mockOperation, + { + toolName: "read_file", + taskId: "integration-test", + timeoutMs: 100, + enableFallback: true, + }, + 100, + ) + + expect(result.success).toBe(false) + expect(result.timedOut).toBe(true) + }) + + test("should handle nested timeout scenarios", async () => { + const manager = TimeoutManager.getInstance() + + // Test nested timeout operations + const outerResult = await manager.executeWithTimeout( + async () => { + // Inner timeout operation + return await manager.executeWithTimeout( + async () => { + await new Promise((resolve) => setTimeout(resolve, 150)) + return "inner success" + }, + { + toolName: "search_files", + timeoutMs: 100, + enableFallback: true, + }, + ) + }, + { + toolName: "execute_command", + timeoutMs: 200, + enableFallback: true, + }, + ) + + // The inner operation should timeout, but the outer should succeed with the timeout result + expect(outerResult.success).toBe(true) + if (outerResult.result) { + expect(outerResult.result.success).toBe(false) + expect(outerResult.result.timedOut).toBe(true) + } }) - const result = await ToolExecutionWrapper.execute( - mockOperation, - { - toolName: "execute_command", - taskId: "test-task", - timeoutMs: 50, // Shorter timeout to trigger abort - enableFallback: false, - }, - 50, - ) - - expect(result.success).toBe(false) - expect(result.timedOut).toBe(true) + test("should maintain timeout event tracking across components", async () => { + const manager = TimeoutManager.getInstance() + manager.clearLastTimeoutEvent() + + // Execute operation that will timeout + await manager.executeWithTimeout( + async () => { + await new Promise((resolve) => setTimeout(resolve, 200)) + return "should timeout" + }, + { + toolName: "browser_action", + timeoutMs: 50, + enableFallback: true, + taskId: "tracking-test", + }, + ) + + // Verify timeout event was tracked + const timeoutEvent = manager.getLastTimeoutEvent() + expect(timeoutEvent).toBeTruthy() + expect(timeoutEvent?.toolName).toBe("browser_action") + expect(timeoutEvent?.taskId).toBe("tracking-test") + expect(timeoutEvent?.timeoutMs).toBe(50) + }) }) }) diff --git a/src/core/timeout/__tests__/timeout-manager.spec.ts b/src/core/timeout/__tests__/timeout-manager.spec.ts new file mode 100644 index 0000000000..5b218d19f5 --- /dev/null +++ b/src/core/timeout/__tests__/timeout-manager.spec.ts @@ -0,0 +1,178 @@ +// npx vitest run src/core/timeout/__tests__/timeout-manager.spec.ts + +import { describe, test, expect, beforeEach, vitest } from "vitest" +import { TimeoutManager } from "../TimeoutManager" + +describe("TimeoutManager", () => { + let manager: TimeoutManager + + beforeEach(() => { + manager = TimeoutManager.getInstance() + manager.clearLastTimeoutEvent() + vitest.clearAllMocks() + }) + + describe("Basic Operations", () => { + test("should handle successful operation within timeout", async () => { + const result = await manager.executeWithTimeout( + async () => { + await new Promise((resolve) => setTimeout(resolve, 10)) + return "success" + }, + { + toolName: "execute_command", + timeoutMs: 100, + enableFallback: true, + }, + ) + + expect(result.success).toBe(true) + expect(result.result).toBe("success") + expect(result.timedOut).toBe(false) + }) + + test("should handle timeout scenarios", async () => { + const result = await manager.executeWithTimeout( + async () => { + await new Promise((resolve) => setTimeout(resolve, 200)) + return "should not reach here" + }, + { + toolName: "execute_command", + timeoutMs: 50, + enableFallback: true, + }, + ) + + expect(result.success).toBe(false) + expect(result.timedOut).toBe(true) + expect(result.error?.message).toContain("Operation timed out") + }) + }) + + describe("Timeout Event Tracking", () => { + test("should track only the last timeout event", async () => { + // First timeout + await manager.executeWithTimeout( + async () => { + await new Promise((resolve) => setTimeout(resolve, 200)) + return "should timeout" + }, + { + toolName: "execute_command", + timeoutMs: 50, + enableFallback: true, + taskId: "task-1", + }, + ) + + const firstTimeout = manager.getLastTimeoutEvent() + expect(firstTimeout).toBeTruthy() + expect(firstTimeout?.toolName).toBe("execute_command") + expect(firstTimeout?.taskId).toBe("task-1") + + // Second timeout should replace the first + await manager.executeWithTimeout( + async () => { + await new Promise((resolve) => setTimeout(resolve, 200)) + return "should timeout" + }, + { + toolName: "read_file", + timeoutMs: 50, + enableFallback: true, + taskId: "task-2", + }, + ) + + const secondTimeout = manager.getLastTimeoutEvent() + expect(secondTimeout).toBeTruthy() + expect(secondTimeout?.toolName).toBe("read_file") + expect(secondTimeout?.taskId).toBe("task-2") + expect(secondTimeout?.timestamp).toBeGreaterThan(firstTimeout!.timestamp) + }) + + test("should clear last timeout event", async () => { + // Create a timeout + await manager.executeWithTimeout( + async () => { + await new Promise((resolve) => setTimeout(resolve, 200)) + return "should timeout" + }, + { + toolName: "execute_command", + timeoutMs: 50, + enableFallback: true, + }, + ) + + expect(manager.getLastTimeoutEvent()).toBeTruthy() + + // Clear it + manager.clearLastTimeoutEvent() + expect(manager.getLastTimeoutEvent()).toBeNull() + }) + + test("should return null when no timeout has occurred", () => { + expect(manager.getLastTimeoutEvent()).toBeNull() + }) + }) + + describe("Operation Management", () => { + test("cancelOperation should work with simplified operation IDs", async () => { + // Start a long-running operation + const operationPromise = manager.executeWithTimeout( + async (signal) => { + await new Promise((resolve, reject) => { + const timeout = setTimeout(resolve, 1000) + signal.addEventListener("abort", () => { + clearTimeout(timeout) + reject(new Error("Operation was aborted")) + }) + }) + return "should be cancelled" + }, + { + toolName: "execute_command", + timeoutMs: 2000, + enableFallback: true, + taskId: "cancel-test", + }, + ) + + // Cancel it immediately + const cancelled = manager.cancelOperation("execute_command", "cancel-test") + expect(cancelled).toBe(true) + + // Verify it was cancelled + const result = await operationPromise + expect(result.success).toBe(false) + expect(result.error?.message).toContain("Operation was aborted") + }) + + test("isOperationActive should work with simplified operation IDs", async () => { + // Start an operation + const operationPromise = manager.executeWithTimeout( + async () => { + await new Promise((resolve) => setTimeout(resolve, 100)) + return "success" + }, + { + toolName: "read_file", + timeoutMs: 200, + enableFallback: true, + taskId: "active-test", + }, + ) + + // Check if it's active + expect(manager.isOperationActive("read_file", "active-test")).toBe(true) + + // Wait for completion + await operationPromise + + // Should no longer be active + expect(manager.isOperationActive("read_file", "active-test")).toBe(false) + }) + }) +}) diff --git a/src/core/timeout/__tests__/tool-injection-test.spec.ts b/src/core/timeout/__tests__/tool-injection-test.spec.ts deleted file mode 100644 index 49c9d0d225..0000000000 --- a/src/core/timeout/__tests__/tool-injection-test.spec.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { describe, test, expect, vi, beforeEach } from "vitest" -import { TimeoutFallbackHandler } from "../TimeoutFallbackHandler" -import { type TimeoutFallbackResult } from "../TimeoutFallbackHandler" -import { Task } from "../../task/Task" - -// Import the real module first -import { TimeoutFallbackHandler as RealTimeoutFallbackHandler } from "../TimeoutFallbackHandler" - -// Mock only the generateAiFallback method -vi.spyOn(RealTimeoutFallbackHandler, "generateAiFallback") - -describe("Tool Call Response Test", () => { - let mockTask: Task - - beforeEach(() => { - // Create a minimal mock task with assistantMessageContent array - mockTask = { - assistantMessageContent: [], - cwd: "/test/dir", - say: vi.fn(), - } as unknown as Task - - vi.clearAllMocks() - }) - - test("should return response with ask_followup_question tool instructions", async () => { - // Mock the TimeoutFallbackHandler to return a successful AI result - const mockAiResult: TimeoutFallbackResult = { - success: true, - toolCall: { - name: "ask_followup_question", - params: { - question: "The execute_command operation timed out after 5 seconds. How would you like to proceed?", - follow_up: - "Try a different approach\nBreak into smaller steps", - }, - }, - } - - // Mock the generateAiFallback method - vi.mocked(RealTimeoutFallbackHandler.generateAiFallback).mockResolvedValue(mockAiResult) - - // Call createTimeoutResponse - const response = await TimeoutFallbackHandler.createTimeoutResponse( - "execute_command", - 5000, - 6000, - { command: "npm install" }, - mockTask, - ) - - // Check that the response contains the base timeout message - expect(response).toContain("timed out after 5 seconds") - expect(response).toContain("Execution Time: 6s") - - // Check that the response includes instructions to use ask_followup_question - expect(response).toContain("You MUST now use the ask_followup_question tool") - expect(response).toContain("") - expect(response).toContain(`${mockAiResult.toolCall?.params.question}`) - expect(response).toContain("") - expect(response).toContain(mockAiResult.toolCall?.params.follow_up) - expect(response).toContain("") - expect(response).toContain("") - expect(response).toContain("This is required to help the user decide how to proceed after the timeout.") - - // Verify that assistantMessageContent was NOT modified - expect(mockTask.assistantMessageContent).toHaveLength(0) - }) - - test("should return fallback message when AI generation fails", async () => { - // Mock the generateAiFallback to return a failure - vi.mocked(RealTimeoutFallbackHandler.generateAiFallback).mockResolvedValue({ - success: false, - error: "AI generation failed", - }) - - // Call createTimeoutResponse - const response = await TimeoutFallbackHandler.createTimeoutResponse( - "execute_command", - 5000, - 6000, - { command: "npm install" }, - mockTask, - ) - - // Check that the response contains the base timeout message - expect(response).toContain("timed out after 5 seconds") - expect(response).toContain("Execution Time: 6s") - - // Check that the response contains the fallback message - expect(response).toContain( - "The operation timed out. Please consider breaking this into smaller steps or trying a different approach.", - ) - - // Should not contain ask_followup_question instructions - expect(response).not.toContain("ask_followup_question") - }) -}) diff --git a/src/core/timeout/__tests__/ui-integration.spec.ts b/src/core/timeout/__tests__/ui-integration.spec.ts deleted file mode 100644 index 8065aa12ed..0000000000 --- a/src/core/timeout/__tests__/ui-integration.spec.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { describe, it, expect, vi } from "vitest" -import { TimeoutFallbackHandler } from "../TimeoutFallbackHandler" - -describe("UI Integration - AI Timeout Fallbacks", () => { - it("should generate AI fallbacks using static method", async () => { - const context = { - toolName: "execute_command" as const, - timeoutMs: 30000, - executionTimeMs: 25000, - toolParams: { command: "npm install" }, - } - - const result = await TimeoutFallbackHandler.generateAiFallback(context) - - expect(result.success).toBe(true) - expect(result.toolCall).toBeDefined() - expect(result.toolCall?.name).toBe("ask_followup_question") - expect(result.toolCall?.params.question).toContain("execute_command") - }) - - it("should create timeout response with AI fallbacks", async () => { - const response = await TimeoutFallbackHandler.createTimeoutResponse("execute_command", 30000, 25000, { - command: "npm install", - }) - - expect(response).toContain("execute_command") - expect(response).toContain("timed out") - expect(response.length).toBeGreaterThan(100) // Should contain substantial content - }) - - it("should create timeout response when AI fallbacks fail", async () => { - const response = await TimeoutFallbackHandler.createTimeoutResponse("execute_command", 30000, 25000, { - command: "npm install", - }) - - expect(response).toContain("execute_command") - expect(response).toContain("timed out") - expect(response.length).toBeGreaterThan(50) // Should contain basic timeout message - }) - - it("should validate UI setting flow", () => { - // This test validates that timeout settings can be toggled - const settings = { - timeoutFallbackEnabled: true, - toolExecutionTimeoutMs: 30000, - } - - // Simulate UI toggle - settings.timeoutFallbackEnabled = false - expect(settings.timeoutFallbackEnabled).toBe(false) - - // Simulate timeout duration change - settings.toolExecutionTimeoutMs = 60000 - expect(settings.toolExecutionTimeoutMs).toBe(60000) - }) - - it("should handle different tool types with AI fallbacks", async () => { - const commandResponse = await TimeoutFallbackHandler.createTimeoutResponse("execute_command", 30000, 25000, { - command: "npm test", - }) - - const browserResponse = await TimeoutFallbackHandler.createTimeoutResponse("browser_action", 30000, 25000, { - action: "click", - }) - - expect(commandResponse).toContain("execute_command") - expect(browserResponse).toContain("browser_action") - expect(commandResponse).not.toEqual(browserResponse) - }) -}) diff --git a/src/core/tools/executeCommandTool.ts b/src/core/tools/executeCommandTool.ts index f1ca671143..fcbf74e7b2 100644 --- a/src/core/tools/executeCommandTool.ts +++ b/src/core/tools/executeCommandTool.ts @@ -16,6 +16,8 @@ import { TerminalRegistry } from "../../integrations/terminal/TerminalRegistry" import { Terminal } from "../../integrations/terminal/Terminal" import { ToolExecutionWrapper, TimeoutFallbackHandler } from "../timeout" +const DEFAULT_TOOL_EXECUTION_TIMEOUT_MS = 60000 // 1 minute default + class ShellIntegrationError extends Error {} export async function executeCommandTool( @@ -64,7 +66,7 @@ export async function executeCommandTool( const { terminalOutputLineLimit = 500, terminalShellIntegrationDisabled = false, - toolExecutionTimeoutMs = 300000, // 5 minutes default + toolExecutionTimeoutMs = 60000, // 1 minute default } = clineProviderState ?? {} const options: ExecuteCommandOptions = { @@ -136,7 +138,7 @@ export async function executeCommand( // Get timeout from settings if not provided const clineProvider = await cline.providerRef.deref() const clineProviderState = await clineProvider?.getState() - const defaultTimeoutMs = clineProviderState?.toolExecutionTimeoutMs ?? 300000 // 5 minutes default + const defaultTimeoutMs = clineProviderState?.toolExecutionTimeoutMs ?? DEFAULT_TOOL_EXECUTION_TIMEOUT_MS const actualTimeoutMs = timeoutMs ?? defaultTimeoutMs const timeoutFallbackEnabled = clineProviderState?.timeoutFallbackEnabled ?? true diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 3530d98c5d..08682cc223 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1524,7 +1524,7 @@ export class ClineProvider hasOpenedModeSelector: this.getGlobalState("hasOpenedModeSelector") ?? false, alwaysAllowFollowupQuestions: alwaysAllowFollowupQuestions ?? false, followupAutoApproveTimeoutMs: followupAutoApproveTimeoutMs ?? 60000, - toolExecutionTimeoutMs: toolExecutionTimeoutMs ?? 300000, + toolExecutionTimeoutMs: toolExecutionTimeoutMs ?? 60000, timeoutFallbackEnabled: timeoutFallbackEnabled ?? false, } } @@ -1638,7 +1638,7 @@ export class ClineProvider terminalZshP10k: stateValues.terminalZshP10k ?? false, terminalZdotdir: stateValues.terminalZdotdir ?? false, terminalCompressProgressBar: stateValues.terminalCompressProgressBar ?? true, - toolExecutionTimeoutMs: stateValues.toolExecutionTimeoutMs ?? 300000, // 5 minutes default + toolExecutionTimeoutMs: stateValues.toolExecutionTimeoutMs ?? 60000, timeoutFallbackEnabled: stateValues.timeoutFallbackEnabled ?? false, mode: stateValues.mode ?? defaultModeSlug, language: stateValues.language ?? formatLanguage(vscode.env.language), diff --git a/webview-ui/src/components/settings/AutoApproveSettings.tsx b/webview-ui/src/components/settings/AutoApproveSettings.tsx index f5685bacba..75d38f5222 100644 --- a/webview-ui/src/components/settings/AutoApproveSettings.tsx +++ b/webview-ui/src/components/settings/AutoApproveSettings.tsx @@ -71,7 +71,7 @@ export const AutoApproveSettings = ({ followupAutoApproveTimeoutMs = 60000, allowedCommands, timeoutFallbackEnabled, - toolExecutionTimeoutMs, + toolExecutionTimeoutMs = 60000, setCachedStateField, ...props }: AutoApproveSettingsProps) => { diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index 1bc78e3634..137e23cbb1 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -46,7 +46,7 @@ export interface ExtensionStateContextType extends ExtensionState { setFollowupAutoApproveTimeoutMs: (value: number) => void // Setter for the timeout timeoutFallbackEnabled?: boolean // New property for timeout fallback enabled setTimeoutFallbackEnabled: (value: boolean) => void // Setter for timeout fallback enabled - toolExecutionTimeoutMs?: number // New property for tool execution timeout + toolExecutionTimeoutMs: number | undefined // New property for tool execution timeout setToolExecutionTimeoutMs: (value: number) => void // Setter for tool execution timeout condensingApiConfigId?: string setCondensingApiConfigId: (value: string) => void @@ -230,7 +230,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode alwaysAllowUpdateTodoList: true, // Timeout settings timeoutFallbackEnabled: false, // Default to disabled - toolExecutionTimeoutMs: 300000, // 5 minutes default + toolExecutionTimeoutMs: undefined, // Will be set from global settings }) const [didHydrateState, setDidHydrateState] = useState(false) @@ -245,7 +245,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode const [alwaysAllowFollowupQuestions, setAlwaysAllowFollowupQuestions] = useState(false) // Add state for follow-up questions auto-approve const [followupAutoApproveTimeoutMs, setFollowupAutoApproveTimeoutMs] = useState(undefined) // Will be set from global settings const [timeoutFallbackEnabled, setTimeoutFallbackEnabledState] = useState(false) // Add state for timeout fallback enabled - const [toolExecutionTimeoutMs, setToolExecutionTimeoutMsState] = useState(300000) // Add state for tool execution timeout (5 minutes default) + const [toolExecutionTimeoutMs, setToolExecutionTimeoutMsState] = useState(undefined) // Will be set from global settings const [marketplaceInstalledMetadata, setMarketplaceInstalledMetadata] = useState({ project: {}, global: {}, diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index 15f3039d1e..99b267bc6c 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -230,7 +230,7 @@ "hasQuestion": "Roo has a question:" }, "taskCompleted": "Task Completed", - "toolTimeout": "Tool Timeout", + "toolTimeout": "Automatic Tool Timeout: Suggesting alternatives...", "error": "Error", "diffError": { "title": "Edit Unsuccessful" diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 5b200778bb..f9436c8594 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -176,7 +176,7 @@ "description": "Configure how Roo handles tool operations that exceed their timeout limits", "timeoutFallbackEnabled": { "label": "Enable timeout handling", - "description": "Enable automatic timeout detection and fallback suggestions for long-running operations" + "description": "Automatically timeout long-running operations and suggest fallback options." }, "toolExecutionTimeoutMs": { "label": "Tool execution timeout (ms)", From ddc255c74fb2342159c418f0f6d6096ebf1d6c67 Mon Sep 17 00:00:00 2001 From: Will Li Date: Wed, 9 Jul 2025 08:21:44 -0700 Subject: [PATCH 06/12] translations --- webview-ui/src/i18n/locales/ca/chat.json | 1 + webview-ui/src/i18n/locales/ca/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/de/chat.json | 1 + webview-ui/src/i18n/locales/de/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/es/chat.json | 1 + webview-ui/src/i18n/locales/es/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/fr/chat.json | 1 + webview-ui/src/i18n/locales/fr/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/hi/chat.json | 1 + webview-ui/src/i18n/locales/hi/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/id/chat.json | 1 + webview-ui/src/i18n/locales/id/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/it/chat.json | 1 + webview-ui/src/i18n/locales/it/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/ja/chat.json | 1 + webview-ui/src/i18n/locales/ja/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/ko/chat.json | 1 + webview-ui/src/i18n/locales/ko/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/nl/chat.json | 1 + webview-ui/src/i18n/locales/nl/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/pl/chat.json | 1 + webview-ui/src/i18n/locales/pl/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/pt-BR/chat.json | 1 + webview-ui/src/i18n/locales/pt-BR/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/ru/chat.json | 1 + webview-ui/src/i18n/locales/ru/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/tr/chat.json | 1 + webview-ui/src/i18n/locales/tr/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/vi/chat.json | 3 ++- webview-ui/src/i18n/locales/vi/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/zh-CN/chat.json | 3 ++- webview-ui/src/i18n/locales/zh-CN/settings.json | 12 ++++++++++++ webview-ui/src/i18n/locales/zh-TW/chat.json | 3 ++- webview-ui/src/i18n/locales/zh-TW/settings.json | 12 ++++++++++++ 34 files changed, 224 insertions(+), 3 deletions(-) diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index 1dd892a39f..ac8c69a153 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -215,6 +215,7 @@ "hasQuestion": "Roo té una pregunta:" }, "taskCompleted": "Tasca completada", + "toolTimeout": "Temps d'espera de l'eina esgotat: Suggerint alternatives...", "powershell": { "issues": "Sembla que estàs tenint problemes amb Windows PowerShell, si us plau consulta aquesta documentació per a més informació." }, diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index 2e2197f123..b36dcd6db4 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -170,6 +170,18 @@ "title": "Màximes Sol·licituds", "description": "Fes aquesta quantitat de sol·licituds API automàticament abans de demanar aprovació per continuar amb la tasca.", "unlimited": "Il·limitat" + }, + "timeout": { + "label": "Temps d'espera", + "description": "Configura com Roo gestiona les operacions d'eines que superen els seus límits de temps d'espera", + "timeoutFallbackEnabled": { + "label": "Habilitar gestió de temps d'espera", + "description": "Atura automàticament les operacions de llarga durada i suggereix opcions alternatives." + }, + "toolExecutionTimeoutMs": { + "label": "Temps d'espera d'execució d'eines (ms)", + "description": "Temps màxim d'espera per a operacions d'eines abans d'activar la gestió de temps d'espera (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index c62fe9d3bb..c98ca8a3b6 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -215,6 +215,7 @@ "hasQuestion": "Roo hat eine Frage:" }, "taskCompleted": "Aufgabe abgeschlossen", + "toolTimeout": "Automatische Tool-Zeitüberschreitung: Schlage Alternativen vor...", "powershell": { "issues": "Es scheint, dass du Probleme mit Windows PowerShell hast, bitte sieh dir dies an" }, diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 14af077b23..edce4177cd 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -170,6 +170,18 @@ "title": "Maximale Anfragen", "description": "Automatisch so viele API-Anfragen stellen, bevor du um die Erlaubnis gebeten wirst, mit der Aufgabe fortzufahren.", "unlimited": "Unbegrenzt" + }, + "timeout": { + "label": "Zeitüberschreitung", + "description": "Konfiguriere, wie Roo mit Tool-Operationen umgeht, die ihre Zeitlimits überschreiten", + "timeoutFallbackEnabled": { + "label": "Zeitüberschreitungsbehandlung aktivieren", + "description": "Automatisch lang laufende Operationen beenden und Alternativen vorschlagen." + }, + "toolExecutionTimeoutMs": { + "label": "Tool-Ausführungszeitlimit (ms)", + "description": "Maximale Wartezeit für Tool-Operationen, bevor die Zeitüberschreitungsbehandlung ausgelöst wird (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index a4349b13dc..53cd277f3a 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -1,4 +1,5 @@ { + "toolTimeout": "Tiempo de espera de herramienta agotado: Sugiriendo alternativas...", "greeting": "Bienvenido a Roo Code", "task": { "title": "Tarea", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index d6cebea206..7c762b5267 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -170,6 +170,18 @@ "title": "Solicitudes máximas", "description": "Realizar automáticamente esta cantidad de solicitudes a la API antes de pedir aprobación para continuar con la tarea.", "unlimited": "Ilimitado" + }, + "timeout": { + "label": "Tiempo de espera", + "description": "Configura cómo Roo maneja las operaciones de herramientas que exceden sus límites de tiempo", + "timeoutFallbackEnabled": { + "label": "Habilitar manejo de tiempo de espera", + "description": "Terminar automáticamente operaciones de larga duración y sugerir opciones alternativas." + }, + "toolExecutionTimeoutMs": { + "label": "Tiempo de espera de ejecución de herramienta (ms)", + "description": "Tiempo máximo de espera para operaciones de herramientas antes de activar el manejo de tiempo de espera (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index b5f06354bb..e57501c176 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -1,4 +1,5 @@ { + "toolTimeout": "Délai d'attente de l'outil dépassé : Suggestion d'alternatives...", "greeting": "Bienvenue sur Roo Code", "task": { "title": "Tâche", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 281fb705fc..5d7f6e923c 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -170,6 +170,18 @@ "title": "Requêtes maximales", "description": "Effectuer automatiquement ce nombre de requêtes API avant de demander l'approbation pour continuer la tâche.", "unlimited": "Illimité" + }, + "timeout": { + "label": "Délai d'attente", + "description": "Configurez la façon dont Roo gère les opérations d'outils qui dépassent leurs limites de temps", + "timeoutFallbackEnabled": { + "label": "Activer la gestion des délais d'attente", + "description": "Arrêter automatiquement les opérations de longue durée et suggérer des alternatives." + }, + "toolExecutionTimeoutMs": { + "label": "Délai d'exécution des outils (ms)", + "description": "Temps d'attente maximal pour les opérations d'outils avant de déclencher la gestion des délais (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index 9afdcbdd38..dc7d82c1f2 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -1,4 +1,5 @@ { + "toolTimeout": "टूल टाइमआउट: विकल्प सुझा रहा हूं...", "greeting": "Roo Code में आपका स्वागत है", "task": { "title": "कार्य", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 4b8132768f..f6b3a7f03f 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -170,6 +170,18 @@ "title": "अधिकतम अनुरोध", "description": "कार्य जारी रखने के लिए अनुमति मांगने से पहले स्वचालित रूप से इतने API अनुरोध करें।", "unlimited": "असीमित" + }, + "timeout": { + "label": "टाइमआउट", + "description": "कॉन्फ़िगर करें कि Roo उन टूल ऑपरेशन्स को कैसे हैंडल करता है जो अपनी समय सीमा पार कर जाते हैं", + "timeoutFallbackEnabled": { + "label": "टाइमआउट हैंडलिंग सक्षम करें", + "description": "लंबे समय तक चलने वाले ऑपरेशन्स को स्वचालित रूप से समाप्त करें और विकल्प सुझाएं।" + }, + "toolExecutionTimeoutMs": { + "label": "टूल एक्जीक्यूशन टाइमआउट (ms)", + "description": "टाइमआउट हैंडलिंग ट्रिगर करने से पहले टूल ऑपरेशन्स के लिए अधिकतम प्रतीक्षा समय (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index fc0bd5056f..a86456313a 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -1,4 +1,5 @@ { + "toolTimeout": "Timeout Tool Otomatis: Menyarankan alternatif...", "greeting": "Selamat datang di Roo Code", "task": { "title": "Tugas", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index ac1454ab7b..d584b3bb09 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -174,6 +174,18 @@ "title": "Permintaan Maks", "description": "Secara otomatis membuat sejumlah permintaan API ini sebelum meminta persetujuan untuk melanjutkan tugas.", "unlimited": "Tidak terbatas" + }, + "timeout": { + "label": "Timeout", + "description": "Konfigurasi cara Roo menangani operasi tool yang melebihi batas waktu", + "timeoutFallbackEnabled": { + "label": "Aktifkan penanganan timeout", + "description": "Otomatis menghentikan operasi yang berjalan lama dan menyarankan alternatif." + }, + "toolExecutionTimeoutMs": { + "label": "Timeout eksekusi tool (ms)", + "description": "Waktu tunggu maksimum untuk operasi tool sebelum memicu penanganan timeout (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index f49a25dfa6..c3ccfe1f0f 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -1,4 +1,5 @@ { + "toolTimeout": "Timeout automatico dello strumento: Suggerendo alternative...", "greeting": "Benvenuto a Roo Code", "task": { "title": "Attività", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 7627486863..233f81900a 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -170,6 +170,18 @@ "title": "Richieste massime", "description": "Esegui automaticamente questo numero di richieste API prima di chiedere l'approvazione per continuare con l'attività.", "unlimited": "Illimitato" + }, + "timeout": { + "label": "Timeout", + "description": "Configura come Roo gestisce le operazioni degli strumenti che superano i loro limiti di tempo", + "timeoutFallbackEnabled": { + "label": "Abilita gestione timeout", + "description": "Termina automaticamente le operazioni di lunga durata e suggerisci alternative." + }, + "toolExecutionTimeoutMs": { + "label": "Timeout esecuzione strumento (ms)", + "description": "Tempo massimo di attesa per le operazioni degli strumenti prima di attivare la gestione del timeout (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index cb5ebcdafd..443c63eb1a 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -1,4 +1,5 @@ { + "toolTimeout": "自動ツールタイムアウト:代替案を提案しています...", "greeting": "Roo Code へようこそ", "task": { "title": "タスク", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index f779749cd4..0be5e161c9 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -170,6 +170,18 @@ "title": "最大リクエスト数", "description": "タスクを続行するための承認を求める前に、自動的にこの数のAPIリクエストを行います。", "unlimited": "無制限" + }, + "timeout": { + "label": "タイムアウト", + "description": "ツール操作が制限時間を超えた場合のRooの処理方法を設定", + "timeoutFallbackEnabled": { + "label": "タイムアウト処理を有効にする", + "description": "長時間実行される操作を自動的に終了し、代替案を提案します。" + }, + "toolExecutionTimeoutMs": { + "label": "ツール実行タイムアウト(ms)", + "description": "タイムアウト処理をトリガーする前のツール操作の最大待機時間(1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index 1f86dc8cf4..5ca6075ec3 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -1,4 +1,5 @@ { + "toolTimeout": "자동 도구 타임아웃: 대안을 제안하고 있습니다...", "greeting": "Roo Code에 오신 것을 환영합니다", "task": { "title": "작업", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 2ea16f7834..1dac64e0a2 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -170,6 +170,18 @@ "title": "최대 요청 수", "description": "작업을 계속하기 위한 승인을 요청하기 전에 자동으로 이 수의 API 요청을 수행합니다.", "unlimited": "무제한" + }, + "timeout": { + "label": "타임아웃", + "description": "도구 작업이 시간 제한을 초과할 때 Roo가 처리하는 방법을 구성", + "timeoutFallbackEnabled": { + "label": "타임아웃 처리 활성화", + "description": "장시간 실행되는 작업을 자동으로 종료하고 대안을 제안합니다." + }, + "toolExecutionTimeoutMs": { + "label": "도구 실행 타임아웃 (ms)", + "description": "타임아웃 처리를 트리거하기 전 도구 작업의 최대 대기 시간 (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index d228d7b0c2..71ebaf2c28 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -1,4 +1,5 @@ { + "toolTimeout": "Automatische tool timeout: Alternatieven voorstellen...", "greeting": "Welkom bij Roo Code", "task": { "title": "Taak", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index 92b00cf3ff..8a07db8bcf 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -170,6 +170,18 @@ "title": "Maximale verzoeken", "description": "Voer automatisch dit aantal API-verzoeken uit voordat om goedkeuring wordt gevraagd om door te gaan met de taak.", "unlimited": "Onbeperkt" + }, + "timeout": { + "label": "Timeout", + "description": "Configureer hoe Roo omgaat met tool-operaties die hun tijdslimieten overschrijden", + "timeoutFallbackEnabled": { + "label": "Timeout-afhandeling inschakelen", + "description": "Automatisch langlopende operaties beëindigen en alternatieven voorstellen." + }, + "toolExecutionTimeoutMs": { + "label": "Tool-uitvoering timeout (ms)", + "description": "Maximale wachttijd voor tool-operaties voordat timeout-afhandeling wordt geactiveerd (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index fdb39b0851..35ee26990c 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -1,4 +1,5 @@ { + "toolTimeout": "Automatyczny timeout narzędzia: Sugerowanie alternatyw...", "greeting": "Witamy w Roo Code", "task": { "title": "Zadanie", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 34e0ac52ef..6679f1d3d1 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -170,6 +170,18 @@ "title": "Maksymalna liczba żądań", "description": "Automatycznie wykonaj tyle żądań API przed poproszeniem o zgodę na kontynuowanie zadania.", "unlimited": "Bez limitu" + }, + "timeout": { + "label": "Timeout", + "description": "Skonfiguruj sposób obsługi przez Roo operacji narzędzi, które przekraczają swoje limity czasowe", + "timeoutFallbackEnabled": { + "label": "Włącz obsługę timeout", + "description": "Automatycznie kończ długotrwałe operacje i sugeruj alternatywy." + }, + "toolExecutionTimeoutMs": { + "label": "Timeout wykonania narzędzia (ms)", + "description": "Maksymalny czas oczekiwania na operacje narzędzi przed uruchomieniem obsługi timeout (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index b37879f2f0..892ed6c49d 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -1,4 +1,5 @@ { + "toolTimeout": "Timeout automático da ferramenta: Sugerindo alternativas...", "greeting": "Bem-vindo ao Roo Code", "task": { "title": "Tarefa", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index e696ab0f77..3a75b2bc15 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -170,6 +170,18 @@ "title": "Máximo de Solicitações", "description": "Fazer automaticamente este número de requisições à API antes de pedir aprovação para continuar com a tarefa.", "unlimited": "Ilimitado" + }, + "timeout": { + "label": "Timeout", + "description": "Configure como o Roo lida com operações de ferramentas que excedem seus limites de tempo", + "timeoutFallbackEnabled": { + "label": "Ativar tratamento de timeout", + "description": "Terminar automaticamente operações de longa duração e sugerir alternativas." + }, + "toolExecutionTimeoutMs": { + "label": "Timeout de execução da ferramenta (ms)", + "description": "Tempo máximo de espera para operações de ferramentas antes de acionar o tratamento de timeout (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index 5865e41a53..d63264259d 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -1,4 +1,5 @@ { + "toolTimeout": "Автоматический тайм-аут инструмента: Предлагаю альтернативы...", "greeting": "Добро пожаловать в Roo Code", "task": { "title": "Задача", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index 3e6a7a9d76..41b7aac00b 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -170,6 +170,18 @@ "title": "Максимум запросов", "description": "Автоматически выполнять это количество API-запросов перед запросом разрешения на продолжение задачи.", "unlimited": "Без ограничений" + }, + "timeout": { + "label": "Тайм-аут", + "description": "Настройте, как Roo обрабатывает операции инструментов, которые превышают свои временные лимиты", + "timeoutFallbackEnabled": { + "label": "Включить обработку тайм-аута", + "description": "Автоматически завершать долго выполняющиеся операции и предлагать альтернативы." + }, + "toolExecutionTimeoutMs": { + "label": "Тайм-аут выполнения инструмента (мс)", + "description": "Максимальное время ожидания операций инструментов перед запуском обработки тайм-аута (1000-1800000мс)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index 6c5bd20353..3377c8e70f 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -1,4 +1,5 @@ { + "toolTimeout": "Otomatik araç zaman aşımı: Alternatifler öneriliyor...", "greeting": "Roo Code'a Hoş Geldiniz", "task": { "title": "Görev", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index c0a3b8f501..6d81fa56d6 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -170,6 +170,18 @@ "title": "Maksimum İstek", "description": "Göreve devam etmek için onay istemeden önce bu sayıda API isteği otomatik olarak yap.", "unlimited": "Sınırsız" + }, + "timeout": { + "label": "Zaman Aşımı", + "description": "Roo'nun zaman sınırlarını aşan araç işlemlerini nasıl ele aldığını yapılandırın", + "timeoutFallbackEnabled": { + "label": "Zaman aşımı işlemeyi etkinleştir", + "description": "Uzun süren işlemleri otomatik olarak sonlandır ve alternatifler öner." + }, + "toolExecutionTimeoutMs": { + "label": "Araç yürütme zaman aşımı (ms)", + "description": "Zaman aşımı işlemeyi tetiklemeden önce araç işlemleri için maksimum bekleme süresi (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index eb7cdc2306..2aa199d056 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -316,5 +316,6 @@ }, "versionIndicator": { "ariaLabel": "Phiên bản {{version}} - Nhấp để xem ghi chú phát hành" - } + }, + "toolTimeout": "Tự động hết thời gian chờ công cụ: Đang đề xuất các lựa chọn thay thế..." } diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index e553f5d0c2..c5645e2d81 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -170,6 +170,18 @@ "title": "Số lượng yêu cầu tối đa", "description": "Tự động thực hiện số lượng API request này trước khi yêu cầu phê duyệt để tiếp tục với nhiệm vụ.", "unlimited": "Không giới hạn" + }, + "timeout": { + "label": "Thời gian chờ", + "description": "Cấu hình cách Roo xử lý các thao tác công cụ vượt quá giới hạn thời gian", + "timeoutFallbackEnabled": { + "label": "Bật xử lý thời gian chờ", + "description": "Tự động kết thúc các thao tác chạy lâu và đề xuất các lựa chọn thay thế." + }, + "toolExecutionTimeoutMs": { + "label": "Thời gian chờ thực thi công cụ (ms)", + "description": "Thời gian chờ tối đa cho các thao tác công cụ trước khi kích hoạt xử lý thời gian chờ (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index 93494e6f50..de30f5e693 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -316,5 +316,6 @@ }, "versionIndicator": { "ariaLabel": "版本 {{version}} - 点击查看发布说明" - } + }, + "toolTimeout": "自动工具超时:正在建议替代方案..." } diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index d8d875c85f..a59c00f5eb 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -170,6 +170,18 @@ "title": "最大请求数", "description": "在请求批准以继续执行任务之前,自动发出此数量的 API 请求。", "unlimited": "无限制" + }, + "timeout": { + "label": "超时", + "description": "配置 Roo 如何处理超过时间限制的工具操作", + "timeoutFallbackEnabled": { + "label": "启用超时处理", + "description": "自动终止长时间运行的操作并建议替代方案。" + }, + "toolExecutionTimeoutMs": { + "label": "工具执行超时 (ms)", + "description": "触发超时处理前工具操作的最大等待时间 (1000-1800000ms)" + } } }, "providers": { diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index e7a476cb37..0ece02f426 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -316,5 +316,6 @@ }, "versionIndicator": { "ariaLabel": "版本 {{version}} - 點擊查看發布說明" - } + }, + "toolTimeout": "自動工具逾時:正在建議替代方案..." } diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index f08cb0dbba..7639474992 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -170,6 +170,18 @@ "title": "最大請求數", "description": "在請求批准以繼續執行工作之前,自動發出此數量的 API 請求。", "unlimited": "無限制" + }, + "timeout": { + "label": "逾時", + "description": "設定 Roo 如何處理超過時間限制的工具操作", + "timeoutFallbackEnabled": { + "label": "啟用逾時處理", + "description": "自動終止長時間執行的操作並建議替代方案。" + }, + "toolExecutionTimeoutMs": { + "label": "工具執行逾時 (ms)", + "description": "觸發逾時處理前工具操作的最大等待時間 (1000-1800000ms)" + } } }, "providers": { From 026d37d66dc1b8275e419db5bc84d4028fd9aa56 Mon Sep 17 00:00:00 2001 From: Will Li Date: Wed, 9 Jul 2025 08:31:30 -0700 Subject: [PATCH 07/12] small copy change --- webview-ui/src/i18n/locales/ca/settings.json | 2 +- webview-ui/src/i18n/locales/de/settings.json | 2 +- webview-ui/src/i18n/locales/en/settings.json | 2 +- webview-ui/src/i18n/locales/es/settings.json | 2 +- webview-ui/src/i18n/locales/fr/settings.json | 2 +- webview-ui/src/i18n/locales/hi/settings.json | 2 +- webview-ui/src/i18n/locales/id/settings.json | 2 +- webview-ui/src/i18n/locales/it/settings.json | 2 +- webview-ui/src/i18n/locales/ja/settings.json | 2 +- webview-ui/src/i18n/locales/ko/settings.json | 2 +- webview-ui/src/i18n/locales/nl/settings.json | 2 +- webview-ui/src/i18n/locales/pl/settings.json | 2 +- webview-ui/src/i18n/locales/pt-BR/settings.json | 2 +- webview-ui/src/i18n/locales/ru/settings.json | 2 +- webview-ui/src/i18n/locales/tr/settings.json | 2 +- webview-ui/src/i18n/locales/vi/settings.json | 2 +- webview-ui/src/i18n/locales/zh-CN/settings.json | 2 +- webview-ui/src/i18n/locales/zh-TW/settings.json | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index b36dcd6db4..aeb8fa37af 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -176,7 +176,7 @@ "description": "Configura com Roo gestiona les operacions d'eines que superen els seus límits de temps d'espera", "timeoutFallbackEnabled": { "label": "Habilitar gestió de temps d'espera", - "description": "Atura automàticament les operacions de llarga durada i suggereix opcions alternatives." + "description": "Atura automàticament les operacions d'eines de llarga durada i suggereix opcions alternatives." }, "toolExecutionTimeoutMs": { "label": "Temps d'espera d'execució d'eines (ms)", diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index edce4177cd..b744bcb6eb 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -176,7 +176,7 @@ "description": "Konfiguriere, wie Roo mit Tool-Operationen umgeht, die ihre Zeitlimits überschreiten", "timeoutFallbackEnabled": { "label": "Zeitüberschreitungsbehandlung aktivieren", - "description": "Automatisch lang laufende Operationen beenden und Alternativen vorschlagen." + "description": "Automatisch lang laufende Tool-Operationen beenden und Fallback-Optionen vorschlagen." }, "toolExecutionTimeoutMs": { "label": "Tool-Ausführungszeitlimit (ms)", diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index f9436c8594..c10d1e5f2f 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -176,7 +176,7 @@ "description": "Configure how Roo handles tool operations that exceed their timeout limits", "timeoutFallbackEnabled": { "label": "Enable timeout handling", - "description": "Automatically timeout long-running operations and suggest fallback options." + "description": "Automatically timeout long-running tool operations and suggest fallback options." }, "toolExecutionTimeoutMs": { "label": "Tool execution timeout (ms)", diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index 7c762b5267..28df923097 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -176,7 +176,7 @@ "description": "Configura cómo Roo maneja las operaciones de herramientas que exceden sus límites de tiempo", "timeoutFallbackEnabled": { "label": "Habilitar manejo de tiempo de espera", - "description": "Terminar automáticamente operaciones de larga duración y sugerir opciones alternativas." + "description": "Terminar automáticamente operaciones de herramientas de larga duración y sugerir opciones de respaldo." }, "toolExecutionTimeoutMs": { "label": "Tiempo de espera de ejecución de herramienta (ms)", diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 5d7f6e923c..aba8dd8e79 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -176,7 +176,7 @@ "description": "Configurez la façon dont Roo gère les opérations d'outils qui dépassent leurs limites de temps", "timeoutFallbackEnabled": { "label": "Activer la gestion des délais d'attente", - "description": "Arrêter automatiquement les opérations de longue durée et suggérer des alternatives." + "description": "Arrêter automatiquement les opérations d'outils de longue durée et suggérer des options de secours." }, "toolExecutionTimeoutMs": { "label": "Délai d'exécution des outils (ms)", diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index f6b3a7f03f..854ce7eaf6 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -176,7 +176,7 @@ "description": "कॉन्फ़िगर करें कि Roo उन टूल ऑपरेशन्स को कैसे हैंडल करता है जो अपनी समय सीमा पार कर जाते हैं", "timeoutFallbackEnabled": { "label": "टाइमआउट हैंडलिंग सक्षम करें", - "description": "लंबे समय तक चलने वाले ऑपरेशन्स को स्वचालित रूप से समाप्त करें और विकल्प सुझाएं।" + "description": "लंबे समय तक चलने वाले टूल ऑपरेशन्स को स्वचालित रूप से समाप्त करें और फॉलबैक विकल्प सुझाएं।" }, "toolExecutionTimeoutMs": { "label": "टूल एक्जीक्यूशन टाइमआउट (ms)", diff --git a/webview-ui/src/i18n/locales/id/settings.json b/webview-ui/src/i18n/locales/id/settings.json index d584b3bb09..53c2e44ae2 100644 --- a/webview-ui/src/i18n/locales/id/settings.json +++ b/webview-ui/src/i18n/locales/id/settings.json @@ -180,7 +180,7 @@ "description": "Konfigurasi cara Roo menangani operasi tool yang melebihi batas waktu", "timeoutFallbackEnabled": { "label": "Aktifkan penanganan timeout", - "description": "Otomatis menghentikan operasi yang berjalan lama dan menyarankan alternatif." + "description": "Otomatis menghentikan operasi alat yang berjalan lama dan menyarankan opsi fallback." }, "toolExecutionTimeoutMs": { "label": "Timeout eksekusi tool (ms)", diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index 233f81900a..54dbd05ae9 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -176,7 +176,7 @@ "description": "Configura come Roo gestisce le operazioni degli strumenti che superano i loro limiti di tempo", "timeoutFallbackEnabled": { "label": "Abilita gestione timeout", - "description": "Termina automaticamente le operazioni di lunga durata e suggerisci alternative." + "description": "Termina automaticamente le operazioni degli strumenti di lunga durata e suggerisci opzioni di fallback." }, "toolExecutionTimeoutMs": { "label": "Timeout esecuzione strumento (ms)", diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index 0be5e161c9..09a0af1ac2 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -176,7 +176,7 @@ "description": "ツール操作が制限時間を超えた場合のRooの処理方法を設定", "timeoutFallbackEnabled": { "label": "タイムアウト処理を有効にする", - "description": "長時間実行される操作を自動的に終了し、代替案を提案します。" + "description": "長時間実行されるツール操作を自動的に終了し、フォールバックオプションを提案します。" }, "toolExecutionTimeoutMs": { "label": "ツール実行タイムアウト(ms)", diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 1dac64e0a2..97ad9a4625 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -176,7 +176,7 @@ "description": "도구 작업이 시간 제한을 초과할 때 Roo가 처리하는 방법을 구성", "timeoutFallbackEnabled": { "label": "타임아웃 처리 활성화", - "description": "장시간 실행되는 작업을 자동으로 종료하고 대안을 제안합니다." + "description": "장시간 실행되는 도구 작업을 자동으로 종료하고 폴백 옵션을 제안합니다." }, "toolExecutionTimeoutMs": { "label": "도구 실행 타임아웃 (ms)", diff --git a/webview-ui/src/i18n/locales/nl/settings.json b/webview-ui/src/i18n/locales/nl/settings.json index 8a07db8bcf..ad0d4ab98d 100644 --- a/webview-ui/src/i18n/locales/nl/settings.json +++ b/webview-ui/src/i18n/locales/nl/settings.json @@ -176,7 +176,7 @@ "description": "Configureer hoe Roo omgaat met tool-operaties die hun tijdslimieten overschrijden", "timeoutFallbackEnabled": { "label": "Timeout-afhandeling inschakelen", - "description": "Automatisch langlopende operaties beëindigen en alternatieven voorstellen." + "description": "Automatisch langlopende tool-operaties beëindigen en fallback-opties voorstellen." }, "toolExecutionTimeoutMs": { "label": "Tool-uitvoering timeout (ms)", diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 6679f1d3d1..1447432994 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -176,7 +176,7 @@ "description": "Skonfiguruj sposób obsługi przez Roo operacji narzędzi, które przekraczają swoje limity czasowe", "timeoutFallbackEnabled": { "label": "Włącz obsługę timeout", - "description": "Automatycznie kończ długotrwałe operacje i sugeruj alternatywy." + "description": "Automatycznie kończ długotrwałe operacje narzędzi i sugeruj opcje fallback." }, "toolExecutionTimeoutMs": { "label": "Timeout wykonania narzędzia (ms)", diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index 3a75b2bc15..c1c4d90a61 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -176,7 +176,7 @@ "description": "Configure como o Roo lida com operações de ferramentas que excedem seus limites de tempo", "timeoutFallbackEnabled": { "label": "Ativar tratamento de timeout", - "description": "Terminar automaticamente operações de longa duração e sugerir alternativas." + "description": "Terminar automaticamente operações de ferramentas de longa duração e sugerir opções de fallback." }, "toolExecutionTimeoutMs": { "label": "Timeout de execução da ferramenta (ms)", diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index 41b7aac00b..ef067b62a7 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -176,7 +176,7 @@ "description": "Настройте, как Roo обрабатывает операции инструментов, которые превышают свои временные лимиты", "timeoutFallbackEnabled": { "label": "Включить обработку тайм-аута", - "description": "Автоматически завершать долго выполняющиеся операции и предлагать альтернативы." + "description": "Автоматически завершать долго выполняющиеся операции инструментов и предлагать резервные варианты." }, "toolExecutionTimeoutMs": { "label": "Тайм-аут выполнения инструмента (мс)", diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 6d81fa56d6..4382cb5a55 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -176,7 +176,7 @@ "description": "Roo'nun zaman sınırlarını aşan araç işlemlerini nasıl ele aldığını yapılandırın", "timeoutFallbackEnabled": { "label": "Zaman aşımı işlemeyi etkinleştir", - "description": "Uzun süren işlemleri otomatik olarak sonlandır ve alternatifler öner." + "description": "Uzun süren araç işlemlerini otomatik olarak sonlandır ve yedek seçenekler öner." }, "toolExecutionTimeoutMs": { "label": "Araç yürütme zaman aşımı (ms)", diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index c5645e2d81..a0340d6fb2 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -176,7 +176,7 @@ "description": "Cấu hình cách Roo xử lý các thao tác công cụ vượt quá giới hạn thời gian", "timeoutFallbackEnabled": { "label": "Bật xử lý thời gian chờ", - "description": "Tự động kết thúc các thao tác chạy lâu và đề xuất các lựa chọn thay thế." + "description": "Tự động kết thúc các thao tác công cụ chạy lâu và đề xuất các tùy chọn dự phòng." }, "toolExecutionTimeoutMs": { "label": "Thời gian chờ thực thi công cụ (ms)", diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index a59c00f5eb..dba09789e9 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -176,7 +176,7 @@ "description": "配置 Roo 如何处理超过时间限制的工具操作", "timeoutFallbackEnabled": { "label": "启用超时处理", - "description": "自动终止长时间运行的操作并建议替代方案。" + "description": "自动终止长时间运行的工具操作并建议备用选项。" }, "toolExecutionTimeoutMs": { "label": "工具执行超时 (ms)", diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 7639474992..f191558b19 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -176,7 +176,7 @@ "description": "設定 Roo 如何處理超過時間限制的工具操作", "timeoutFallbackEnabled": { "label": "啟用逾時處理", - "description": "自動終止長時間執行的操作並建議替代方案。" + "description": "自動終止長時間執行的工具操作並建議備用選項。" }, "toolExecutionTimeoutMs": { "label": "工具執行逾時 (ms)", From b019b4c7945c3792afd52c80d69ca2b51ca88ad4 Mon Sep 17 00:00:00 2001 From: Will Li Date: Thu, 10 Jul 2025 17:21:42 -0700 Subject: [PATCH 08/12] Update src/core/timeout/TimeoutManager.ts Co-authored-by: Daniel <57051444+daniel-lxs@users.noreply.github.com> --- src/core/timeout/TimeoutManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/timeout/TimeoutManager.ts b/src/core/timeout/TimeoutManager.ts index 72af1beb49..805b46dc3e 100644 --- a/src/core/timeout/TimeoutManager.ts +++ b/src/core/timeout/TimeoutManager.ts @@ -32,7 +32,7 @@ export class TimeoutManager extends EventEmitter { private static instance: TimeoutManager | undefined private activeOperations = new Map() /** - * Assumes there is only on active tool-- does not timeout edge cases + * Assumes there is only one active tool-- does not timeout edge cases * like "Proceed While Running" */ private lastTimeoutEvent: TimeoutEvent | null = null From 3c7a54b3cd4a68709e9e3a035184046708d20115 Mon Sep 17 00:00:00 2001 From: Will Li Date: Wed, 16 Jul 2025 11:23:35 -0700 Subject: [PATCH 09/12] code review --- packages/telemetry/src/TelemetryService.ts | 17 ++ packages/types/src/telemetry.ts | 2 + .../timeout-fallback-responses.spec.ts | 51 +++- src/core/prompts/responses.ts | 29 +- src/core/timeout/TimeoutFallbackHandler.ts | 48 +++- src/core/timeout/TimeoutManager.ts | 48 +++- .../__tests__/timeout-fallback.spec.ts | 48 +++- .../__tests__/timeout-telemetry.spec.ts | 256 ++++++++++++++++++ webview-ui/src/components/chat/ChatRow.tsx | 30 +- webview-ui/src/i18n/locales/ca/chat.json | 6 +- webview-ui/src/i18n/locales/de/chat.json | 6 +- webview-ui/src/i18n/locales/en/chat.json | 6 +- webview-ui/src/i18n/locales/es/chat.json | 6 +- webview-ui/src/i18n/locales/fr/chat.json | 6 +- webview-ui/src/i18n/locales/hi/chat.json | 6 +- webview-ui/src/i18n/locales/id/chat.json | 6 +- webview-ui/src/i18n/locales/it/chat.json | 6 +- webview-ui/src/i18n/locales/ja/chat.json | 6 +- webview-ui/src/i18n/locales/ko/chat.json | 6 +- webview-ui/src/i18n/locales/nl/chat.json | 6 +- webview-ui/src/i18n/locales/pl/chat.json | 6 +- webview-ui/src/i18n/locales/pt-BR/chat.json | 6 +- webview-ui/src/i18n/locales/ru/chat.json | 6 +- webview-ui/src/i18n/locales/tr/chat.json | 6 +- webview-ui/src/i18n/locales/vi/chat.json | 8 +- webview-ui/src/i18n/locales/zh-CN/chat.json | 8 +- webview-ui/src/i18n/locales/zh-TW/chat.json | 8 +- 27 files changed, 597 insertions(+), 46 deletions(-) create mode 100644 src/core/timeout/__tests__/timeout-telemetry.spec.ts diff --git a/packages/telemetry/src/TelemetryService.ts b/packages/telemetry/src/TelemetryService.ts index 7a11e3d388..7d59f2a417 100644 --- a/packages/telemetry/src/TelemetryService.ts +++ b/packages/telemetry/src/TelemetryService.ts @@ -152,6 +152,23 @@ export class TelemetryService { this.captureEvent(TelemetryEventName.CONSECUTIVE_MISTAKE_ERROR, { taskId }) } + /** + * Captures when a tool execution times out + * @param taskId The task ID where the timeout occurred + * @param toolName The name of the tool that timed out + * @param timeoutMs The timeout duration in milliseconds + * @param executionTimeMs The actual execution time before timeout + */ + public captureToolTimeout(taskId: string, toolName: string, timeoutMs: number, executionTimeMs: number): void { + this.captureEvent(TelemetryEventName.TOOL_TIMEOUT, { + taskId, + toolName, + timeoutMs, + executionTimeMs, + timeoutRatio: executionTimeMs / timeoutMs, + }) + } + /** * Captures when a tab is shown due to user action * @param tab The tab that was shown diff --git a/packages/types/src/telemetry.ts b/packages/types/src/telemetry.ts index 6ad2eb3a7a..b714d16509 100644 --- a/packages/types/src/telemetry.ts +++ b/packages/types/src/telemetry.ts @@ -65,6 +65,7 @@ export enum TelemetryEventName { DIFF_APPLICATION_ERROR = "Diff Application Error", SHELL_INTEGRATION_ERROR = "Shell Integration Error", CONSECUTIVE_MISTAKE_ERROR = "Consecutive Mistake Error", + TOOL_TIMEOUT = "Tool Timeout", } /** @@ -157,6 +158,7 @@ export const rooCodeTelemetryEventSchema = z.discriminatedUnion("type", [ TelemetryEventName.TAB_SHOWN, TelemetryEventName.MODE_SETTINGS_CHANGED, TelemetryEventName.CUSTOM_MODE_CREATED, + TelemetryEventName.TOOL_TIMEOUT, ]), properties: telemetryPropertiesSchema, }), diff --git a/src/core/prompts/__tests__/timeout-fallback-responses.spec.ts b/src/core/prompts/__tests__/timeout-fallback-responses.spec.ts index 30b53f1581..3899df3923 100644 --- a/src/core/prompts/__tests__/timeout-fallback-responses.spec.ts +++ b/src/core/prompts/__tests__/timeout-fallback-responses.spec.ts @@ -2,6 +2,47 @@ import { describe, it, expect } from "vitest" import { formatResponse } from "../responses" describe("timeout fallback responses", () => { + describe("toolTimeout", () => { + it("should include background operation warning for execute_command", () => { + const message = formatResponse.toolTimeout("execute_command", 30000, 35000) + + expect(message).toContain("timed out after 30 seconds") + expect(message).toContain( + "**Important**: The execute_command operation may still be running in the background", + ) + expect(message).toContain("You might see output or effects from this operation later") + }) + + it("should include background operation warning for browser_action", () => { + const message = formatResponse.toolTimeout("browser_action", 15000, 20000) + + expect(message).toContain("timed out after 15 seconds") + expect(message).toContain( + "**Important**: The browser_action operation may still be running in the background", + ) + expect(message).toContain("You might see output or effects from this operation later") + }) + + it("should not include background operation warning for other tools", () => { + const message = formatResponse.toolTimeout("read_file", 10000, 12000) + + expect(message).toContain("timed out after 10 seconds") + expect(message).not.toContain("may still be running in the background") + expect(message).not.toContain("**Important**") + }) + + it("should format timeout details correctly", () => { + const message = formatResponse.toolTimeout("write_to_file", 5000, 6000) + + expect(message).toContain("") + expect(message).toContain("Tool: write_to_file") + expect(message).toContain("Configured Timeout: 5s") + expect(message).toContain("Execution Time: 6s") + expect(message).toContain("Status: Canceled") + expect(message).toContain("") + }) + }) + describe("generateContextualSuggestions", () => { it("should generate execute_command suggestions", () => { const suggestions = formatResponse.timeoutFallbackSuggestions.generateContextualSuggestions( @@ -11,7 +52,8 @@ describe("timeout fallback responses", () => { expect(suggestions).toHaveLength(4) expect(suggestions[0].text).toContain("npm install") - expect(suggestions[0].text).toContain("smaller, sequential steps") + expect(suggestions[0].text).toContain("still running in the background") + expect(suggestions[1].text).toContain("smaller, sequential steps") }) it("should generate read_file suggestions", () => { @@ -42,8 +84,9 @@ describe("timeout fallback responses", () => { ) expect(suggestions).toHaveLength(4) - expect(suggestions[0].text).toContain("click") - expect(suggestions[0].text).toContain("smaller, more targeted steps") + expect(suggestions[0].text).toContain("browser action") + expect(suggestions[0].text).toContain("still processing in the background") + expect(suggestions[1].text).toContain("smaller, more targeted steps") }) it("should generate search_files suggestions", () => { @@ -73,6 +116,7 @@ describe("timeout fallback responses", () => { expect(suggestions).toHaveLength(4) expect(suggestions[0].text).toContain("the command") + expect(suggestions[0].text).toContain("still running in the background") }) it("should generate read file suggestions with default file name", () => { @@ -94,6 +138,7 @@ describe("timeout fallback responses", () => { expect(suggestions).toHaveLength(4) expect(suggestions[0].text).toContain("browser action") + expect(suggestions[0].text).toContain("still processing in the background") }) it("should generate search suggestions", () => { diff --git a/src/core/prompts/responses.ts b/src/core/prompts/responses.ts index f3c629101b..37282e13c1 100644 --- a/src/core/prompts/responses.ts +++ b/src/core/prompts/responses.ts @@ -16,17 +16,26 @@ export const formatResponse = { toolError: (error?: string) => `The tool execution failed with the following error:\n\n${error}\n`, - toolTimeout: (toolName: string, timeoutMs: number, executionTimeMs: number) => - `The ${toolName} operation timed out after ${Math.round(timeoutMs / 1000)} seconds and was automatically canceled. + toolTimeout: (toolName: string, timeoutMs: number, executionTimeMs: number) => { + // Determine if this tool might continue running in the background + const backgroundOperationTools = ["execute_command", "browser_action"] + const mightContinueInBackground = backgroundOperationTools.includes(toolName) + + const backgroundWarning = mightContinueInBackground + ? `\n\n**Important**: The ${toolName} operation may still be running in the background. You might see output or effects from this operation later.` + : "" + + return `The ${toolName} operation timed out after ${Math.round(timeoutMs / 1000)} seconds and was automatically canceled. Tool: ${toolName} Configured Timeout: ${Math.round(timeoutMs / 1000)}s Execution Time: ${Math.round(executionTimeMs / 1000)}s Status: Canceled - +${backgroundWarning} -The operation has been terminated to prevent system resource issues. Please consider one of the following approaches to complete your task.`, +The operation has been terminated to prevent system resource issues. Please consider one of the following approaches to complete your task.` + }, rooIgnoreError: (path: string) => `Access to ${path} is blocked by the .rooignore file settings. You must try to continue in the task without using this file, or ask the user to update the .rooignore file.`, @@ -215,6 +224,9 @@ Otherwise, if you have not completed the task and do not need additional informa const command = params?.command || "the command" return [ + { + text: `Check if "${command}" is still running in the background and wait for it to complete`, + }, { text: `Break "${command}" into smaller, sequential steps that can complete faster`, }, @@ -224,9 +236,6 @@ Otherwise, if you have not completed the task and do not need additional informa { text: `Try an alternative approach or tool to accomplish the same goal`, }, - { - text: `Increase the timeout setting if this operation legitimately needs more time`, - }, ] }, @@ -273,13 +282,13 @@ Otherwise, if you have not completed the task and do not need additional informa return [ { - text: `Simplify the "${action}" into smaller, more targeted steps`, + text: `Check if the browser action is still processing in the background`, }, { - text: `Wait for specific elements to load before proceeding`, + text: `Simplify the "${action}" into smaller, more targeted steps`, }, { - text: `Use direct API calls instead of browser automation if possible`, + text: `Wait for specific elements to load before proceeding`, }, { text: `Reset the browser session and try again`, diff --git a/src/core/timeout/TimeoutFallbackHandler.ts b/src/core/timeout/TimeoutFallbackHandler.ts index 5aaa2c62f1..6c9e09dc97 100644 --- a/src/core/timeout/TimeoutFallbackHandler.ts +++ b/src/core/timeout/TimeoutFallbackHandler.ts @@ -25,6 +25,18 @@ export interface TimeoutFallbackResult { * and creates timeout responses in a single optimized flow */ export class TimeoutFallbackHandler { + private static readonly BACKGROUND_OPERATION_TOOLS = ["execute_command", "browser_action"] + + /** + * Helper method to generate the timeout question message + */ + private static generateTimeoutQuestion(toolName: ToolName, timeoutMs: number): string { + const mightContinueInBackground = this.BACKGROUND_OPERATION_TOOLS.includes(toolName) + const baseMessage = `The ${toolName} operation timed out after ${Math.round(timeoutMs / 1000)} seconds` + const backgroundSuffix = mightContinueInBackground ? " but may still be running in the background" : "" + return `${baseMessage}${backgroundSuffix}. How would you like to proceed?` + } + /** * Create a timeout response with AI-generated fallback question in a single optimized query */ @@ -39,7 +51,11 @@ export class TimeoutFallbackHandler { // Create a timeout message for display in the chat if (task) { - await task.say("tool_timeout", "", undefined, false, undefined, undefined, { + const mightContinueInBackground = this.BACKGROUND_OPERATION_TOOLS.includes(toolName) + + // Pass a JSON string with the tool info so the UI can determine if it should show a background warning + const timeoutInfo = JSON.stringify({ toolName, mightContinueInBackground }) + await task.say("tool_timeout", timeoutInfo, undefined, false, undefined, undefined, { isNonInteractive: true, }) } @@ -93,10 +109,17 @@ This is required to help the user decide how to proceed after the timeout.` // Try to use AI to generate contextual suggestions if (task?.api && "completePrompt" in task.api) { try { - const aiResult = await this.generateAiSuggestions(context, task.api as SingleCompletionHandler) + // Pass the timeout from context to use exact tool timeout + const aiResult = await this.generateAiSuggestions( + context, + task.api as SingleCompletionHandler, + context.timeoutMs, + ) if (aiResult.success) { + console.log(`[TimeoutFallbackHandler] AI suggestions generated successfully`) return aiResult } + console.error(`[TimeoutFallbackHandler] AI suggestions failed:`, aiResult.error) } catch (error) { // AI failed, fall through to static suggestions } @@ -117,10 +140,20 @@ This is required to help the user decide how to proceed after the timeout.` private static async generateAiSuggestions( context: TimeoutFallbackContext, apiHandler: SingleCompletionHandler, + timeoutMs: number, ): Promise { try { const prompt = createTimeoutFallbackPrompt(context) - const aiResponse = await apiHandler.completePrompt(prompt) + + // Create a timeout promise using exactly the same timeout as the tool + const timeoutPromise = new Promise((_, reject) => { + setTimeout(() => { + reject(new Error(`AI fallback generation timed out after ${timeoutMs / 1000} seconds`)) + }, timeoutMs) + }) + + // Race between AI completion and timeout + const aiResponse = await Promise.race([apiHandler.completePrompt(prompt), timeoutPromise]) // Parse the AI response to extract suggestions const suggestions = parseTimeoutFallbackResponse(aiResponse) @@ -129,7 +162,7 @@ This is required to help the user decide how to proceed after the timeout.` throw new Error("No valid suggestions generated by AI") } - const question = `The ${context.toolName} operation timed out after ${Math.round(context.timeoutMs / 1000)} seconds. How would you like to proceed?` + const question = this.generateTimeoutQuestion(context.toolName, context.timeoutMs) const followUpXml = suggestions .map((suggestion) => @@ -150,9 +183,12 @@ This is required to help the user decide how to proceed after the timeout.` }, } } catch (error) { + // If it's a timeout error, include that in the error message + const errorMessage = error instanceof Error ? error.message : "Unknown error generating AI suggestions" + return { success: false, - error: error instanceof Error ? error.message : "Unknown error generating AI suggestions", + error: errorMessage, } } } @@ -166,7 +202,7 @@ This is required to help the user decide how to proceed after the timeout.` context.toolParams, ) - const question = `The ${context.toolName} operation timed out after ${Math.round(context.timeoutMs / 1000)} seconds. How would you like to proceed?` + const question = this.generateTimeoutQuestion(context.toolName, context.timeoutMs) const followUpXml = suggestions .map((suggestion) => diff --git a/src/core/timeout/TimeoutManager.ts b/src/core/timeout/TimeoutManager.ts index 805b46dc3e..fe1ae3c458 100644 --- a/src/core/timeout/TimeoutManager.ts +++ b/src/core/timeout/TimeoutManager.ts @@ -1,5 +1,6 @@ import { EventEmitter } from "events" import type { ToolName } from "@roo-code/types" +import { TelemetryService } from "@roo-code/telemetry" export interface TimeoutConfig { toolName: ToolName @@ -36,14 +37,16 @@ export class TimeoutManager extends EventEmitter { * like "Proceed While Running" */ private lastTimeoutEvent: TimeoutEvent | null = null + private logger: (...args: any[]) => void - private constructor() { + private constructor(logger?: (...args: any[]) => void) { super() + this.logger = logger || console.log } - public static getInstance(): TimeoutManager { + public static getInstance(logger?: (...args: any[]) => void): TimeoutManager { if (!TimeoutManager.instance) { - TimeoutManager.instance = new TimeoutManager() + TimeoutManager.instance = new TimeoutManager(logger) } return TimeoutManager.instance } @@ -59,6 +62,8 @@ export class TimeoutManager extends EventEmitter { const controller = new AbortController() const startTime = Date.now() + this.logger(`[TimeoutManager] Starting operation ${operationId} with timeout ${config.timeoutMs}ms`) + // Store the controller for potential cancellation this.activeOperations.set(operationId, controller) @@ -81,6 +86,8 @@ export class TimeoutManager extends EventEmitter { const executionTimeMs = Date.now() - startTime + this.logger(`[TimeoutManager] Operation ${operationId} completed successfully in ${executionTimeMs}ms`) + return { success: true, result, @@ -105,6 +112,21 @@ export class TimeoutManager extends EventEmitter { this.lastTimeoutEvent = timeoutEvent this.emit("timeout", timeoutEvent) + // Log timeout event + this.logger( + `[TimeoutManager] Operation ${operationId} timed out after ${executionTimeMs}ms (limit: ${config.timeoutMs}ms)`, + ) + + // Capture telemetry if TelemetryService is available + if (TelemetryService.hasInstance() && config.taskId) { + TelemetryService.instance.captureToolTimeout( + config.taskId, + config.toolName, + config.timeoutMs, + executionTimeMs, + ) + } + return { success: false, timedOut: true, @@ -114,6 +136,11 @@ export class TimeoutManager extends EventEmitter { } } + // Log non-timeout errors + this.logger( + `[TimeoutManager] Operation ${operationId} failed after ${executionTimeMs}ms: ${error instanceof Error ? error.message : String(error)}`, + ) + return { success: false, timedOut: false, @@ -186,6 +213,21 @@ export class TimeoutManager extends EventEmitter { return `${toolName}:${taskId || "default"}` } + /** + * Get timeout statistics for monitoring + */ + public getTimeoutStats(): { + lastTimeout: TimeoutEvent | null + activeOperations: number + operationIds: string[] + } { + return { + lastTimeout: this.lastTimeoutEvent, + activeOperations: this.activeOperations.size, + operationIds: Array.from(this.activeOperations.keys()), + } + } + /** * Cleanup method for graceful shutdown */ diff --git a/src/core/timeout/__tests__/timeout-fallback.spec.ts b/src/core/timeout/__tests__/timeout-fallback.spec.ts index d835bbf6ac..ee98890f2a 100644 --- a/src/core/timeout/__tests__/timeout-fallback.spec.ts +++ b/src/core/timeout/__tests__/timeout-fallback.spec.ts @@ -59,6 +59,7 @@ describe("TimeoutFallbackHandler", () => { expect(result.toolCall?.name).toBe("ask_followup_question") expect(result.toolCall?.params.question).toContain("execute_command") expect(result.toolCall?.params.question).toContain("30 seconds") + expect(result.toolCall?.params.question).toContain("may still be running in the background") // Check that AI-generated suggestions are included const followUp = result.toolCall?.params.follow_up || "" @@ -93,12 +94,55 @@ describe("TimeoutFallbackHandler", () => { // Should contain static fallback suggestions const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain("still running in the background") expect(followUp).toContain('Break "npm test" into smaller') expect(followUp).toContain("background using") expect(followUp).toContain("alternative approach") - expect(followUp).toContain("Increase the timeout") }) + test("should timeout AI fallback generation using exact tool timeout", async () => { + // Mock AI handler that takes longer than the timeout + ;(mockApiHandler.completePrompt as any).mockImplementation(() => { + return new Promise((resolve) => { + // This would resolve after 5 seconds, but should timeout before that + setTimeout(() => { + resolve("This response should never be used") + }, 5000) + }) + }) + + const context = { + toolName: "execute_command" as const, + timeoutMs: 2000, // 2 second timeout for faster testing + executionTimeMs: 2500, + toolParams: { command: "npm install" }, + } + + const startTime = Date.now() + // The timeout is now taken from context.timeoutMs + const result = await TimeoutFallbackHandler.generateAiFallback(context, mockTask as Task) + const elapsedTime = Date.now() - startTime + + // Should timeout and fallback to static suggestions + expect(result.success).toBe(true) + expect(result.toolCall).toBeDefined() + expect(result.toolCall?.name).toBe("ask_followup_question") + + // Should have timed out around 2 seconds (exact tool timeout) + expect(elapsedTime).toBeGreaterThanOrEqual(1900) + expect(elapsedTime).toBeLessThan(2500) + + // Should contain static fallback suggestions since AI timed out + const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain("still running in the background") + expect(followUp).toContain('Break "npm install" into smaller') + expect(followUp).toContain("background using") + expect(followUp).toContain("alternative approach") + + // Verify AI was called + expect(mockApiHandler.completePrompt).toHaveBeenCalled() + }, 5000) // Test timeout of 5 seconds + test("should fallback to static suggestions when API handler is unavailable", async () => { // Task without API handler const taskWithoutApi = {} @@ -400,9 +444,9 @@ Based on the search_files timeout, here are my recommendations: // Should contain static fallback suggestions for browser_action const followUp = result.toolCall?.params.follow_up || "" + expect(followUp).toContain("still processing in the background") expect(followUp).toContain('Simplify the "click"') expect(followUp).toContain("Wait for specific elements") - expect(followUp).toContain("direct API calls") expect(followUp).toContain("Reset the browser session") }) }) diff --git a/src/core/timeout/__tests__/timeout-telemetry.spec.ts b/src/core/timeout/__tests__/timeout-telemetry.spec.ts new file mode 100644 index 0000000000..a8fd4effc9 --- /dev/null +++ b/src/core/timeout/__tests__/timeout-telemetry.spec.ts @@ -0,0 +1,256 @@ +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest" +import { TimeoutManager } from "../TimeoutManager" +import { TelemetryService } from "@roo-code/telemetry" + +// Mock TelemetryService +vi.mock("@roo-code/telemetry", () => ({ + TelemetryService: { + hasInstance: vi.fn(), + instance: { + captureToolTimeout: vi.fn(), + }, + }, +})) + +describe("TimeoutManager Telemetry and Logging", () => { + let timeoutManager: TimeoutManager + let mockLogger: ReturnType + let originalInstance: TimeoutManager | undefined + + beforeEach(() => { + // Store the original instance + originalInstance = (TimeoutManager as any).instance + // Reset the singleton instance + ;(TimeoutManager as any).instance = undefined + + // Create mock logger + mockLogger = vi.fn() + + // Create new instance with mock logger + timeoutManager = TimeoutManager.getInstance(mockLogger) + + // Setup TelemetryService mock + vi.mocked(TelemetryService.hasInstance).mockReturnValue(true) + vi.mocked(TelemetryService.instance.captureToolTimeout).mockClear() + }) + + afterEach(() => { + // Restore the original instance + ;(TimeoutManager as any).instance = originalInstance + vi.clearAllMocks() + }) + + describe("Logging", () => { + it("should log operation start", async () => { + const operation = vi.fn().mockResolvedValue("result") + + await timeoutManager.executeWithTimeout(operation, { + toolName: "execute_command", + timeoutMs: 1000, + enableFallback: false, + taskId: "task-123", + }) + + expect(mockLogger).toHaveBeenCalledWith( + expect.stringContaining( + "[TimeoutManager] Starting operation execute_command:task-123 with timeout 1000ms", + ), + ) + }) + + it("should log successful operation completion", async () => { + const operation = vi.fn().mockResolvedValue("result") + + await timeoutManager.executeWithTimeout(operation, { + toolName: "execute_command", + timeoutMs: 1000, + enableFallback: false, + taskId: "task-123", + }) + + expect(mockLogger).toHaveBeenCalledWith( + expect.stringMatching( + /\[TimeoutManager\] Operation execute_command:task-123 completed successfully in \d+ms/, + ), + ) + }) + + it("should log timeout events", async () => { + const operation = vi.fn().mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 2000))) + + await timeoutManager.executeWithTimeout(operation, { + toolName: "execute_command", + timeoutMs: 100, + enableFallback: false, + taskId: "task-123", + }) + + expect(mockLogger).toHaveBeenCalledWith( + expect.stringMatching( + /\[TimeoutManager\] Operation execute_command:task-123 timed out after \d+ms \(limit: 100ms\)/, + ), + ) + }) + + it("should log non-timeout errors", async () => { + const error = new Error("Test error") + const operation = vi.fn().mockRejectedValue(error) + + await timeoutManager.executeWithTimeout(operation, { + toolName: "execute_command", + timeoutMs: 1000, + enableFallback: false, + taskId: "task-123", + }) + + expect(mockLogger).toHaveBeenCalledWith( + expect.stringMatching( + /\[TimeoutManager\] Operation execute_command:task-123 failed after \d+ms: Test error/, + ), + ) + }) + }) + + describe("Telemetry", () => { + it("should capture telemetry for timeout events when TelemetryService is available", async () => { + const operation = vi.fn().mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 2000))) + + const result = await timeoutManager.executeWithTimeout(operation, { + toolName: "execute_command", + timeoutMs: 100, + enableFallback: false, + taskId: "task-123", + }) + + expect(result.timedOut).toBe(true) + expect(TelemetryService.instance.captureToolTimeout).toHaveBeenCalledWith( + "task-123", + "execute_command", + 100, + expect.any(Number), + ) + }) + + it("should not capture telemetry when taskId is not provided", async () => { + const operation = vi.fn().mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 2000))) + + await timeoutManager.executeWithTimeout(operation, { + toolName: "execute_command", + timeoutMs: 100, + enableFallback: false, + }) + + expect(TelemetryService.instance.captureToolTimeout).not.toHaveBeenCalled() + }) + + it("should not capture telemetry when TelemetryService is not available", async () => { + vi.mocked(TelemetryService.hasInstance).mockReturnValue(false) + + const operation = vi.fn().mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 2000))) + + await timeoutManager.executeWithTimeout(operation, { + toolName: "execute_command", + timeoutMs: 100, + enableFallback: false, + taskId: "task-123", + }) + + expect(TelemetryService.instance.captureToolTimeout).not.toHaveBeenCalled() + }) + + it("should not capture telemetry for successful operations", async () => { + const operation = vi.fn().mockResolvedValue("result") + + await timeoutManager.executeWithTimeout(operation, { + toolName: "execute_command", + timeoutMs: 1000, + enableFallback: false, + taskId: "task-123", + }) + + expect(TelemetryService.instance.captureToolTimeout).not.toHaveBeenCalled() + }) + + it("should not capture telemetry for non-timeout errors", async () => { + const operation = vi.fn().mockRejectedValue(new Error("Test error")) + + await timeoutManager.executeWithTimeout(operation, { + toolName: "execute_command", + timeoutMs: 1000, + enableFallback: false, + taskId: "task-123", + }) + + expect(TelemetryService.instance.captureToolTimeout).not.toHaveBeenCalled() + }) + }) + + describe("getTimeoutStats", () => { + it("should return timeout statistics", async () => { + // Execute an operation that will timeout + const operation = vi.fn().mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 2000))) + + await timeoutManager.executeWithTimeout(operation, { + toolName: "execute_command", + timeoutMs: 100, + enableFallback: false, + taskId: "task-123", + }) + + const stats = timeoutManager.getTimeoutStats() + + expect(stats.lastTimeout).toBeTruthy() + expect(stats.lastTimeout?.toolName).toBe("execute_command") + expect(stats.lastTimeout?.taskId).toBe("task-123") + expect(stats.lastTimeout?.timeoutMs).toBe(100) + expect(stats.activeOperations).toBe(0) // Should be 0 after operation completes + }) + + it("should track active operations", async () => { + // Start a long-running operation + const operation = vi.fn().mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 5000))) + + const promise = timeoutManager.executeWithTimeout(operation, { + toolName: "execute_command", + timeoutMs: 10000, + enableFallback: false, + taskId: "task-123", + }) + + // Check stats while operation is running + const stats = timeoutManager.getTimeoutStats() + expect(stats.activeOperations).toBe(1) + expect(stats.operationIds).toContain("execute_command:task-123") + + // Cancel to clean up + timeoutManager.cancelOperation("execute_command", "task-123") + await promise.catch(() => {}) // Ignore cancellation error + }) + }) + + describe("Timeout event emission", () => { + it("should emit timeout event with correct data", async () => { + const timeoutHandler = vi.fn() + timeoutManager.on("timeout", timeoutHandler) + + const operation = vi.fn().mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 2000))) + + await timeoutManager.executeWithTimeout(operation, { + toolName: "execute_command", + timeoutMs: 100, + enableFallback: true, + taskId: "task-123", + }) + + expect(timeoutHandler).toHaveBeenCalledWith({ + toolName: "execute_command", + timeoutMs: 100, + executionTimeMs: expect.any(Number), + taskId: "task-123", + timestamp: expect.any(Number), + }) + + timeoutManager.off("timeout", timeoutHandler) + }) + }) +}) diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx index ae19d3bb2a..397cc0c8da 100644 --- a/webview-ui/src/components/chat/ChatRow.tsx +++ b/webview-ui/src/components/chat/ChatRow.tsx @@ -259,9 +259,27 @@ export const ChatRowContent = ({ {t("chat:questions.hasQuestion")}, ] case "tool_timeout": + let showBackgroundWarning = false + try { + const timeoutInfo = message.text ? JSON.parse(message.text) : null + showBackgroundWarning = timeoutInfo?.mightContinueInBackground || false + } catch (_e) { + // If parsing fails, don't show the warning + } return [ , - {t("chat:toolTimeout")}, + + {t("chat:toolTimeout.title")}{" "} + {t("chat:toolTimeout.subtitle")} + {showBackgroundWarning && ( + <> +
+ + {t("chat:toolTimeout.backgroundWarning")} + + + )} +
, ] default: return [null, null] @@ -1115,6 +1133,16 @@ export const ChatRowContent = ({ case "user_edit_todos": return {}} /> default: + // Don't render message text for tool_timeout as it contains JSON metadata + if (message.say === "tool_timeout") { + return title ? ( +
+ {icon} + {title} +
+ ) : null + } + return ( <> {title && ( diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index ac8c69a153..8c429bbb20 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -215,7 +215,6 @@ "hasQuestion": "Roo té una pregunta:" }, "taskCompleted": "Tasca completada", - "toolTimeout": "Temps d'espera de l'eina esgotat: Suggerint alternatives...", "powershell": { "issues": "Sembla que estàs tenint problemes amb Windows PowerShell, si us plau consulta aquesta documentació per a més informació." }, @@ -239,6 +238,11 @@ "autoSelectCountdown": "Selecció automàtica en {{count}}s", "countdownDisplay": "{{count}}s" }, + "toolTimeout": { + "title": "Temps d'espera d'eina configurat per l'usuari:", + "subtitle": "Suggerint alternatives...", + "backgroundWarning": "Nota: l'operació pot seguir executant-se en segon pla" + }, "announcement": { "title": "🎉 Roo Code {{version}} Llançat", "description": "Roo Code {{version}} porta noves funcions potents i millores significatives per millorar el vostre flux de treball de desenvolupament.", diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index c98ca8a3b6..8b3ae34dc1 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -215,7 +215,6 @@ "hasQuestion": "Roo hat eine Frage:" }, "taskCompleted": "Aufgabe abgeschlossen", - "toolTimeout": "Automatische Tool-Zeitüberschreitung: Schlage Alternativen vor...", "powershell": { "issues": "Es scheint, dass du Probleme mit Windows PowerShell hast, bitte sieh dir dies an" }, @@ -239,6 +238,11 @@ "autoSelectCountdown": "Automatische Auswahl in {{count}}s", "countdownDisplay": "{{count}}s" }, + "toolTimeout": { + "title": "Benutzerdefiniertes Tool-Timeout:", + "subtitle": "Alternativen werden vorgeschlagen...", + "backgroundWarning": "Hinweis: Der Vorgang läuft möglicherweise noch im Hintergrund" + }, "announcement": { "title": "🎉 Roo Code {{version}} veröffentlicht", "description": "Roo Code {{version}} bringt mächtige neue Funktionen und bedeutende Verbesserungen, um deinen Entwicklungsworkflow zu verbessern.", diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index 99b267bc6c..0add37cab5 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -230,7 +230,11 @@ "hasQuestion": "Roo has a question:" }, "taskCompleted": "Task Completed", - "toolTimeout": "Automatic Tool Timeout: Suggesting alternatives...", + "toolTimeout": { + "title": "User Configured Tool Timeout:", + "subtitle": "Suggesting alternatives...", + "backgroundWarning": "Note operation may still be running in the background" + }, "error": "Error", "diffError": { "title": "Edit Unsuccessful" diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index 53cd277f3a..6b8a3a34eb 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -1,5 +1,4 @@ { - "toolTimeout": "Tiempo de espera de herramienta agotado: Sugiriendo alternativas...", "greeting": "Bienvenido a Roo Code", "task": { "title": "Tarea", @@ -239,6 +238,11 @@ "autoSelectCountdown": "Selección automática en {{count}}s", "countdownDisplay": "{{count}}s" }, + "toolTimeout": { + "title": "Tiempo de espera de herramienta configurado por el usuario:", + "subtitle": "Sugiriendo alternativas...", + "backgroundWarning": "Nota: la operación puede seguir ejecutándose en segundo plano" + }, "announcement": { "title": "🎉 Roo Code {{version}} publicado", "description": "Roo Code {{version}} trae poderosas nuevas funcionalidades y mejoras significativas para mejorar tu flujo de trabajo de desarrollo.", diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index e57501c176..032a6cc54b 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -1,5 +1,4 @@ { - "toolTimeout": "Délai d'attente de l'outil dépassé : Suggestion d'alternatives...", "greeting": "Bienvenue sur Roo Code", "task": { "title": "Tâche", @@ -239,6 +238,11 @@ "autoSelectCountdown": "Sélection automatique dans {{count}}s", "countdownDisplay": "{{count}}s" }, + "toolTimeout": { + "title": "Délai d'expiration d'outil configuré par l'utilisateur :", + "subtitle": "Suggestion d'alternatives...", + "backgroundWarning": "Note : l'opération peut encore s'exécuter en arrière-plan" + }, "announcement": { "title": "🎉 Roo Code {{version}} est sortie", "description": "Roo Code {{version}} apporte de puissantes nouvelles fonctionnalités et des améliorations significatives pour améliorer ton flux de travail de développement.", diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index dc7d82c1f2..95c7621605 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -1,5 +1,4 @@ { - "toolTimeout": "टूल टाइमआउट: विकल्प सुझा रहा हूं...", "greeting": "Roo Code में आपका स्वागत है", "task": { "title": "कार्य", @@ -239,6 +238,11 @@ "autoSelectCountdown": "{{count}}s में स्वचालित रूप से चयन हो रहा है", "countdownDisplay": "{{count}}सेकंड" }, + "toolTimeout": { + "title": "उपयोगकर्ता द्वारा कॉन्फ़िगर किया गया टूल टाइमआउट:", + "subtitle": "विकल्प सुझा रहा है...", + "backgroundWarning": "नोट: ऑपरेशन अभी भी बैकग्राउंड में चल रहा हो सकता है" + }, "announcement": { "title": "🎉 Roo Code {{version}} रिलीज़ हुआ", "description": "Roo Code {{version}} आपके विकास वर्कफ़्लो को बेहतर बनाने के लिए शक्तिशाली नई सुविधाएं और महत्वपूर्ण सुधार लेकर आया है।", diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index a86456313a..7bf8671a79 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -1,5 +1,4 @@ { - "toolTimeout": "Timeout Tool Otomatis: Menyarankan alternatif...", "greeting": "Selamat datang di Roo Code", "task": { "title": "Tugas", @@ -236,6 +235,11 @@ "questions": { "hasQuestion": "Roo punya pertanyaan:" }, + "toolTimeout": { + "title": "Timeout Tool yang Dikonfigurasi Pengguna:", + "subtitle": "Menyarankan alternatif...", + "backgroundWarning": "Catatan: operasi mungkin masih berjalan di latar belakang" + }, "taskCompleted": "Tugas Selesai", "error": "Error", "diffError": { diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index c3ccfe1f0f..c30123c0eb 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -1,5 +1,4 @@ { - "toolTimeout": "Timeout automatico dello strumento: Suggerendo alternative...", "greeting": "Benvenuto a Roo Code", "task": { "title": "Attività", @@ -239,6 +238,11 @@ "autoSelectCountdown": "Selezione automatica in {{count}}s", "countdownDisplay": "{{count}}s" }, + "toolTimeout": { + "title": "Timeout Strumento Configurato dall'Utente:", + "subtitle": "Suggerendo alternative...", + "backgroundWarning": "Nota: l'operazione potrebbe essere ancora in esecuzione in background" + }, "announcement": { "title": "🎉 Rilasciato Roo Code {{version}}", "description": "Roo Code {{version}} porta nuove potenti funzionalità e miglioramenti significativi per potenziare il tuo flusso di lavoro di sviluppo.", diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index 443c63eb1a..1787fcec72 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -1,5 +1,4 @@ { - "toolTimeout": "自動ツールタイムアウト:代替案を提案しています...", "greeting": "Roo Code へようこそ", "task": { "title": "タスク", @@ -239,6 +238,11 @@ "autoSelectCountdown": "{{count}}秒後に自動選択します", "countdownDisplay": "{{count}}秒" }, + "toolTimeout": { + "title": "ユーザー設定ツールタイムアウト:", + "subtitle": "代替案を提案中...", + "backgroundWarning": "注意: 操作がバックグラウンドで実行中の可能性があります" + }, "announcement": { "title": "🎉 Roo Code {{version}} リリース", "description": "Roo Code {{version}}は、開発ワークフローを向上させる強力な新機能と重要な改善をもたらします。", diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index 5ca6075ec3..1234935b29 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -1,5 +1,4 @@ { - "toolTimeout": "자동 도구 타임아웃: 대안을 제안하고 있습니다...", "greeting": "Roo Code에 오신 것을 환영합니다", "task": { "title": "작업", @@ -239,6 +238,11 @@ "autoSelectCountdown": "{{count}}초 후 자동 선택", "countdownDisplay": "{{count}}초" }, + "toolTimeout": { + "title": "사용자 구성 도구 타임아웃:", + "subtitle": "대안을 제안하는 중...", + "backgroundWarning": "참고: 작업이 백그라운드에서 계속 실행 중일 수 있습니다" + }, "announcement": { "title": "🎉 Roo Code {{version}} 출시", "description": "Roo Code {{version}}은 개발 워크플로우를 향상시키는 강력한 새 기능과 중요한 개선사항을 제공합니다.", diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index 71ebaf2c28..146e27576f 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -1,5 +1,4 @@ { - "toolTimeout": "Automatische tool timeout: Alternatieven voorstellen...", "greeting": "Welkom bij Roo Code", "task": { "title": "Taak", @@ -244,6 +243,11 @@ "errorHeader": "Context samenvatten mislukt", "tokens": "tokens" }, + "toolTimeout": { + "title": "Door gebruiker geconfigureerde tool timeout:", + "subtitle": "Alternatieven voorstellen...", + "backgroundWarning": "Let op: de bewerking kan nog steeds op de achtergrond worden uitgevoerd" + }, "followUpSuggest": { "copyToInput": "Kopiëren naar invoer (zelfde als shift + klik)", "autoSelectCountdown": "Automatische selectie in {{count}}s", diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index 35ee26990c..894f06f5eb 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -1,5 +1,4 @@ { - "toolTimeout": "Automatyczny timeout narzędzia: Sugerowanie alternatyw...", "greeting": "Witamy w Roo Code", "task": { "title": "Zadanie", @@ -239,6 +238,11 @@ "autoSelectCountdown": "Automatyczny wybór za {{count}}s", "countdownDisplay": "{{count}}s" }, + "toolTimeout": { + "title": "Skonfigurowany przez użytkownika timeout narzędzia:", + "subtitle": "Sugerowanie alternatyw...", + "backgroundWarning": "Uwaga: operacja może nadal działać w tle" + }, "announcement": { "title": "🎉 Roo Code {{version}} wydany", "description": "Roo Code {{version}} wprowadza potężne nowe funkcje i znaczące ulepszenia, aby ulepszyć Twój przepływ pracy programistycznej.", diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index 892ed6c49d..cc7b86eafd 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -1,5 +1,4 @@ { - "toolTimeout": "Timeout automático da ferramenta: Sugerindo alternativas...", "greeting": "Bem-vindo ao Roo Code", "task": { "title": "Tarefa", @@ -239,6 +238,11 @@ "autoSelectCountdown": "Seleção automática em {{count}}s", "countdownDisplay": "{{count}}s" }, + "toolTimeout": { + "title": "Timeout de Ferramenta Configurado pelo Usuário:", + "subtitle": "Sugerindo alternativas...", + "backgroundWarning": "Nota: a operação pode ainda estar executando em segundo plano" + }, "announcement": { "title": "🎉 Roo Code {{version}} Lançado", "description": "Roo Code {{version}} traz novos recursos poderosos e melhorias significativas para aprimorar seu fluxo de trabalho de desenvolvimento.", diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index d63264259d..64eed7bdfa 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -1,5 +1,4 @@ { - "toolTimeout": "Автоматический тайм-аут инструмента: Предлагаю альтернативы...", "greeting": "Добро пожаловать в Roo Code", "task": { "title": "Задача", @@ -244,6 +243,11 @@ "errorHeader": "Не удалось сжать контекст", "tokens": "токены" }, + "toolTimeout": { + "title": "Настроенный пользователем тайм-аут инструмента:", + "subtitle": "Предлагаем альтернативы...", + "backgroundWarning": "Примечание: операция может все еще выполняться в фоновом режиме" + }, "followUpSuggest": { "copyToInput": "Скопировать во ввод (то же, что shift + клик)", "autoSelectCountdown": "Автовыбор через {{count}}с", diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index 3377c8e70f..bc44e17c00 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -1,5 +1,4 @@ { - "toolTimeout": "Otomatik araç zaman aşımı: Alternatifler öneriliyor...", "greeting": "Roo Code'a Hoş Geldiniz", "task": { "title": "Görev", @@ -239,6 +238,11 @@ "autoSelectCountdown": "{{count}}s içinde otomatik seçilecek", "countdownDisplay": "{{count}}sn" }, + "toolTimeout": { + "title": "Kullanıcı Tarafından Yapılandırılan Araç Zaman Aşımı:", + "subtitle": "Alternatifler öneriliyor...", + "backgroundWarning": "Not: işlem hala arka planda çalışıyor olabilir" + }, "announcement": { "title": "🎉 Roo Code {{version}} Yayınlandı", "description": "Roo Code {{version}}, geliştirme iş akışınızı geliştirmek için güçlü yeni özellikler ve önemli iyileştirmeler getiriyor.", diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index 2aa199d056..e8ceb8a9d1 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -238,6 +238,11 @@ "autoSelectCountdown": "Tự động chọn sau {{count}}s", "countdownDisplay": "{{count}}s" }, + "toolTimeout": { + "title": "Thời gian chờ công cụ do người dùng cấu hình:", + "subtitle": "Đang đề xuất các lựa chọn thay thế...", + "backgroundWarning": "Lưu ý: thao tác có thể vẫn đang chạy trong nền" + }, "announcement": { "title": "🎉 Roo Code {{version}} Đã phát hành", "description": "Roo Code {{version}} mang đến các tính năng mạnh mẽ mới và cải tiến đáng kể để nâng cao quy trình phát triển của bạn.", @@ -316,6 +321,5 @@ }, "versionIndicator": { "ariaLabel": "Phiên bản {{version}} - Nhấp để xem ghi chú phát hành" - }, - "toolTimeout": "Tự động hết thời gian chờ công cụ: Đang đề xuất các lựa chọn thay thế..." + } } diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index de30f5e693..e5b3ec283e 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -238,6 +238,11 @@ "autoSelectCountdown": "{{count}}秒后自动选择", "countdownDisplay": "{{count}}秒" }, + "toolTimeout": { + "title": "用户配置的工具超时:", + "subtitle": "正在建议替代方案...", + "backgroundWarning": "注意: 操作可能仍在后台运行" + }, "announcement": { "title": "🎉 Roo Code {{version}} 已发布", "description": "Roo Code {{version}} 带来强大的新功能和重大改进,提升您的开发工作流程。", @@ -316,6 +321,5 @@ }, "versionIndicator": { "ariaLabel": "版本 {{version}} - 点击查看发布说明" - }, - "toolTimeout": "自动工具超时:正在建议替代方案..." + } } diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index 0ece02f426..b198111910 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -238,6 +238,11 @@ "autoSelectCountdown": "{{count}}秒後自動選擇", "countdownDisplay": "{{count}}秒" }, + "toolTimeout": { + "title": "使用者設定的工具逾時:", + "subtitle": "正在建議替代方案...", + "backgroundWarning": "注意: 操作可能仍在背景執行" + }, "announcement": { "title": "🎉 Roo Code {{version}} 已發布", "description": "Roo Code {{version}} 帶來強大的新功能和重大改進,提升您的開發工作流程。", @@ -316,6 +321,5 @@ }, "versionIndicator": { "ariaLabel": "版本 {{version}} - 點擊查看發布說明" - }, - "toolTimeout": "自動工具逾時:正在建議替代方案..." + } } From 7d963649e3dd93c8ed4e865714d8583ebcb9f3aa Mon Sep 17 00:00:00 2001 From: Will Li Date: Wed, 16 Jul 2025 15:41:38 -0700 Subject: [PATCH 10/12] nice catch dan! --- webview-ui/src/components/settings/AutoApproveSettings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webview-ui/src/components/settings/AutoApproveSettings.tsx b/webview-ui/src/components/settings/AutoApproveSettings.tsx index 75d38f5222..cbdad599b8 100644 --- a/webview-ui/src/components/settings/AutoApproveSettings.tsx +++ b/webview-ui/src/components/settings/AutoApproveSettings.tsx @@ -331,7 +331,7 @@ export const AutoApproveSettings = ({ min="1000" max="1800000" step="1000" - value={toolExecutionTimeoutMs || 300000} + value={toolExecutionTimeoutMs || 60000} onChange={(e) => setCachedStateField("toolExecutionTimeoutMs", parseInt(e.target.value))} disabled={!timeoutFallbackEnabled} className="w-32" From 44f538b3f7ef28b164eb2a0a132e8657c6eb8822 Mon Sep 17 00:00:00 2001 From: Will Li Date: Wed, 16 Jul 2025 16:37:41 -0700 Subject: [PATCH 11/12] test passing --- .../tools/__tests__/executeCommandTimeout.integration.spec.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts index de98c9df20..c185f69df3 100644 --- a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts +++ b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts @@ -36,6 +36,10 @@ describe("Command Execution Timeout Integration", () => { providerRef: { deref: vitest.fn().mockResolvedValue({ postMessageToWebview: vitest.fn(), + getState: vitest.fn().mockResolvedValue({ + toolExecutionTimeoutMs: 60000, + timeoutFallbackEnabled: false, // Disable new timeout approach for legacy tests + }), }), }, say: vitest.fn().mockResolvedValue(undefined), From 20a27f7c94defa586b24c6c2343ceff47282a49f Mon Sep 17 00:00:00 2001 From: Will Li Date: Wed, 16 Jul 2025 16:42:22 -0700 Subject: [PATCH 12/12] fix weird lint failure --- locales/ca/README.md | 78 ++++++++++++++++++++--------------------- locales/de/README.md | 78 ++++++++++++++++++++--------------------- locales/es/README.md | 78 ++++++++++++++++++++--------------------- locales/fr/README.md | 78 ++++++++++++++++++++--------------------- locales/hi/README.md | 78 ++++++++++++++++++++--------------------- locales/id/README.md | 78 ++++++++++++++++++++--------------------- locales/it/README.md | 78 ++++++++++++++++++++--------------------- locales/ja/README.md | 78 ++++++++++++++++++++--------------------- locales/ko/README.md | 78 ++++++++++++++++++++--------------------- locales/nl/README.md | 78 ++++++++++++++++++++--------------------- locales/pl/README.md | 78 ++++++++++++++++++++--------------------- locales/pt-BR/README.md | 78 ++++++++++++++++++++--------------------- locales/ru/README.md | 78 ++++++++++++++++++++--------------------- locales/tr/README.md | 78 ++++++++++++++++++++--------------------- locales/vi/README.md | 78 ++++++++++++++++++++--------------------- locales/zh-CN/README.md | 78 ++++++++++++++++++++--------------------- locales/zh-TW/README.md | 78 ++++++++++++++++++++--------------------- 17 files changed, 646 insertions(+), 680 deletions(-) diff --git a/locales/ca/README.md b/locales/ca/README.md index 7a3db8ef24..6ea7073db2 100644 --- a/locales/ca/README.md +++ b/locales/ca/README.md @@ -180,46 +180,44 @@ Ens encanten les contribucions de la comunitat! Comenceu llegint el nostre [CONT Gràcies a tots els nostres col·laboradors que han ajudat a millorar Roo Code! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## Llicència diff --git a/locales/de/README.md b/locales/de/README.md index 8b891a3c37..95ef8dce48 100644 --- a/locales/de/README.md +++ b/locales/de/README.md @@ -180,46 +180,44 @@ Wir lieben Community-Beiträge! Beginnen Sie mit dem Lesen unserer [CONTRIBUTING Danke an alle unsere Mitwirkenden, die geholfen haben, Roo Code zu verbessern! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## Lizenz diff --git a/locales/es/README.md b/locales/es/README.md index a8ad2832fc..08e5a721a8 100644 --- a/locales/es/README.md +++ b/locales/es/README.md @@ -180,46 +180,44 @@ Usamos [changesets](https://github.com/changesets/changesets) para versionar y p ¡Gracias a todos nuestros colaboradores que han ayudado a mejorar Roo Code! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## Licencia diff --git a/locales/fr/README.md b/locales/fr/README.md index 62c9823268..8f726f338a 100644 --- a/locales/fr/README.md +++ b/locales/fr/README.md @@ -180,46 +180,44 @@ Nous adorons les contributions de la communauté ! Commencez par lire notre [CON Merci à tous nos contributeurs qui ont aidé à améliorer Roo Code ! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## Licence diff --git a/locales/hi/README.md b/locales/hi/README.md index d4d60eea51..19e0dc944a 100644 --- a/locales/hi/README.md +++ b/locales/hi/README.md @@ -180,46 +180,44 @@ code --install-extension bin/roo-cline-.vsix Roo Code को बेहतर बनाने में मदद करने वाले हमारे सभी योगदानकर्ताओं को धन्यवाद! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## लाइसेंस diff --git a/locales/id/README.md b/locales/id/README.md index d4f68a2bf3..4141dede49 100644 --- a/locales/id/README.md +++ b/locales/id/README.md @@ -174,46 +174,44 @@ Kami menyukai kontribusi komunitas! Mulai dengan membaca [CONTRIBUTING.md](CONTR Terima kasih kepada semua kontributor kami yang telah membantu membuat Roo Code lebih baik! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## License diff --git a/locales/it/README.md b/locales/it/README.md index 13784d094f..8231f7c630 100644 --- a/locales/it/README.md +++ b/locales/it/README.md @@ -180,46 +180,44 @@ Amiamo i contributi della community! Inizia leggendo il nostro [CONTRIBUTING.md] Grazie a tutti i nostri contributori che hanno aiutato a migliorare Roo Code! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## Licenza diff --git a/locales/ja/README.md b/locales/ja/README.md index e92030bcf8..5a1ead7bbc 100644 --- a/locales/ja/README.md +++ b/locales/ja/README.md @@ -180,46 +180,44 @@ code --install-extension bin/roo-cline-.vsix Roo Codeの改善に貢献してくれたすべての貢献者に感謝します! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## ライセンス diff --git a/locales/ko/README.md b/locales/ko/README.md index f76cbaae32..b1160f102c 100644 --- a/locales/ko/README.md +++ b/locales/ko/README.md @@ -180,46 +180,44 @@ code --install-extension bin/roo-cline-.vsix Roo Code를 더 좋게 만드는 데 도움을 준 모든 기여자에게 감사드립니다! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## 라이선스 diff --git a/locales/nl/README.md b/locales/nl/README.md index d592725268..97f63c555f 100644 --- a/locales/nl/README.md +++ b/locales/nl/README.md @@ -180,46 +180,44 @@ We houden van bijdragen uit de community! Begin met het lezen van onze [CONTRIBU Dank aan alle bijdragers die Roo Code beter hebben gemaakt! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## Licentie diff --git a/locales/pl/README.md b/locales/pl/README.md index 551aa66bc6..db4addb080 100644 --- a/locales/pl/README.md +++ b/locales/pl/README.md @@ -180,46 +180,44 @@ Kochamy wkład społeczności! Zacznij od przeczytania naszego [CONTRIBUTING.md] Dziękujemy wszystkim naszym współtwórcom, którzy pomogli ulepszyć Roo Code! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## Licencja diff --git a/locales/pt-BR/README.md b/locales/pt-BR/README.md index 8994311dab..d7234a479a 100644 --- a/locales/pt-BR/README.md +++ b/locales/pt-BR/README.md @@ -180,46 +180,44 @@ Adoramos contribuições da comunidade! Comece lendo nosso [CONTRIBUTING.md](CON Obrigado a todos os nossos contribuidores que ajudaram a tornar o Roo Code melhor! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## Licença diff --git a/locales/ru/README.md b/locales/ru/README.md index 220282ae93..85ea090fbf 100644 --- a/locales/ru/README.md +++ b/locales/ru/README.md @@ -180,46 +180,44 @@ code --install-extension bin/roo-cline-.vsix Спасибо всем нашим участникам, которые помогли сделать Roo Code лучше! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## Лицензия diff --git a/locales/tr/README.md b/locales/tr/README.md index f3a7cd2f45..35b5c5a931 100644 --- a/locales/tr/README.md +++ b/locales/tr/README.md @@ -180,46 +180,44 @@ Topluluk katkılarını seviyoruz! [CONTRIBUTING.md](CONTRIBUTING.md) dosyasın Roo Code'u daha iyi hale getirmeye yardımcı olan tüm katkıda bulunanlara teşekkür ederiz! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## Lisans diff --git a/locales/vi/README.md b/locales/vi/README.md index 4dba942cec..7ef33dcfd5 100644 --- a/locales/vi/README.md +++ b/locales/vi/README.md @@ -180,46 +180,44 @@ Chúng tôi rất hoan nghênh đóng góp từ cộng đồng! Bắt đầu b Cảm ơn tất cả những người đóng góp đã giúp cải thiện Roo Code! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## Giấy Phép diff --git a/locales/zh-CN/README.md b/locales/zh-CN/README.md index 812ccab3f9..e13c88b3b3 100644 --- a/locales/zh-CN/README.md +++ b/locales/zh-CN/README.md @@ -180,46 +180,44 @@ code --install-extension bin/roo-cline-.vsix 感谢所有帮助改进 Roo Code 的贡献者! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## 许可证 diff --git a/locales/zh-TW/README.md b/locales/zh-TW/README.md index 3ecd9b44b0..e4ae30ad02 100644 --- a/locales/zh-TW/README.md +++ b/locales/zh-TW/README.md @@ -181,46 +181,44 @@ code --install-extension bin/roo-cline-.vsix 感謝所有幫助改進 Roo Code 的貢獻者! - -| mrubens
mrubens
| saoudrizwan
saoudrizwan
| cte
cte
| samhvw8
samhvw8
| daniel-lxs
daniel-lxs
| hannesrudolph
hannesrudolph
| -| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | -| KJ7LNW
KJ7LNW
| a8trejo
a8trejo
| ColemanRoo
ColemanRoo
| canrobins13
canrobins13
| stea9499
stea9499
| MuriloFP
MuriloFP
| -| joemanley201
joemanley201
| System233
System233
| jr
jr
| nissa-seru
nissa-seru
| jquanton
jquanton
| NyxJae
NyxJae
| -| roomote-bot
roomote-bot
| elianiva
elianiva
| d-oit
d-oit
| punkpeye
punkpeye
| wkordalski
wkordalski
| qdaxb
qdaxb
| -| xyOz-dev
xyOz-dev
| feifei325
feifei325
| zhangtony239
zhangtony239
| sachasayan
sachasayan
| monotykamary
monotykamary
| cannuri
cannuri
| -| Smartsheet-JB-Brown
Smartsheet-JB-Brown
| shariqriazz
shariqriazz
| vigneshsubbiah16
vigneshsubbiah16
| chrarnoldus
chrarnoldus
| pugazhendhi-m
pugazhendhi-m
| lloydchang
lloydchang
| -| SannidhyaSah
SannidhyaSah
| dtrugman
dtrugman
| Szpadel
Szpadel
| diarmidmackenzie
diarmidmackenzie
| olweraltuve
olweraltuve
| psv2522
psv2522
| -| Premshay
Premshay
| kiwina
kiwina
| lupuletic
lupuletic
| aheizi
aheizi
| liwilliam2021
liwilliam2021
| PeterDaveHello
PeterDaveHello
| -| hassoncs
hassoncs
| ChuKhaLi
ChuKhaLi
| nbihan-mediware
nbihan-mediware
| noritaka1166
noritaka1166
| RaySinner
RaySinner
| afshawnlotfi
afshawnlotfi
| -| dleffel
dleffel
| StevenTCramer
StevenTCramer
| Ruakij
Ruakij
| pdecat
pdecat
| kyle-apex
kyle-apex
| emshvac
emshvac
| -| Lunchb0ne
Lunchb0ne
| SmartManoj
SmartManoj
| vagadiya
vagadiya
| slytechnical
slytechnical
| dlab-anton
dlab-anton
| arthurauffray
arthurauffray
| -| upamune
upamune
| NamesMT
NamesMT
| taylorwilsdon
taylorwilsdon
| sammcj
sammcj
| p12tic
p12tic
| gtaylor
gtaylor
| -| aitoroses
aitoroses
| anton-otee
anton-otee
| ross
ross
| mr-ryan-james
mr-ryan-james
| heyseth
heyseth
| taisukeoe
taisukeoe
| -| avtc
avtc
| eonghk
eonghk
| GOODBOY008
GOODBOY008
| kcwhite
kcwhite
| ronyblum
ronyblum
| teddyOOXX
teddyOOXX
| -| vincentsong
vincentsong
| yongjer
yongjer
| zeozeozeo
zeozeozeo
| ashktn
ashktn
| franekp
franekp
| yt3trees
yt3trees
| -| seedlord
seedlord
| bramburn
bramburn
| benzntech
benzntech
| axkirillov
axkirillov
| olearycrew
olearycrew
| brunobergher
brunobergher
| -| catrielmuller
catrielmuller
| devxpain
devxpain
| snoyiatk
snoyiatk
| GitlyHallows
GitlyHallows
| jcbdev
jcbdev
| Chenjiayuan195
Chenjiayuan195
| -| julionav
julionav
| KanTakahiro
KanTakahiro
| SplittyDev
SplittyDev
| mdp
mdp
| napter
napter
| philfung
philfung
| -| chris-garrett
chris-garrett
| dairui1
dairui1
| dqroid
dqroid
| forestyoo
forestyoo
| hatsu38
hatsu38
| hongzio
hongzio
| -| im47cn
im47cn
| shoopapa
shoopapa
| jwcraig
jwcraig
| kinandan
kinandan
| nevermorec
nevermorec
| bbenshalom
bbenshalom
| -| bannzai
bannzai
| axmo
axmo
| asychin
asychin
| amittell
amittell
| Yoshino-Yukitaro
Yoshino-Yukitaro
| Yikai-Liao
Yikai-Liao
| -| zxdvd
zxdvd
| s97712
s97712
| vladstudio
vladstudio
| vivekfyi
vivekfyi
| tmsjngx0
tmsjngx0
| Githubguy132010
Githubguy132010
| -| tgfjt
tgfjt
| PretzelVector
PretzelVector
| zetaloop
zetaloop
| cdlliuy
cdlliuy
| user202729
user202729
| takakoutso
takakoutso
| -| student20880
student20880
| shubhamgupta731
shubhamgupta731
| shohei-ihaya
shohei-ihaya
| shivamd1810
shivamd1810
| shaybc
shaybc
| sensei-woo
sensei-woo
| -| samir-nimbly
samir-nimbly
| robertheadley
robertheadley
| refactorthis
refactorthis
| qingyuan1109
qingyuan1109
| pokutuna
pokutuna
| philipnext
philipnext
| -| village-way
village-way
| oprstchn
oprstchn
| nobu007
nobu007
| mosleyit
mosleyit
| moqimoqidea
moqimoqidea
| mlopezr
mlopezr
| -| mecab
mecab
| olup
olup
| lightrabbit
lightrabbit
| lhish
lhish
| kohii
kohii
| pfitz
pfitz
| -| ExactDoug
ExactDoug
| celestial-vault
celestial-vault
| linegel
linegel
| edwin-truthsearch-io
edwin-truthsearch-io
| EamonNerbonne
EamonNerbonne
| dbasclpy
dbasclpy
| -| dflatline
dflatline
| Deon588
Deon588
| dleen
dleen
| CW-B-W
CW-B-W
| chadgauth
chadgauth
| thecolorblue
thecolorblue
| -| bogdan0083
bogdan0083
| benashby
benashby
| Atlogit
Atlogit
| atlasgong
atlasgong
| andrewshu2000
andrewshu2000
| andreastempsch
andreastempsch
| -| alasano
alasano
| QuinsZouls
QuinsZouls
| HadesArchitect
HadesArchitect
| alarno
alarno
| nexon33
nexon33
| adilhafeez
adilhafeez
| -| adamwlarson
adamwlarson
| adamhill
adamhill
| AMHesch
AMHesch
| maekawataiki
maekawataiki
| AlexandruSmirnov
AlexandruSmirnov
| samsilveira
samsilveira
| -| 01Rian
01Rian
| RSO
RSO
| SECKainersdorfer
SECKainersdorfer
| R-omk
R-omk
| Sarke
Sarke
| PaperBoardOfficial
PaperBoardOfficial
| -| OlegOAndreev
OlegOAndreev
| kvokka
kvokka
| ecmasx
ecmasx
| mollux
mollux
| marvijo-code
marvijo-code
| markijbema
markijbema
| -| mamertofabian
mamertofabian
| monkeyDluffy6017
monkeyDluffy6017
| libertyteeth
libertyteeth
| shtse8
shtse8
| Rexarrior
Rexarrior
| kevinvandijk
kevinvandijk
| -| KevinZhao
KevinZhao
| ksze
ksze
| Juice10
Juice10
| Fovty
Fovty
| Jdo300
Jdo300
| hesara
hesara
| -| DeXtroTip
DeXtroTip
| | | | | | - +|mrubens
mrubens
|saoudrizwan
saoudrizwan
|cte
cte
|samhvw8
samhvw8
|daniel-lxs
daniel-lxs
|hannesrudolph
hannesrudolph
| +|:---:|:---:|:---:|:---:|:---:|:---:| +|KJ7LNW
KJ7LNW
|a8trejo
a8trejo
|ColemanRoo
ColemanRoo
|canrobins13
canrobins13
|stea9499
stea9499
|MuriloFP
MuriloFP
| +|joemanley201
joemanley201
|System233
System233
|jr
jr
|nissa-seru
nissa-seru
|jquanton
jquanton
|NyxJae
NyxJae
| +|roomote-bot
roomote-bot
|elianiva
elianiva
|d-oit
d-oit
|punkpeye
punkpeye
|wkordalski
wkordalski
|qdaxb
qdaxb
| +|xyOz-dev
xyOz-dev
|feifei325
feifei325
|zhangtony239
zhangtony239
|sachasayan
sachasayan
|monotykamary
monotykamary
|cannuri
cannuri
| +|Smartsheet-JB-Brown
Smartsheet-JB-Brown
|shariqriazz
shariqriazz
|vigneshsubbiah16
vigneshsubbiah16
|chrarnoldus
chrarnoldus
|pugazhendhi-m
pugazhendhi-m
|lloydchang
lloydchang
| +|SannidhyaSah
SannidhyaSah
|dtrugman
dtrugman
|Szpadel
Szpadel
|diarmidmackenzie
diarmidmackenzie
|olweraltuve
olweraltuve
|psv2522
psv2522
| +|Premshay
Premshay
|kiwina
kiwina
|lupuletic
lupuletic
|aheizi
aheizi
|liwilliam2021
liwilliam2021
|PeterDaveHello
PeterDaveHello
| +|hassoncs
hassoncs
|ChuKhaLi
ChuKhaLi
|nbihan-mediware
nbihan-mediware
|noritaka1166
noritaka1166
|RaySinner
RaySinner
|afshawnlotfi
afshawnlotfi
| +|dleffel
dleffel
|StevenTCramer
StevenTCramer
|Ruakij
Ruakij
|pdecat
pdecat
|kyle-apex
kyle-apex
|emshvac
emshvac
| +|Lunchb0ne
Lunchb0ne
|SmartManoj
SmartManoj
|vagadiya
vagadiya
|slytechnical
slytechnical
|dlab-anton
dlab-anton
|arthurauffray
arthurauffray
| +|upamune
upamune
|NamesMT
NamesMT
|taylorwilsdon
taylorwilsdon
|sammcj
sammcj
|p12tic
p12tic
|gtaylor
gtaylor
| +|aitoroses
aitoroses
|anton-otee
anton-otee
|ross
ross
|mr-ryan-james
mr-ryan-james
|heyseth
heyseth
|taisukeoe
taisukeoe
| +|avtc
avtc
|eonghk
eonghk
|GOODBOY008
GOODBOY008
|kcwhite
kcwhite
|ronyblum
ronyblum
|teddyOOXX
teddyOOXX
| +|vincentsong
vincentsong
|yongjer
yongjer
|zeozeozeo
zeozeozeo
|ashktn
ashktn
|franekp
franekp
|yt3trees
yt3trees
| +|seedlord
seedlord
|bramburn
bramburn
|benzntech
benzntech
|axkirillov
axkirillov
|olearycrew
olearycrew
|brunobergher
brunobergher
| +|catrielmuller
catrielmuller
|devxpain
devxpain
|snoyiatk
snoyiatk
|GitlyHallows
GitlyHallows
|jcbdev
jcbdev
|Chenjiayuan195
Chenjiayuan195
| +|julionav
julionav
|KanTakahiro
KanTakahiro
|SplittyDev
SplittyDev
|mdp
mdp
|napter
napter
|philfung
philfung
| +|chris-garrett
chris-garrett
|dairui1
dairui1
|dqroid
dqroid
|forestyoo
forestyoo
|hatsu38
hatsu38
|hongzio
hongzio
| +|im47cn
im47cn
|shoopapa
shoopapa
|jwcraig
jwcraig
|kinandan
kinandan
|nevermorec
nevermorec
|bbenshalom
bbenshalom
| +|bannzai
bannzai
|axmo
axmo
|asychin
asychin
|amittell
amittell
|Yoshino-Yukitaro
Yoshino-Yukitaro
|Yikai-Liao
Yikai-Liao
| +|zxdvd
zxdvd
|s97712
s97712
|vladstudio
vladstudio
|vivekfyi
vivekfyi
|tmsjngx0
tmsjngx0
|Githubguy132010
Githubguy132010
| +|tgfjt
tgfjt
|PretzelVector
PretzelVector
|zetaloop
zetaloop
|cdlliuy
cdlliuy
|user202729
user202729
|takakoutso
takakoutso
| +|student20880
student20880
|shubhamgupta731
shubhamgupta731
|shohei-ihaya
shohei-ihaya
|shivamd1810
shivamd1810
|shaybc
shaybc
|sensei-woo
sensei-woo
| +|samir-nimbly
samir-nimbly
|robertheadley
robertheadley
|refactorthis
refactorthis
|qingyuan1109
qingyuan1109
|pokutuna
pokutuna
|philipnext
philipnext
| +|village-way
village-way
|oprstchn
oprstchn
|nobu007
nobu007
|mosleyit
mosleyit
|moqimoqidea
moqimoqidea
|mlopezr
mlopezr
| +|mecab
mecab
|olup
olup
|lightrabbit
lightrabbit
|lhish
lhish
|kohii
kohii
|pfitz
pfitz
| +|ExactDoug
ExactDoug
|celestial-vault
celestial-vault
|linegel
linegel
|edwin-truthsearch-io
edwin-truthsearch-io
|EamonNerbonne
EamonNerbonne
|dbasclpy
dbasclpy
| +|dflatline
dflatline
|Deon588
Deon588
|dleen
dleen
|CW-B-W
CW-B-W
|chadgauth
chadgauth
|thecolorblue
thecolorblue
| +|bogdan0083
bogdan0083
|benashby
benashby
|Atlogit
Atlogit
|atlasgong
atlasgong
|andrewshu2000
andrewshu2000
|andreastempsch
andreastempsch
| +|alasano
alasano
|QuinsZouls
QuinsZouls
|HadesArchitect
HadesArchitect
|alarno
alarno
|nexon33
nexon33
|adilhafeez
adilhafeez
| +|adamwlarson
adamwlarson
|adamhill
adamhill
|AMHesch
AMHesch
|maekawataiki
maekawataiki
|AlexandruSmirnov
AlexandruSmirnov
|samsilveira
samsilveira
| +|01Rian
01Rian
|RSO
RSO
|SECKainersdorfer
SECKainersdorfer
|R-omk
R-omk
|Sarke
Sarke
|PaperBoardOfficial
PaperBoardOfficial
| +|OlegOAndreev
OlegOAndreev
|kvokka
kvokka
|ecmasx
ecmasx
|mollux
mollux
|marvijo-code
marvijo-code
|markijbema
markijbema
| +|mamertofabian
mamertofabian
|monkeyDluffy6017
monkeyDluffy6017
|libertyteeth
libertyteeth
|shtse8
shtse8
|Rexarrior
Rexarrior
|kevinvandijk
kevinvandijk
| +|KevinZhao
KevinZhao
|ksze
ksze
|Juice10
Juice10
|Fovty
Fovty
|Jdo300
Jdo300
|hesara
hesara
| +|DeXtroTip
DeXtroTip
| | | | | | ## 授權