From 8e1fe550b97576009c2f0e6f9a98889999376b29 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Sun, 13 Jul 2025 17:50:17 +0000 Subject: [PATCH 01/11] feat: add configurable timeout for command execution - Add commandExecutionTimeout setting to VSCode configuration (1-300 seconds, default 30s) - Implement timeout logic in executeCommand function with proper cleanup - Add timeout status to CommandExecutionStatus type - Include comprehensive tests for timeout functionality - Abort running processes when timeout is reached - Provide clear timeout error messages to users Addresses Slack mention request for configurable command execution timeout. --- packages/types/src/terminal.ts | 4 + .../executeCommandTimeout.integration.spec.ts | 168 ++++++++++++++++++ .../__tests__/executeCommandTool.spec.ts | 41 +++++ src/core/tools/executeCommandTool.ts | 49 ++++- src/package.json | 7 + src/package.nls.json | 1 + 6 files changed, 268 insertions(+), 2 deletions(-) create mode 100644 src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts diff --git a/packages/types/src/terminal.ts b/packages/types/src/terminal.ts index 51d6f252a93..ffa1ffe7811 100644 --- a/packages/types/src/terminal.ts +++ b/packages/types/src/terminal.ts @@ -25,6 +25,10 @@ export const commandExecutionStatusSchema = z.discriminatedUnion("status", [ executionId: z.string(), status: z.literal("fallback"), }), + z.object({ + executionId: z.string(), + status: z.literal("timeout"), + }), ]) export type CommandExecutionStatus = z.infer diff --git a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts new file mode 100644 index 00000000000..7decd019fbc --- /dev/null +++ b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts @@ -0,0 +1,168 @@ +// Integration tests for command execution timeout functionality +// npx vitest run src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts + +import * as vscode from "vscode" +import { executeCommand, ExecuteCommandOptions } from "../executeCommandTool" +import { Task } from "../../task/Task" +import { TerminalRegistry } from "../../../integrations/terminal/TerminalRegistry" + +// Mock dependencies +vitest.mock("vscode", () => ({ + workspace: { + getConfiguration: vitest.fn(), + }, +})) + +vitest.mock("../../../integrations/terminal/TerminalRegistry") +vitest.mock("../../task/Task") + +describe("Command Execution Timeout Integration", () => { + let mockTask: any + let mockTerminal: any + let mockProcess: any + + beforeEach(() => { + vitest.clearAllMocks() + + // Mock task + mockTask = { + cwd: "/test/directory", + terminalProcess: undefined, + providerRef: { + deref: vitest.fn().mockResolvedValue({ + postMessageToWebview: vitest.fn(), + }), + }, + } + + // Mock terminal process + mockProcess = { + abort: vitest.fn(), + then: vitest.fn(), + catch: vitest.fn(), + } + + // Mock terminal + mockTerminal = { + runCommand: vitest.fn().mockReturnValue(mockProcess), + getCurrentWorkingDirectory: vitest.fn().mockReturnValue("/test/directory"), + } + + // Mock TerminalRegistry + ;(TerminalRegistry.getOrCreateTerminal as any).mockResolvedValue(mockTerminal) + + // Mock VSCode configuration + const mockGetConfiguration = vitest.fn().mockReturnValue({ + get: vitest.fn().mockReturnValue(30000), // Default 30 second timeout + }) + ;(vscode.workspace.getConfiguration as any).mockReturnValue(mockGetConfiguration()) + }) + + it("should pass timeout configuration to executeCommand", async () => { + const customTimeout = 15000 + const options: ExecuteCommandOptions = { + executionId: "test-execution", + command: "echo test", + commandExecutionTimeout: customTimeout, + } + + // Mock a quick-completing process + const quickProcess = Promise.resolve() + mockTerminal.runCommand.mockReturnValue(quickProcess) + + await executeCommand(mockTask as Task, options) + + // Verify that the terminal was called with the command + expect(mockTerminal.runCommand).toHaveBeenCalledWith("echo test", expect.any(Object)) + }) + + it("should handle timeout scenario", async () => { + const shortTimeout = 100 // Very short timeout + const options: ExecuteCommandOptions = { + executionId: "test-execution", + command: "sleep 10", + commandExecutionTimeout: shortTimeout, + } + + // Mock a long-running process that never resolves + const longRunningProcess = new Promise(() => { + // Never resolves to simulate a hanging command + }) + mockTerminal.runCommand.mockReturnValue(longRunningProcess) + + // Execute with timeout + const result = await executeCommand(mockTask as Task, options) + + // Should return timeout error + expect(result[0]).toBe(false) // Not rejected by user + expect(result[1]).toContain("timed out") + expect(result[1]).toContain(`${shortTimeout}ms`) + }) + + it("should abort process on timeout", async () => { + const shortTimeout = 50 + const options: ExecuteCommandOptions = { + executionId: "test-execution", + command: "sleep 10", + commandExecutionTimeout: shortTimeout, + } + + // Create a process that can be aborted + let abortCalled = false + const mockAbortableProcess = { + abort: () => { + abortCalled = true + }, + then: vitest.fn(), + catch: vitest.fn(), + } + + // Mock the process to never resolve but be abortable + const neverResolvingPromise = new Promise(() => {}) + Object.assign(neverResolvingPromise, mockAbortableProcess) + + mockTerminal.runCommand.mockReturnValue(neverResolvingPromise) + + // Set the task's terminal process so it can be aborted + mockTask.terminalProcess = mockAbortableProcess + + await executeCommand(mockTask as Task, options) + + // Verify abort was called + expect(abortCalled).toBe(true) + }) + + it("should clean up timeout on successful completion", async () => { + const options: ExecuteCommandOptions = { + executionId: "test-execution", + command: "echo test", + commandExecutionTimeout: 5000, + } + + // Mock a process that completes quickly + const quickProcess = Promise.resolve() + mockTerminal.runCommand.mockReturnValue(quickProcess) + + const result = await executeCommand(mockTask as Task, options) + + // Should complete successfully without timeout + expect(result[0]).toBe(false) // Not rejected + expect(result[1]).not.toContain("timed out") + }) + + it("should use default timeout when not specified", async () => { + const options: ExecuteCommandOptions = { + executionId: "test-execution", + command: "echo test", + // commandExecutionTimeout not specified, should use default + } + + const quickProcess = Promise.resolve() + mockTerminal.runCommand.mockReturnValue(quickProcess) + + await executeCommand(mockTask as Task, options) + + // Should complete without issues using default timeout + expect(mockTerminal.runCommand).toHaveBeenCalled() + }) +}) diff --git a/src/core/tools/__tests__/executeCommandTool.spec.ts b/src/core/tools/__tests__/executeCommandTool.spec.ts index e1bc90a178f..d051e0187f7 100644 --- a/src/core/tools/__tests__/executeCommandTool.spec.ts +++ b/src/core/tools/__tests__/executeCommandTool.spec.ts @@ -1,6 +1,7 @@ // npx vitest run src/core/tools/__tests__/executeCommandTool.spec.ts import type { ToolUsage } from "@roo-code/types" +import * as vscode from "vscode" import { Task } from "../../task/Task" import { formatResponse } from "../../prompts/responses" @@ -12,6 +13,12 @@ vitest.mock("execa", () => ({ execa: vitest.fn(), })) +vitest.mock("vscode", () => ({ + workspace: { + getConfiguration: vitest.fn(), + }, +})) + vitest.mock("../../task/Task") vitest.mock("../../prompts/responses") @@ -266,4 +273,38 @@ describe("executeCommandTool", () => { expect(mockExecuteCommand).not.toHaveBeenCalled() }) }) + + describe("Command execution timeout configuration", () => { + it("should include timeout parameter in ExecuteCommandOptions", () => { + // This test verifies that the timeout configuration is properly typed + // The actual timeout logic is tested in integration tests + const options = { + executionId: "test-id", + command: "echo test", + commandExecutionTimeout: 15000, + } + + // Verify the options object has the expected structure + expect(options.commandExecutionTimeout).toBe(15000) + expect(typeof options.commandExecutionTimeout).toBe("number") + }) + + it("should handle timeout parameter in function signature", () => { + // Test that the executeCommand function accepts timeout parameter + // This is a compile-time check that the types are correct + const mockOptions = { + executionId: "test-id", + command: "echo test", + customCwd: undefined, + terminalShellIntegrationDisabled: false, + terminalOutputLineLimit: 500, + commandExecutionTimeout: 30000, + } + + // Verify all required properties exist + expect(mockOptions.executionId).toBeDefined() + expect(mockOptions.command).toBeDefined() + expect(mockOptions.commandExecutionTimeout).toBeDefined() + }) + }) }) diff --git a/src/core/tools/executeCommandTool.ts b/src/core/tools/executeCommandTool.ts index 795beccc061..47fe947a479 100644 --- a/src/core/tools/executeCommandTool.ts +++ b/src/core/tools/executeCommandTool.ts @@ -1,5 +1,6 @@ import fs from "fs/promises" import * as path from "path" +import * as vscode from "vscode" import delay from "delay" @@ -14,6 +15,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 { Package } from "../../shared/package" class ShellIntegrationError extends Error {} @@ -62,12 +64,18 @@ export async function executeCommandTool( const clineProviderState = await clineProvider?.getState() const { terminalOutputLineLimit = 500, terminalShellIntegrationDisabled = false } = clineProviderState ?? {} + // Get command execution timeout from VSCode configuration + const commandExecutionTimeout = vscode.workspace + .getConfiguration(Package.name) + .get("commandExecutionTimeout", 30000) + const options: ExecuteCommandOptions = { executionId, command, customCwd, terminalShellIntegrationDisabled, terminalOutputLineLimit, + commandExecutionTimeout, } try { @@ -113,6 +121,7 @@ export type ExecuteCommandOptions = { customCwd?: string terminalShellIntegrationDisabled?: boolean terminalOutputLineLimit?: number + commandExecutionTimeout?: number } export async function executeCommand( @@ -123,6 +132,7 @@ export async function executeCommand( customCwd, terminalShellIntegrationDisabled = false, terminalOutputLineLimit = 500, + commandExecutionTimeout = 30000, }: ExecuteCommandOptions, ): Promise<[boolean, ToolResponse]> { let workingDir: string @@ -211,8 +221,43 @@ export async function executeCommand( const process = terminal.runCommand(command, callbacks) cline.terminalProcess = process - await process - cline.terminalProcess = undefined + // Implement command execution timeout + let timeoutId: NodeJS.Timeout | undefined + let isTimedOut = false + + const timeoutPromise = new Promise((_, reject) => { + timeoutId = setTimeout(() => { + isTimedOut = true + // Try to abort the process + if (cline.terminalProcess) { + cline.terminalProcess.abort() + } + reject(new Error(`Command execution timed out after ${commandExecutionTimeout}ms`)) + }, commandExecutionTimeout) + }) + + try { + await Promise.race([process, timeoutPromise]) + } catch (error) { + if (isTimedOut) { + // Handle timeout case + const status: CommandExecutionStatus = { executionId, status: "timeout" } + clineProvider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) }) + + cline.terminalProcess = undefined + + return [ + false, + `Command execution timed out after ${commandExecutionTimeout}ms. The command was terminated.`, + ] + } + throw error + } finally { + if (timeoutId) { + clearTimeout(timeoutId) + } + cline.terminalProcess = undefined + } if (shellIntegrationError) { throw new ShellIntegrationError(shellIntegrationError) diff --git a/src/package.json b/src/package.json index bc55107fc81..c8b5206aa3b 100644 --- a/src/package.json +++ b/src/package.json @@ -338,6 +338,13 @@ "default": [], "description": "%commands.deniedCommands.description%" }, + "roo-cline.commandExecutionTimeout": { + "type": "number", + "default": 30000, + "minimum": 1000, + "maximum": 300000, + "description": "%commands.commandExecutionTimeout.description%" + }, "roo-cline.vsCodeLmModelSelector": { "type": "object", "properties": { diff --git a/src/package.nls.json b/src/package.nls.json index 2c8908fadb9..1cfff343ca7 100644 --- a/src/package.nls.json +++ b/src/package.nls.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Commands that can be auto-executed when 'Always approve execute operations' is enabled", "commands.deniedCommands.description": "Command prefixes that will be automatically denied without asking for approval. In case of conflicts with allowed commands, the longest prefix match takes precedence. Add * to deny all commands.", + "commands.commandExecutionTimeout.description": "Maximum time in milliseconds to wait for command execution to complete before timing out (1000-300000ms, default: 30000ms)", "settings.vsCodeLmModelSelector.description": "Settings for VSCode Language Model API", "settings.vsCodeLmModelSelector.vendor.description": "The vendor of the language model (e.g. copilot)", "settings.vsCodeLmModelSelector.family.description": "The family of the language model (e.g. gpt-4)", From ac332f3a03c87e9d1ff4b44ccdfc84fe804dec18 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Sun, 13 Jul 2025 18:02:17 +0000 Subject: [PATCH 02/11] fix: resolve integration test failures for command timeout functionality - Fixed fs.promises mocking in integration tests - Added proper abort method mocking for timeout scenarios - Increased test timeouts for async timeout testing - All timeout integration tests now pass successfully --- .../executeCommandTimeout.integration.spec.ts | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts index 7decd019fbc..e7ef2c45370 100644 --- a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts +++ b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts @@ -2,6 +2,7 @@ // npx vitest run src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts import * as vscode from "vscode" +import * as fs from "fs/promises" import { executeCommand, ExecuteCommandOptions } from "../executeCommandTool" import { Task } from "../../task/Task" import { TerminalRegistry } from "../../../integrations/terminal/TerminalRegistry" @@ -13,6 +14,7 @@ vitest.mock("vscode", () => ({ }, })) +vitest.mock("fs/promises") vitest.mock("../../../integrations/terminal/TerminalRegistry") vitest.mock("../../task/Task") @@ -24,6 +26,9 @@ describe("Command Execution Timeout Integration", () => { beforeEach(() => { vitest.clearAllMocks() + // Mock fs.access to resolve successfully for working directory + ;(fs.access as any).mockResolvedValue(undefined) + // Mock task mockTask = { cwd: "/test/directory", @@ -84,10 +89,14 @@ describe("Command Execution Timeout Integration", () => { commandExecutionTimeout: shortTimeout, } - // Mock a long-running process that never resolves + // Create a process that never resolves but has an abort method const longRunningProcess = new Promise(() => { // Never resolves to simulate a hanging command }) + + // Add abort method to the promise + ;(longRunningProcess as any).abort = vitest.fn() + mockTerminal.runCommand.mockReturnValue(longRunningProcess) // Execute with timeout @@ -97,7 +106,7 @@ describe("Command Execution Timeout Integration", () => { expect(result[0]).toBe(false) // Not rejected by user expect(result[1]).toContain("timed out") expect(result[1]).toContain(`${shortTimeout}ms`) - }) + }, 10000) // Increase test timeout to 10 seconds it("should abort process on timeout", async () => { const shortTimeout = 50 @@ -108,29 +117,19 @@ describe("Command Execution Timeout Integration", () => { } // Create a process that can be aborted - let abortCalled = false - const mockAbortableProcess = { - abort: () => { - abortCalled = true - }, - then: vitest.fn(), - catch: vitest.fn(), - } + const abortSpy = vitest.fn() // Mock the process to never resolve but be abortable const neverResolvingPromise = new Promise(() => {}) - Object.assign(neverResolvingPromise, mockAbortableProcess) + ;(neverResolvingPromise as any).abort = abortSpy mockTerminal.runCommand.mockReturnValue(neverResolvingPromise) - // Set the task's terminal process so it can be aborted - mockTask.terminalProcess = mockAbortableProcess - await executeCommand(mockTask as Task, options) // Verify abort was called - expect(abortCalled).toBe(true) - }) + expect(abortSpy).toHaveBeenCalled() + }, 5000) // Increase test timeout to 5 seconds it("should clean up timeout on successful completion", async () => { const options: ExecuteCommandOptions = { From 3df6abd044aefef0f0f835afa322c7cca3964790 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Sun, 13 Jul 2025 18:22:35 +0000 Subject: [PATCH 03/11] feat: change default command execution timeout to 0 (no timeout) - Change default commandExecutionTimeout from 30000ms to 0 (no timeout) - Update minimum value from 1000ms to 0ms in package.json - Update package.nls.json description to clarify 0 = no timeout - Modify executeCommandTool.ts to skip timeout logic when timeout is 0 - Update tests to reflect new default behavior and add test for no timeout - Timeout functionality works for both VSCode terminal and execa execution Addresses @mrubens feedback in PR #5668 --- .../executeCommandTimeout.integration.spec.ts | 29 ++++++- .../__tests__/executeCommandTool.spec.ts | 2 +- src/core/tools/executeCommandTool.ts | 75 +++++++++++-------- src/package.json | 4 +- src/package.nls.json | 2 +- 5 files changed, 71 insertions(+), 41 deletions(-) diff --git a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts index e7ef2c45370..056423bcc2d 100644 --- a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts +++ b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts @@ -58,7 +58,7 @@ describe("Command Execution Timeout Integration", () => { // Mock VSCode configuration const mockGetConfiguration = vitest.fn().mockReturnValue({ - get: vitest.fn().mockReturnValue(30000), // Default 30 second timeout + get: vitest.fn().mockReturnValue(0), // Default 0 (no timeout) }) ;(vscode.workspace.getConfiguration as any).mockReturnValue(mockGetConfiguration()) }) @@ -149,11 +149,11 @@ describe("Command Execution Timeout Integration", () => { expect(result[1]).not.toContain("timed out") }) - it("should use default timeout when not specified", async () => { + it("should use default timeout when not specified (0 = no timeout)", async () => { const options: ExecuteCommandOptions = { executionId: "test-execution", command: "echo test", - // commandExecutionTimeout not specified, should use default + // commandExecutionTimeout not specified, should use default (0) } const quickProcess = Promise.resolve() @@ -161,7 +161,28 @@ describe("Command Execution Timeout Integration", () => { await executeCommand(mockTask as Task, options) - // Should complete without issues using default timeout + // Should complete without issues using default (no timeout) expect(mockTerminal.runCommand).toHaveBeenCalled() }) + + it("should not timeout when commandExecutionTimeout is 0", async () => { + const options: ExecuteCommandOptions = { + executionId: "test-execution", + command: "sleep 10", + commandExecutionTimeout: 0, // No timeout + } + + // Create a process that resolves after a delay to simulate a long-running command + const longRunningProcess = new Promise((resolve) => { + setTimeout(resolve, 200) // 200ms delay + }) + + mockTerminal.runCommand.mockReturnValue(longRunningProcess) + + const result = await executeCommand(mockTask as Task, options) + + // Should complete successfully without timeout + expect(result[0]).toBe(false) // Not rejected + expect(result[1]).not.toContain("timed out") + }) }) diff --git a/src/core/tools/__tests__/executeCommandTool.spec.ts b/src/core/tools/__tests__/executeCommandTool.spec.ts index d051e0187f7..042c64fa1bf 100644 --- a/src/core/tools/__tests__/executeCommandTool.spec.ts +++ b/src/core/tools/__tests__/executeCommandTool.spec.ts @@ -298,7 +298,7 @@ describe("executeCommandTool", () => { customCwd: undefined, terminalShellIntegrationDisabled: false, terminalOutputLineLimit: 500, - commandExecutionTimeout: 30000, + commandExecutionTimeout: 0, } // Verify all required properties exist diff --git a/src/core/tools/executeCommandTool.ts b/src/core/tools/executeCommandTool.ts index 47fe947a479..bff1a6bad98 100644 --- a/src/core/tools/executeCommandTool.ts +++ b/src/core/tools/executeCommandTool.ts @@ -67,7 +67,7 @@ export async function executeCommandTool( // Get command execution timeout from VSCode configuration const commandExecutionTimeout = vscode.workspace .getConfiguration(Package.name) - .get("commandExecutionTimeout", 30000) + .get("commandExecutionTimeout", 0) const options: ExecuteCommandOptions = { executionId, @@ -132,7 +132,7 @@ export async function executeCommand( customCwd, terminalShellIntegrationDisabled = false, terminalOutputLineLimit = 500, - commandExecutionTimeout = 30000, + commandExecutionTimeout = 0, }: ExecuteCommandOptions, ): Promise<[boolean, ToolResponse]> { let workingDir: string @@ -221,42 +221,51 @@ export async function executeCommand( const process = terminal.runCommand(command, callbacks) cline.terminalProcess = process - // Implement command execution timeout - let timeoutId: NodeJS.Timeout | undefined - let isTimedOut = false - - const timeoutPromise = new Promise((_, reject) => { - timeoutId = setTimeout(() => { - isTimedOut = true - // Try to abort the process - if (cline.terminalProcess) { - cline.terminalProcess.abort() - } - reject(new Error(`Command execution timed out after ${commandExecutionTimeout}ms`)) - }, commandExecutionTimeout) - }) + // Implement command execution timeout (skip if timeout is 0) + if (commandExecutionTimeout > 0) { + let timeoutId: NodeJS.Timeout | undefined + let isTimedOut = false + + const timeoutPromise = new Promise((_, reject) => { + timeoutId = setTimeout(() => { + isTimedOut = true + // Try to abort the process + if (cline.terminalProcess) { + cline.terminalProcess.abort() + } + reject(new Error(`Command execution timed out after ${commandExecutionTimeout}ms`)) + }, commandExecutionTimeout) + }) + + try { + await Promise.race([process, timeoutPromise]) + } catch (error) { + if (isTimedOut) { + // Handle timeout case + const status: CommandExecutionStatus = { executionId, status: "timeout" } + clineProvider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) }) - try { - await Promise.race([process, timeoutPromise]) - } catch (error) { - if (isTimedOut) { - // Handle timeout case - const status: CommandExecutionStatus = { executionId, status: "timeout" } - clineProvider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) }) + cline.terminalProcess = undefined + return [ + false, + `Command execution timed out after ${commandExecutionTimeout}ms. The command was terminated.`, + ] + } + throw error + } finally { + if (timeoutId) { + clearTimeout(timeoutId) + } cline.terminalProcess = undefined - - return [ - false, - `Command execution timed out after ${commandExecutionTimeout}ms. The command was terminated.`, - ] } - throw error - } finally { - if (timeoutId) { - clearTimeout(timeoutId) + } else { + // No timeout - just wait for the process to complete + try { + await process + } finally { + cline.terminalProcess = undefined } - cline.terminalProcess = undefined } if (shellIntegrationError) { diff --git a/src/package.json b/src/package.json index c8b5206aa3b..4fd24a54b55 100644 --- a/src/package.json +++ b/src/package.json @@ -340,8 +340,8 @@ }, "roo-cline.commandExecutionTimeout": { "type": "number", - "default": 30000, - "minimum": 1000, + "default": 0, + "minimum": 0, "maximum": 300000, "description": "%commands.commandExecutionTimeout.description%" }, diff --git a/src/package.nls.json b/src/package.nls.json index 1cfff343ca7..dcc1ad6d394 100644 --- a/src/package.nls.json +++ b/src/package.nls.json @@ -28,7 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Commands that can be auto-executed when 'Always approve execute operations' is enabled", "commands.deniedCommands.description": "Command prefixes that will be automatically denied without asking for approval. In case of conflicts with allowed commands, the longest prefix match takes precedence. Add * to deny all commands.", - "commands.commandExecutionTimeout.description": "Maximum time in milliseconds to wait for command execution to complete before timing out (1000-300000ms, default: 30000ms)", + "commands.commandExecutionTimeout.description": "Maximum time in milliseconds to wait for command execution to complete before timing out (0 = no timeout, 1000-300000ms, default: 0ms)", "settings.vsCodeLmModelSelector.description": "Settings for VSCode Language Model API", "settings.vsCodeLmModelSelector.vendor.description": "The vendor of the language model (e.g. copilot)", "settings.vsCodeLmModelSelector.family.description": "The family of the language model (e.g. gpt-4)", From b0a72dc3ee1ec6163a5b5feea6161b26b0756c5a Mon Sep 17 00:00:00 2001 From: Roo Code Date: Sun, 13 Jul 2025 19:03:57 +0000 Subject: [PATCH 04/11] feat: change command execution timeout from milliseconds to seconds - Update package.json configuration: max timeout now 600s (10 minutes) instead of 300000ms - Update package.nls.json description to reflect seconds unit - Update executeCommandTool.ts to convert seconds to milliseconds internally - Update error messages to display timeout in seconds - Update integration and unit tests to use seconds configuration - Maintain backward compatibility by converting seconds to milliseconds for internal timeout logic --- .../executeCommandTimeout.integration.spec.ts | 14 +++++++++----- .../tools/__tests__/executeCommandTool.spec.ts | 4 +++- src/core/tools/executeCommandTool.ts | 11 +++++++---- src/package.json | 2 +- src/package.nls.json | 2 +- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts index 056423bcc2d..049783f3786 100644 --- a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts +++ b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts @@ -64,7 +64,8 @@ describe("Command Execution Timeout Integration", () => { }) it("should pass timeout configuration to executeCommand", async () => { - const customTimeout = 15000 + const customTimeoutSeconds = 15 + const customTimeout = customTimeoutSeconds * 1000 // Convert to milliseconds for internal use const options: ExecuteCommandOptions = { executionId: "test-execution", command: "echo test", @@ -82,7 +83,8 @@ describe("Command Execution Timeout Integration", () => { }) it("should handle timeout scenario", async () => { - const shortTimeout = 100 // Very short timeout + const shortTimeoutSeconds = 0.1 // Very short timeout in seconds + const shortTimeout = shortTimeoutSeconds * 1000 // Convert to milliseconds const options: ExecuteCommandOptions = { executionId: "test-execution", command: "sleep 10", @@ -105,11 +107,12 @@ describe("Command Execution Timeout Integration", () => { // Should return timeout error expect(result[0]).toBe(false) // Not rejected by user expect(result[1]).toContain("timed out") - expect(result[1]).toContain(`${shortTimeout}ms`) + expect(result[1]).toContain(`${shortTimeoutSeconds}s`) }, 10000) // Increase test timeout to 10 seconds it("should abort process on timeout", async () => { - const shortTimeout = 50 + const shortTimeoutSeconds = 0.05 + const shortTimeout = shortTimeoutSeconds * 1000 const options: ExecuteCommandOptions = { executionId: "test-execution", command: "sleep 10", @@ -132,10 +135,11 @@ describe("Command Execution Timeout Integration", () => { }, 5000) // Increase test timeout to 5 seconds it("should clean up timeout on successful completion", async () => { + const timeoutSeconds = 5 const options: ExecuteCommandOptions = { executionId: "test-execution", command: "echo test", - commandExecutionTimeout: 5000, + commandExecutionTimeout: timeoutSeconds * 1000, } // Mock a process that completes quickly diff --git a/src/core/tools/__tests__/executeCommandTool.spec.ts b/src/core/tools/__tests__/executeCommandTool.spec.ts index 042c64fa1bf..dbb1945177a 100644 --- a/src/core/tools/__tests__/executeCommandTool.spec.ts +++ b/src/core/tools/__tests__/executeCommandTool.spec.ts @@ -278,10 +278,12 @@ describe("executeCommandTool", () => { it("should include timeout parameter in ExecuteCommandOptions", () => { // This test verifies that the timeout configuration is properly typed // The actual timeout logic is tested in integration tests + // Note: timeout is stored internally in milliseconds but configured in seconds + const timeoutSeconds = 15 const options = { executionId: "test-id", command: "echo test", - commandExecutionTimeout: 15000, + commandExecutionTimeout: timeoutSeconds * 1000, // Convert to milliseconds } // Verify the options object has the expected structure diff --git a/src/core/tools/executeCommandTool.ts b/src/core/tools/executeCommandTool.ts index bff1a6bad98..ba960f4aa68 100644 --- a/src/core/tools/executeCommandTool.ts +++ b/src/core/tools/executeCommandTool.ts @@ -64,11 +64,14 @@ export async function executeCommandTool( const clineProviderState = await clineProvider?.getState() const { terminalOutputLineLimit = 500, terminalShellIntegrationDisabled = false } = clineProviderState ?? {} - // Get command execution timeout from VSCode configuration - const commandExecutionTimeout = vscode.workspace + // Get command execution timeout from VSCode configuration (in seconds) + const commandExecutionTimeoutSeconds = vscode.workspace .getConfiguration(Package.name) .get("commandExecutionTimeout", 0) + // Convert seconds to milliseconds for internal use + const commandExecutionTimeout = commandExecutionTimeoutSeconds * 1000 + const options: ExecuteCommandOptions = { executionId, command, @@ -233,7 +236,7 @@ export async function executeCommand( if (cline.terminalProcess) { cline.terminalProcess.abort() } - reject(new Error(`Command execution timed out after ${commandExecutionTimeout}ms`)) + reject(new Error(`Command execution timed out after ${commandExecutionTimeout / 1000}s`)) }, commandExecutionTimeout) }) @@ -249,7 +252,7 @@ export async function executeCommand( return [ false, - `Command execution timed out after ${commandExecutionTimeout}ms. The command was terminated.`, + `Command execution timed out after ${commandExecutionTimeout / 1000}s. The command was terminated.`, ] } throw error diff --git a/src/package.json b/src/package.json index 4fd24a54b55..fb4eab61776 100644 --- a/src/package.json +++ b/src/package.json @@ -342,7 +342,7 @@ "type": "number", "default": 0, "minimum": 0, - "maximum": 300000, + "maximum": 600, "description": "%commands.commandExecutionTimeout.description%" }, "roo-cline.vsCodeLmModelSelector": { diff --git a/src/package.nls.json b/src/package.nls.json index dcc1ad6d394..c5225c45c8a 100644 --- a/src/package.nls.json +++ b/src/package.nls.json @@ -28,7 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Commands that can be auto-executed when 'Always approve execute operations' is enabled", "commands.deniedCommands.description": "Command prefixes that will be automatically denied without asking for approval. In case of conflicts with allowed commands, the longest prefix match takes precedence. Add * to deny all commands.", - "commands.commandExecutionTimeout.description": "Maximum time in milliseconds to wait for command execution to complete before timing out (0 = no timeout, 1000-300000ms, default: 0ms)", + "commands.commandExecutionTimeout.description": "Maximum time in seconds to wait for command execution to complete before timing out (0 = no timeout, 1-600s, default: 0s)", "settings.vsCodeLmModelSelector.description": "Settings for VSCode Language Model API", "settings.vsCodeLmModelSelector.vendor.description": "The vendor of the language model (e.g. copilot)", "settings.vsCodeLmModelSelector.family.description": "The family of the language model (e.g. gpt-4)", From 784870920f8e41e1704faceaaf3dd9abf036509d Mon Sep 17 00:00:00 2001 From: Roo Code Date: Sun, 13 Jul 2025 19:11:57 +0000 Subject: [PATCH 05/11] feat: Add commandExecutionTimeout translations for all supported languages - Added translations for commands.commandExecutionTimeout.description in 17 languages - Covers: ca, de, es, fr, hi, id, it, ja, ko, nl, pl, pt-BR, ru, tr, vi, zh-CN, zh-TW - All translations validated with missing-translations script --- src/package.nls.ca.json | 1 + src/package.nls.de.json | 1 + src/package.nls.es.json | 1 + src/package.nls.fr.json | 1 + src/package.nls.hi.json | 1 + src/package.nls.id.json | 1 + src/package.nls.it.json | 1 + src/package.nls.ja.json | 1 + src/package.nls.ko.json | 1 + src/package.nls.nl.json | 1 + src/package.nls.pl.json | 1 + src/package.nls.pt-BR.json | 1 + src/package.nls.ru.json | 1 + src/package.nls.tr.json | 1 + src/package.nls.vi.json | 1 + src/package.nls.zh-CN.json | 1 + src/package.nls.zh-TW.json | 1 + 17 files changed, 17 insertions(+) diff --git a/src/package.nls.ca.json b/src/package.nls.ca.json index 0d82f931c4f..339e635f0dd 100644 --- a/src/package.nls.ca.json +++ b/src/package.nls.ca.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Ordres que es poden executar automàticament quan 'Aprova sempre les operacions d'execució' està activat", "commands.deniedCommands.description": "Prefixos d'ordres que seran automàticament denegats sense demanar aprovació. En cas de conflictes amb ordres permeses, la coincidència de prefix més llarga té prioritat. Afegeix * per denegar totes les ordres.", + "commands.commandExecutionTimeout.description": "Temps màxim en segons per esperar que l'execució de l'ordre es completi abans d'esgotar el temps (0 = sense temps límit, 1-600s, per defecte: 0s)", "settings.vsCodeLmModelSelector.description": "Configuració per a l'API del model de llenguatge VSCode", "settings.vsCodeLmModelSelector.vendor.description": "El proveïdor del model de llenguatge (p. ex. copilot)", "settings.vsCodeLmModelSelector.family.description": "La família del model de llenguatge (p. ex. gpt-4)", diff --git a/src/package.nls.de.json b/src/package.nls.de.json index 2a04ed5398c..5a6fe65b119 100644 --- a/src/package.nls.de.json +++ b/src/package.nls.de.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Befehle, die automatisch ausgeführt werden können, wenn 'Ausführungsoperationen immer genehmigen' aktiviert ist", "commands.deniedCommands.description": "Befehlspräfixe, die automatisch abgelehnt werden, ohne nach Genehmigung zu fragen. Bei Konflikten mit erlaubten Befehlen hat die längste Präfix-Übereinstimmung Vorrang. Füge * hinzu, um alle Befehle abzulehnen.", + "commands.commandExecutionTimeout.description": "Maximale Zeit in Sekunden, die auf den Abschluss der Befehlsausführung gewartet wird, bevor ein Timeout auftritt (0 = kein Timeout, 1-600s, Standard: 0s)", "settings.vsCodeLmModelSelector.description": "Einstellungen für die VSCode-Sprachmodell-API", "settings.vsCodeLmModelSelector.vendor.description": "Der Anbieter des Sprachmodells (z.B. copilot)", "settings.vsCodeLmModelSelector.family.description": "Die Familie des Sprachmodells (z.B. gpt-4)", diff --git a/src/package.nls.es.json b/src/package.nls.es.json index 1966c4aecbe..3e480550d8d 100644 --- a/src/package.nls.es.json +++ b/src/package.nls.es.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Comandos que pueden ejecutarse automáticamente cuando 'Aprobar siempre operaciones de ejecución' está activado", "commands.deniedCommands.description": "Prefijos de comandos que serán automáticamente denegados sin solicitar aprobación. En caso de conflictos con comandos permitidos, la coincidencia de prefijo más larga tiene prioridad. Añade * para denegar todos los comandos.", + "commands.commandExecutionTimeout.description": "Tiempo máximo en segundos para esperar que se complete la ejecución del comando antes de que expire (0 = sin tiempo límite, 1-600s, predeterminado: 0s)", "settings.vsCodeLmModelSelector.description": "Configuración para la API del modelo de lenguaje VSCode", "settings.vsCodeLmModelSelector.vendor.description": "El proveedor del modelo de lenguaje (ej. copilot)", "settings.vsCodeLmModelSelector.family.description": "La familia del modelo de lenguaje (ej. gpt-4)", diff --git a/src/package.nls.fr.json b/src/package.nls.fr.json index 293c87351be..9e8fb83cc35 100644 --- a/src/package.nls.fr.json +++ b/src/package.nls.fr.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Commandes pouvant être exécutées automatiquement lorsque 'Toujours approuver les opérations d'exécution' est activé", "commands.deniedCommands.description": "Préfixes de commandes qui seront automatiquement refusés sans demander d'approbation. En cas de conflit avec les commandes autorisées, la correspondance de préfixe la plus longue a la priorité. Ajouter * pour refuser toutes les commandes.", + "commands.commandExecutionTimeout.description": "Temps maximum en secondes pour attendre que l'exécution de la commande se termine avant expiration (0 = pas de délai, 1-600s, défaut : 0s)", "settings.vsCodeLmModelSelector.description": "Paramètres pour l'API du modèle de langage VSCode", "settings.vsCodeLmModelSelector.vendor.description": "Le fournisseur du modèle de langage (ex: copilot)", "settings.vsCodeLmModelSelector.family.description": "La famille du modèle de langage (ex: gpt-4)", diff --git a/src/package.nls.hi.json b/src/package.nls.hi.json index 471cbe464e8..88bc8459696 100644 --- a/src/package.nls.hi.json +++ b/src/package.nls.hi.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "वे कमांड जो स्वचालित रूप से निष्पादित की जा सकती हैं जब 'हमेशा निष्पादन संचालन को स्वीकृत करें' सक्रिय हो", "commands.deniedCommands.description": "कमांड प्रीफिक्स जो स्वचालित रूप से अस्वीकार कर दिए जाएंगे बिना अनुमोदन मांगे। अनुमतित कमांड के साथ संघर्ष की स्थिति में, सबसे लंबा प्रीफिक्स मैच प्राथमिकता लेता है। सभी कमांड को अस्वीकार करने के लिए * जोड़ें।", + "commands.commandExecutionTimeout.description": "कमांड निष्पादन पूरा होने का इंतजार करने के लिए अधिकतम समय सेकंड में, समय समाप्त होने से पहले (0 = कोई समय सीमा नहीं, 1-600s, डिफ़ॉल्ट: 0s)", "settings.vsCodeLmModelSelector.description": "VSCode भाषा मॉडल API के लिए सेटिंग्स", "settings.vsCodeLmModelSelector.vendor.description": "भाषा मॉडल का विक्रेता (उदा. copilot)", "settings.vsCodeLmModelSelector.family.description": "भाषा मॉडल का परिवार (उदा. gpt-4)", diff --git a/src/package.nls.id.json b/src/package.nls.id.json index d2cc5737c80..1a2e038547b 100644 --- a/src/package.nls.id.json +++ b/src/package.nls.id.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Perintah yang dapat dijalankan secara otomatis ketika 'Selalu setujui operasi eksekusi' diaktifkan", "commands.deniedCommands.description": "Awalan perintah yang akan otomatis ditolak tanpa meminta persetujuan. Jika terjadi konflik dengan perintah yang diizinkan, pencocokan awalan terpanjang akan diprioritaskan. Tambahkan * untuk menolak semua perintah.", + "commands.commandExecutionTimeout.description": "Waktu maksimum dalam detik untuk menunggu eksekusi perintah selesai sebelum timeout (0 = tanpa timeout, 1-600s, default: 0s)", "settings.vsCodeLmModelSelector.description": "Pengaturan untuk API Model Bahasa VSCode", "settings.vsCodeLmModelSelector.vendor.description": "Vendor dari model bahasa (misalnya copilot)", "settings.vsCodeLmModelSelector.family.description": "Keluarga dari model bahasa (misalnya gpt-4)", diff --git a/src/package.nls.it.json b/src/package.nls.it.json index c790c27a889..4d5ac4895d6 100644 --- a/src/package.nls.it.json +++ b/src/package.nls.it.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Comandi che possono essere eseguiti automaticamente quando 'Approva sempre le operazioni di esecuzione' è attivato", "commands.deniedCommands.description": "Prefissi di comandi che verranno automaticamente rifiutati senza richiedere approvazione. In caso di conflitti con comandi consentiti, la corrispondenza del prefisso più lungo ha la precedenza. Aggiungi * per rifiutare tutti i comandi.", + "commands.commandExecutionTimeout.description": "Tempo massimo in secondi per attendere il completamento dell'esecuzione del comando prima del timeout (0 = nessun timeout, 1-600s, predefinito: 0s)", "settings.vsCodeLmModelSelector.description": "Impostazioni per l'API del modello linguistico VSCode", "settings.vsCodeLmModelSelector.vendor.description": "Il fornitore del modello linguistico (es. copilot)", "settings.vsCodeLmModelSelector.family.description": "La famiglia del modello linguistico (es. gpt-4)", diff --git a/src/package.nls.ja.json b/src/package.nls.ja.json index eec17d344ca..dcbc01d1640 100644 --- a/src/package.nls.ja.json +++ b/src/package.nls.ja.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "'常に実行操作を承認する'が有効な場合に自動実行できるコマンド", "commands.deniedCommands.description": "承認を求めずに自動的に拒否されるコマンドプレフィックス。許可されたコマンドとの競合がある場合、最長プレフィックスマッチが優先されます。すべてのコマンドを拒否するには * を追加してください。", + "commands.commandExecutionTimeout.description": "コマンド実行の完了を待つ最大時間(秒)、タイムアウトまで(0 = タイムアウトなし、1-600秒、デフォルト: 0秒)", "settings.vsCodeLmModelSelector.description": "VSCode 言語モデル API の設定", "settings.vsCodeLmModelSelector.vendor.description": "言語モデルのベンダー(例:copilot)", "settings.vsCodeLmModelSelector.family.description": "言語モデルのファミリー(例:gpt-4)", diff --git a/src/package.nls.ko.json b/src/package.nls.ko.json index 833ef268750..6cb839e793c 100644 --- a/src/package.nls.ko.json +++ b/src/package.nls.ko.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "'항상 실행 작업 승인' 이 활성화되어 있을 때 자동으로 실행할 수 있는 명령어", "commands.deniedCommands.description": "승인을 요청하지 않고 자동으로 거부될 명령어 접두사. 허용된 명령어와 충돌하는 경우 가장 긴 접두사 일치가 우선됩니다. 모든 명령어를 거부하려면 *를 추가하세요.", + "commands.commandExecutionTimeout.description": "명령어 실행이 완료되기를 기다리는 최대 시간(초), 타임아웃 전까지 (0 = 타임아웃 없음, 1-600초, 기본값: 0초)", "settings.vsCodeLmModelSelector.description": "VSCode 언어 모델 API 설정", "settings.vsCodeLmModelSelector.vendor.description": "언어 모델 공급자 (예: copilot)", "settings.vsCodeLmModelSelector.family.description": "언어 모델 계열 (예: gpt-4)", diff --git a/src/package.nls.nl.json b/src/package.nls.nl.json index bf74a5d2c68..51b23ec1a65 100644 --- a/src/package.nls.nl.json +++ b/src/package.nls.nl.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Commando's die automatisch kunnen worden uitgevoerd wanneer 'Altijd goedkeuren uitvoerbewerkingen' is ingeschakeld", "commands.deniedCommands.description": "Commando-prefixen die automatisch worden geweigerd zonder om goedkeuring te vragen. Bij conflicten met toegestane commando's heeft de langste prefix-match voorrang. Voeg * toe om alle commando's te weigeren.", + "commands.commandExecutionTimeout.description": "Maximale tijd in seconden om te wachten tot commando-uitvoering voltooid is voordat er een timeout optreedt (0 = geen timeout, 1-600s, standaard: 0s)", "settings.vsCodeLmModelSelector.description": "Instellingen voor VSCode Language Model API", "settings.vsCodeLmModelSelector.vendor.description": "De leverancier van het taalmodel (bijv. copilot)", "settings.vsCodeLmModelSelector.family.description": "De familie van het taalmodel (bijv. gpt-4)", diff --git a/src/package.nls.pl.json b/src/package.nls.pl.json index de55dd1f219..62daaae24b3 100644 --- a/src/package.nls.pl.json +++ b/src/package.nls.pl.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Polecenia, które mogą być wykonywane automatycznie, gdy włączona jest opcja 'Zawsze zatwierdzaj operacje wykonania'", "commands.deniedCommands.description": "Prefiksy poleceń, które będą automatycznie odrzucane bez pytania o zatwierdzenie. W przypadku konfliktów z dozwolonymi poleceniami, najdłuższe dopasowanie prefiksu ma pierwszeństwo. Dodaj * aby odrzucić wszystkie polecenia.", + "commands.commandExecutionTimeout.description": "Maksymalny czas w sekundach oczekiwania na zakończenie wykonania polecenia przed przekroczeniem limitu czasu (0 = brak limitu czasu, 1-600s, domyślnie: 0s)", "settings.vsCodeLmModelSelector.description": "Ustawienia dla API modelu językowego VSCode", "settings.vsCodeLmModelSelector.vendor.description": "Dostawca modelu językowego (np. copilot)", "settings.vsCodeLmModelSelector.family.description": "Rodzina modelu językowego (np. gpt-4)", diff --git a/src/package.nls.pt-BR.json b/src/package.nls.pt-BR.json index 385e1d88ab8..7f3f7aece3c 100644 --- a/src/package.nls.pt-BR.json +++ b/src/package.nls.pt-BR.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Comandos que podem ser executados automaticamente quando 'Sempre aprovar operações de execução' está ativado", "commands.deniedCommands.description": "Prefixos de comandos que serão automaticamente negados sem solicitar aprovação. Em caso de conflitos com comandos permitidos, a correspondência de prefixo mais longa tem precedência. Adicione * para negar todos os comandos.", + "commands.commandExecutionTimeout.description": "Tempo máximo em segundos para aguardar a conclusão da execução do comando antes do timeout (0 = sem timeout, 1-600s, padrão: 0s)", "settings.vsCodeLmModelSelector.description": "Configurações para a API do modelo de linguagem do VSCode", "settings.vsCodeLmModelSelector.vendor.description": "O fornecedor do modelo de linguagem (ex: copilot)", "settings.vsCodeLmModelSelector.family.description": "A família do modelo de linguagem (ex: gpt-4)", diff --git a/src/package.nls.ru.json b/src/package.nls.ru.json index 7367eb46720..c1872a759e2 100644 --- a/src/package.nls.ru.json +++ b/src/package.nls.ru.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Команды, которые могут быть автоматически выполнены, когда включена опция 'Всегда подтверждать операции выполнения'", "commands.deniedCommands.description": "Префиксы команд, которые будут автоматически отклонены без запроса подтверждения. В случае конфликтов с разрешенными командами приоритет имеет самое длинное совпадение префикса. Добавьте * чтобы отклонить все команды.", + "commands.commandExecutionTimeout.description": "Максимальное время в секундах для ожидания завершения выполнения команды до истечения времени ожидания (0 = без тайм-аута, 1-600с, по умолчанию: 0с)", "settings.vsCodeLmModelSelector.description": "Настройки для VSCode Language Model API", "settings.vsCodeLmModelSelector.vendor.description": "Поставщик языковой модели (например, copilot)", "settings.vsCodeLmModelSelector.family.description": "Семейство языковой модели (например, gpt-4)", diff --git a/src/package.nls.tr.json b/src/package.nls.tr.json index d9c040c9fff..589ce619120 100644 --- a/src/package.nls.tr.json +++ b/src/package.nls.tr.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "'Her zaman yürütme işlemlerini onayla' etkinleştirildiğinde otomatik olarak yürütülebilen komutlar", "commands.deniedCommands.description": "Onay istenmeden otomatik olarak reddedilecek komut önekleri. İzin verilen komutlarla çakışma durumunda en uzun önek eşleşmesi öncelik alır. Tüm komutları reddetmek için * ekleyin.", + "commands.commandExecutionTimeout.description": "Komut yürütmesinin tamamlanmasını beklemek için maksimum süre (saniye), zaman aşımından önce (0 = zaman aşımı yok, 1-600s, varsayılan: 0s)", "settings.vsCodeLmModelSelector.description": "VSCode dil modeli API'si için ayarlar", "settings.vsCodeLmModelSelector.vendor.description": "Dil modelinin sağlayıcısı (örn: copilot)", "settings.vsCodeLmModelSelector.family.description": "Dil modelinin ailesi (örn: gpt-4)", diff --git a/src/package.nls.vi.json b/src/package.nls.vi.json index 8d3d76fc827..067738892d7 100644 --- a/src/package.nls.vi.json +++ b/src/package.nls.vi.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "Các lệnh có thể được thực thi tự động khi 'Luôn phê duyệt các thao tác thực thi' được bật", "commands.deniedCommands.description": "Các tiền tố lệnh sẽ được tự động từ chối mà không yêu cầu phê duyệt. Trong trường hợp xung đột với các lệnh được phép, việc khớp tiền tố dài nhất sẽ được ưu tiên. Thêm * để từ chối tất cả các lệnh.", + "commands.commandExecutionTimeout.description": "Thời gian tối đa tính bằng giây để chờ việc thực thi lệnh hoàn thành trước khi hết thời gian chờ (0 = không có thời gian chờ, 1-600s, mặc định: 0s)", "settings.vsCodeLmModelSelector.description": "Cài đặt cho API mô hình ngôn ngữ VSCode", "settings.vsCodeLmModelSelector.vendor.description": "Nhà cung cấp mô hình ngôn ngữ (ví dụ: copilot)", "settings.vsCodeLmModelSelector.family.description": "Họ mô hình ngôn ngữ (ví dụ: gpt-4)", diff --git a/src/package.nls.zh-CN.json b/src/package.nls.zh-CN.json index 91f36fb6012..3a69340f812 100644 --- a/src/package.nls.zh-CN.json +++ b/src/package.nls.zh-CN.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "当启用'始终批准执行操作'时可以自动执行的命令", "commands.deniedCommands.description": "将自动拒绝而无需请求批准的命令前缀。与允许命令冲突时,最长前缀匹配优先。添加 * 拒绝所有命令。", + "commands.commandExecutionTimeout.description": "等待命令执行完成的最大时间(秒),超时前(0 = 无超时,1-600秒,默认:0秒)", "settings.vsCodeLmModelSelector.description": "VSCode 语言模型 API 的设置", "settings.vsCodeLmModelSelector.vendor.description": "语言模型的供应商(例如:copilot)", "settings.vsCodeLmModelSelector.family.description": "语言模型的系列(例如:gpt-4)", diff --git a/src/package.nls.zh-TW.json b/src/package.nls.zh-TW.json index 6ab074bc4c1..d6314420f17 100644 --- a/src/package.nls.zh-TW.json +++ b/src/package.nls.zh-TW.json @@ -28,6 +28,7 @@ "configuration.title": "Roo Code", "commands.allowedCommands.description": "當啟用'始終批准執行操作'時可以自動執行的命令", "commands.deniedCommands.description": "將自動拒絕而無需請求批准的命令前綴。與允許命令衝突時,最長前綴匹配優先。新增 * 拒絕所有命令。", + "commands.commandExecutionTimeout.description": "等待命令執行完成的最大時間(秒),逾時前(0 = 無逾時,1-600秒,預設:0秒)", "settings.vsCodeLmModelSelector.description": "VSCode 語言模型 API 的設定", "settings.vsCodeLmModelSelector.vendor.description": "語言模型供應商(例如:copilot)", "settings.vsCodeLmModelSelector.family.description": "語言模型系列(例如:gpt-4)", From 21997e6d4c9337393d5df7222e9c330095b013b7 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Sun, 13 Jul 2025 16:00:19 -0400 Subject: [PATCH 06/11] Clearer error language --- .../executeCommandTimeout.integration.spec.ts | 20 ++++++++----------- src/core/tools/executeCommandTool.ts | 11 ++++------ 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts index 049783f3786..e351fff3957 100644 --- a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts +++ b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts @@ -64,8 +64,7 @@ describe("Command Execution Timeout Integration", () => { }) it("should pass timeout configuration to executeCommand", async () => { - const customTimeoutSeconds = 15 - const customTimeout = customTimeoutSeconds * 1000 // Convert to milliseconds for internal use + const customTimeout = 15000 const options: ExecuteCommandOptions = { executionId: "test-execution", command: "echo test", @@ -83,8 +82,7 @@ describe("Command Execution Timeout Integration", () => { }) it("should handle timeout scenario", async () => { - const shortTimeoutSeconds = 0.1 // Very short timeout in seconds - const shortTimeout = shortTimeoutSeconds * 1000 // Convert to milliseconds + const shortTimeout = 100 // Very short timeout const options: ExecuteCommandOptions = { executionId: "test-execution", command: "sleep 10", @@ -106,13 +104,12 @@ describe("Command Execution Timeout Integration", () => { // Should return timeout error expect(result[0]).toBe(false) // Not rejected by user - expect(result[1]).toContain("timed out") - expect(result[1]).toContain(`${shortTimeoutSeconds}s`) + expect(result[1]).toContain("terminated after exceeding") + expect(result[1]).toContain(`${shortTimeout}ms`) }, 10000) // Increase test timeout to 10 seconds it("should abort process on timeout", async () => { - const shortTimeoutSeconds = 0.05 - const shortTimeout = shortTimeoutSeconds * 1000 + const shortTimeout = 50 const options: ExecuteCommandOptions = { executionId: "test-execution", command: "sleep 10", @@ -135,11 +132,10 @@ describe("Command Execution Timeout Integration", () => { }, 5000) // Increase test timeout to 5 seconds it("should clean up timeout on successful completion", async () => { - const timeoutSeconds = 5 const options: ExecuteCommandOptions = { executionId: "test-execution", command: "echo test", - commandExecutionTimeout: timeoutSeconds * 1000, + commandExecutionTimeout: 5000, } // Mock a process that completes quickly @@ -150,7 +146,7 @@ describe("Command Execution Timeout Integration", () => { // Should complete successfully without timeout expect(result[0]).toBe(false) // Not rejected - expect(result[1]).not.toContain("timed out") + expect(result[1]).not.toContain("terminated after exceeding") }) it("should use default timeout when not specified (0 = no timeout)", async () => { @@ -187,6 +183,6 @@ describe("Command Execution Timeout Integration", () => { // Should complete successfully without timeout expect(result[0]).toBe(false) // Not rejected - expect(result[1]).not.toContain("timed out") + expect(result[1]).not.toContain("terminated after exceeding") }) }) diff --git a/src/core/tools/executeCommandTool.ts b/src/core/tools/executeCommandTool.ts index ba960f4aa68..96766c49317 100644 --- a/src/core/tools/executeCommandTool.ts +++ b/src/core/tools/executeCommandTool.ts @@ -64,14 +64,11 @@ export async function executeCommandTool( const clineProviderState = await clineProvider?.getState() const { terminalOutputLineLimit = 500, terminalShellIntegrationDisabled = false } = clineProviderState ?? {} - // Get command execution timeout from VSCode configuration (in seconds) - const commandExecutionTimeoutSeconds = vscode.workspace + // Get command execution timeout from VSCode configuration + const commandExecutionTimeout = vscode.workspace .getConfiguration(Package.name) .get("commandExecutionTimeout", 0) - // Convert seconds to milliseconds for internal use - const commandExecutionTimeout = commandExecutionTimeoutSeconds * 1000 - const options: ExecuteCommandOptions = { executionId, command, @@ -236,7 +233,7 @@ export async function executeCommand( if (cline.terminalProcess) { cline.terminalProcess.abort() } - reject(new Error(`Command execution timed out after ${commandExecutionTimeout / 1000}s`)) + reject(new Error(`Command execution timed out after ${commandExecutionTimeout}ms`)) }, commandExecutionTimeout) }) @@ -252,7 +249,7 @@ export async function executeCommand( return [ false, - `Command execution timed out after ${commandExecutionTimeout / 1000}s. The command was terminated.`, + `The command was terminated after exceeding a user-configured ${commandExecutionTimeout}ms timeout. Do not try to re-run the command.`, ] } throw error From 8a7147cd80dc13101d62dc56dacf141b5fd7409b Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Sun, 13 Jul 2025 16:04:34 -0400 Subject: [PATCH 07/11] fix: update command timeout to use seconds configuration - Read commandExecutionTimeout from VSCode config in seconds - Convert to milliseconds internally for timeout logic - Display timeout in seconds in error messages - Update integration tests to expect seconds format --- .../executeCommandTimeout.integration.spec.ts | 14 +++++++------- src/core/tools/executeCommandTool.ts | 11 ++++++++--- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts index e351fff3957..098f84c287b 100644 --- a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts +++ b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts @@ -64,11 +64,11 @@ describe("Command Execution Timeout Integration", () => { }) it("should pass timeout configuration to executeCommand", async () => { - const customTimeout = 15000 + const customTimeoutMs = 15000 // 15 seconds in milliseconds const options: ExecuteCommandOptions = { executionId: "test-execution", command: "echo test", - commandExecutionTimeout: customTimeout, + commandExecutionTimeout: customTimeoutMs, } // Mock a quick-completing process @@ -82,11 +82,11 @@ describe("Command Execution Timeout Integration", () => { }) it("should handle timeout scenario", async () => { - const shortTimeout = 100 // Very short timeout + const shortTimeoutMs = 100 // Very short timeout in milliseconds const options: ExecuteCommandOptions = { executionId: "test-execution", command: "sleep 10", - commandExecutionTimeout: shortTimeout, + commandExecutionTimeout: shortTimeoutMs, } // Create a process that never resolves but has an abort method @@ -105,15 +105,15 @@ describe("Command Execution Timeout Integration", () => { // Should return timeout error expect(result[0]).toBe(false) // Not rejected by user expect(result[1]).toContain("terminated after exceeding") - expect(result[1]).toContain(`${shortTimeout}ms`) + expect(result[1]).toContain("0.1s") // Should show seconds in error message }, 10000) // Increase test timeout to 10 seconds it("should abort process on timeout", async () => { - const shortTimeout = 50 + const shortTimeoutMs = 50 // Short timeout in milliseconds const options: ExecuteCommandOptions = { executionId: "test-execution", command: "sleep 10", - commandExecutionTimeout: shortTimeout, + commandExecutionTimeout: shortTimeoutMs, } // Create a process that can be aborted diff --git a/src/core/tools/executeCommandTool.ts b/src/core/tools/executeCommandTool.ts index 96766c49317..997e20428aa 100644 --- a/src/core/tools/executeCommandTool.ts +++ b/src/core/tools/executeCommandTool.ts @@ -64,11 +64,14 @@ export async function executeCommandTool( const clineProviderState = await clineProvider?.getState() const { terminalOutputLineLimit = 500, terminalShellIntegrationDisabled = false } = clineProviderState ?? {} - // Get command execution timeout from VSCode configuration - const commandExecutionTimeout = vscode.workspace + // Get command execution timeout from VSCode configuration (in seconds) + const commandExecutionTimeoutSeconds = vscode.workspace .getConfiguration(Package.name) .get("commandExecutionTimeout", 0) + // Convert seconds to milliseconds for internal use + const commandExecutionTimeout = commandExecutionTimeoutSeconds * 1000 + const options: ExecuteCommandOptions = { executionId, command, @@ -135,6 +138,8 @@ export async function executeCommand( commandExecutionTimeout = 0, }: ExecuteCommandOptions, ): Promise<[boolean, ToolResponse]> { + // Convert milliseconds back to seconds for display purposes + const commandExecutionTimeoutSeconds = commandExecutionTimeout / 1000 let workingDir: string if (!customCwd) { @@ -249,7 +254,7 @@ export async function executeCommand( return [ false, - `The command was terminated after exceeding a user-configured ${commandExecutionTimeout}ms timeout. Do not try to re-run the command.`, + `The command was terminated after exceeding a user-configured ${commandExecutionTimeoutSeconds}s timeout. Do not try to re-run the command.`, ] } throw error From 224c366e81ffc461f145d8c581dd35461306debb Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Mon, 14 Jul 2025 08:59:06 -0500 Subject: [PATCH 08/11] feat: add visual feedback for command execution timeout --- src/core/tools/executeCommandTool.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/tools/executeCommandTool.ts b/src/core/tools/executeCommandTool.ts index 997e20428aa..41d2d8943c5 100644 --- a/src/core/tools/executeCommandTool.ts +++ b/src/core/tools/executeCommandTool.ts @@ -250,6 +250,9 @@ export async function executeCommand( const status: CommandExecutionStatus = { executionId, status: "timeout" } clineProvider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) }) + // Add visual feedback for timeout + await cline.say("text", `Command execution timed out after ${commandExecutionTimeoutSeconds} seconds`) + cline.terminalProcess = undefined return [ From c6d798a4f599d3e2d8d2f4189c0df21d77fe7069 Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Mon, 14 Jul 2025 09:01:06 -0500 Subject: [PATCH 09/11] feat: add visual feedback when command execution timeout is reached --- .../tools/__tests__/executeCommandTimeout.integration.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts index 098f84c287b..de98c9df209 100644 --- a/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts +++ b/src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts @@ -38,6 +38,7 @@ describe("Command Execution Timeout Integration", () => { postMessageToWebview: vitest.fn(), }), }, + say: vitest.fn().mockResolvedValue(undefined), } // Mock terminal process From 680c783a591c9bd8a20b2d6059126bb2ea50bb92 Mon Sep 17 00:00:00 2001 From: Daniel Riccio Date: Mon, 14 Jul 2025 09:06:51 -0500 Subject: [PATCH 10/11] feat: add internationalized visual feedback for command timeout --- src/core/tools/executeCommandTool.ts | 3 ++- src/i18n/locales/ca/common.json | 1 + src/i18n/locales/de/common.json | 1 + src/i18n/locales/en/common.json | 1 + src/i18n/locales/es/common.json | 1 + src/i18n/locales/fr/common.json | 1 + src/i18n/locales/hi/common.json | 1 + src/i18n/locales/id/common.json | 1 + src/i18n/locales/it/common.json | 1 + src/i18n/locales/ja/common.json | 1 + src/i18n/locales/ko/common.json | 1 + src/i18n/locales/nl/common.json | 1 + src/i18n/locales/pl/common.json | 1 + src/i18n/locales/pt-BR/common.json | 1 + src/i18n/locales/ru/common.json | 1 + src/i18n/locales/tr/common.json | 1 + src/i18n/locales/vi/common.json | 1 + src/i18n/locales/zh-CN/common.json | 1 + src/i18n/locales/zh-TW/common.json | 1 + 19 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/core/tools/executeCommandTool.ts b/src/core/tools/executeCommandTool.ts index 41d2d8943c5..ef1b2fc7a36 100644 --- a/src/core/tools/executeCommandTool.ts +++ b/src/core/tools/executeCommandTool.ts @@ -16,6 +16,7 @@ import { ExitCodeDetails, RooTerminalCallbacks, RooTerminalProcess } from "../.. import { TerminalRegistry } from "../../integrations/terminal/TerminalRegistry" import { Terminal } from "../../integrations/terminal/Terminal" import { Package } from "../../shared/package" +import { t } from "../../i18n" class ShellIntegrationError extends Error {} @@ -251,7 +252,7 @@ export async function executeCommand( clineProvider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) }) // Add visual feedback for timeout - await cline.say("text", `Command execution timed out after ${commandExecutionTimeoutSeconds} seconds`) + await cline.say("text", t("common:command_timeout", { seconds: commandExecutionTimeoutSeconds })) cline.terminalProcess = undefined diff --git a/src/i18n/locales/ca/common.json b/src/i18n/locales/ca/common.json index 0caa3fca47e..7dac4d7431b 100644 --- a/src/i18n/locales/ca/common.json +++ b/src/i18n/locales/ca/common.json @@ -71,6 +71,7 @@ "url_page_not_found": "No s'ha trobat la pàgina. Comprova si la URL és correcta.", "url_fetch_failed": "Error en obtenir el contingut de la URL: {{error}}", "url_fetch_error_with_url": "Error en obtenir contingut per {{url}}: {{error}}", + "command_timeout": "L'execució de la comanda ha superat el temps d'espera de {{seconds}} segons", "share_task_failed": "Ha fallat compartir la tasca. Si us plau, torna-ho a provar.", "share_no_active_task": "No hi ha cap tasca activa per compartir", "share_auth_required": "Es requereix autenticació. Si us plau, inicia sessió per compartir tasques.", diff --git a/src/i18n/locales/de/common.json b/src/i18n/locales/de/common.json index bf9af547cae..db9ba9b51ce 100644 --- a/src/i18n/locales/de/common.json +++ b/src/i18n/locales/de/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "Die Seite wurde nicht gefunden. Bitte prüfe, ob die URL korrekt ist.", "url_fetch_failed": "Fehler beim Abrufen des URL-Inhalts: {{error}}", "url_fetch_error_with_url": "Fehler beim Abrufen des Inhalts für {{url}}: {{error}}", + "command_timeout": "Zeitüberschreitung bei der Befehlsausführung nach {{seconds}} Sekunden", "share_task_failed": "Teilen der Aufgabe fehlgeschlagen. Bitte versuche es erneut.", "share_no_active_task": "Keine aktive Aufgabe zum Teilen", "share_auth_required": "Authentifizierung erforderlich. Bitte melde dich an, um Aufgaben zu teilen.", diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index 3004038d421..84d37985198 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "The page was not found. Please check if the URL is correct.", "url_fetch_failed": "Failed to fetch URL content: {{error}}", "url_fetch_error_with_url": "Error fetching content for {{url}}: {{error}}", + "command_timeout": "Command execution timed out after {{seconds}} seconds", "share_task_failed": "Failed to share task. Please try again.", "share_no_active_task": "No active task to share", "share_auth_required": "Authentication required. Please sign in to share tasks.", diff --git a/src/i18n/locales/es/common.json b/src/i18n/locales/es/common.json index 1a16dbf1ae4..cdd26831a57 100644 --- a/src/i18n/locales/es/common.json +++ b/src/i18n/locales/es/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "La página no fue encontrada. Por favor verifica si la URL es correcta.", "url_fetch_failed": "Error al obtener el contenido de la URL: {{error}}", "url_fetch_error_with_url": "Error al obtener contenido para {{url}}: {{error}}", + "command_timeout": "La ejecución del comando superó el tiempo de espera de {{seconds}} segundos", "share_task_failed": "Error al compartir la tarea. Por favor, inténtalo de nuevo.", "share_no_active_task": "No hay tarea activa para compartir", "share_auth_required": "Se requiere autenticación. Por favor, inicia sesión para compartir tareas.", diff --git a/src/i18n/locales/fr/common.json b/src/i18n/locales/fr/common.json index 98945f305dc..3ddacdda593 100644 --- a/src/i18n/locales/fr/common.json +++ b/src/i18n/locales/fr/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "La page n'a pas été trouvée. Vérifie si l'URL est correcte.", "url_fetch_failed": "Échec de récupération du contenu de l'URL : {{error}}", "url_fetch_error_with_url": "Erreur lors de la récupération du contenu pour {{url}} : {{error}}", + "command_timeout": "L'exécution de la commande a expiré après {{seconds}} secondes", "share_task_failed": "Échec du partage de la tâche. Veuillez réessayer.", "share_no_active_task": "Aucune tâche active à partager", "share_auth_required": "Authentification requise. Veuillez vous connecter pour partager des tâches.", diff --git a/src/i18n/locales/hi/common.json b/src/i18n/locales/hi/common.json index 7daa0046ec2..86374268460 100644 --- a/src/i18n/locales/hi/common.json +++ b/src/i18n/locales/hi/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "पेज नहीं मिला। कृपया जांचें कि URL सही है।", "url_fetch_failed": "URL सामग्री प्राप्त करने में त्रुटि: {{error}}", "url_fetch_error_with_url": "{{url}} के लिए सामग्री प्राप्त करने में त्रुटि: {{error}}", + "command_timeout": "कमांड निष्पादन {{seconds}} सेकंड के बाद समय समाप्त हो गया", "share_task_failed": "कार्य साझा करने में विफल। कृपया पुनः प्रयास करें।", "share_no_active_task": "साझा करने के लिए कोई सक्रिय कार्य नहीं", "share_auth_required": "प्रमाणीकरण आवश्यक है। कार्य साझा करने के लिए कृपया साइन इन करें।", diff --git a/src/i18n/locales/id/common.json b/src/i18n/locales/id/common.json index c021dab4cda..1e8f9dbbbdd 100644 --- a/src/i18n/locales/id/common.json +++ b/src/i18n/locales/id/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "Halaman tidak ditemukan. Silakan periksa apakah URL sudah benar.", "url_fetch_failed": "Gagal mengambil konten URL: {{error}}", "url_fetch_error_with_url": "Error mengambil konten untuk {{url}}: {{error}}", + "command_timeout": "Eksekusi perintah timed out setelah {{seconds}} detik", "share_task_failed": "Gagal membagikan tugas. Silakan coba lagi.", "share_no_active_task": "Tidak ada tugas aktif untuk dibagikan", "share_auth_required": "Autentikasi diperlukan. Silakan masuk untuk berbagi tugas.", diff --git a/src/i18n/locales/it/common.json b/src/i18n/locales/it/common.json index ff45cd8f1ec..d12e376c0c7 100644 --- a/src/i18n/locales/it/common.json +++ b/src/i18n/locales/it/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "La pagina non è stata trovata. Verifica se l'URL è corretto.", "url_fetch_failed": "Errore nel recupero del contenuto URL: {{error}}", "url_fetch_error_with_url": "Errore nel recupero del contenuto per {{url}}: {{error}}", + "command_timeout": "Esecuzione del comando scaduta dopo {{seconds}} secondi", "share_task_failed": "Condivisione dell'attività fallita. Riprova.", "share_no_active_task": "Nessuna attività attiva da condividere", "share_auth_required": "Autenticazione richiesta. Accedi per condividere le attività.", diff --git a/src/i18n/locales/ja/common.json b/src/i18n/locales/ja/common.json index 4d9b88d114d..56be64c44c8 100644 --- a/src/i18n/locales/ja/common.json +++ b/src/i18n/locales/ja/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "ページが見つかりませんでした。URLが正しいか確認してください。", "url_fetch_failed": "URLコンテンツの取得に失敗しました:{{error}}", "url_fetch_error_with_url": "{{url}} のコンテンツ取得エラー:{{error}}", + "command_timeout": "コマンドの実行が{{seconds}}秒後にタイムアウトしました", "share_task_failed": "タスクの共有に失敗しました", "share_no_active_task": "共有するアクティブなタスクがありません", "share_auth_required": "認証が必要です。タスクを共有するにはサインインしてください。", diff --git a/src/i18n/locales/ko/common.json b/src/i18n/locales/ko/common.json index 34d9bced71e..0b12455c0f2 100644 --- a/src/i18n/locales/ko/common.json +++ b/src/i18n/locales/ko/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "페이지를 찾을 수 없습니다. URL이 올바른지 확인해 주세요.", "url_fetch_failed": "URL 콘텐츠 가져오기 실패: {{error}}", "url_fetch_error_with_url": "{{url}} 콘텐츠 가져오기 오류: {{error}}", + "command_timeout": "명령 실행 시간이 {{seconds}}초 후 초과되었습니다", "share_task_failed": "작업 공유에 실패했습니다", "share_no_active_task": "공유할 활성 작업이 없습니다", "share_auth_required": "인증이 필요합니다. 작업을 공유하려면 로그인하세요.", diff --git a/src/i18n/locales/nl/common.json b/src/i18n/locales/nl/common.json index dff1bb83f76..43fda70dc23 100644 --- a/src/i18n/locales/nl/common.json +++ b/src/i18n/locales/nl/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "De pagina werd niet gevonden. Controleer of de URL correct is.", "url_fetch_failed": "Fout bij ophalen van URL-inhoud: {{error}}", "url_fetch_error_with_url": "Fout bij ophalen van inhoud voor {{url}}: {{error}}", + "command_timeout": "Time-out bij uitvoeren van commando na {{seconds}} seconden", "share_task_failed": "Delen van taak mislukt", "share_no_active_task": "Geen actieve taak om te delen", "share_auth_required": "Authenticatie vereist. Log in om taken te delen.", diff --git a/src/i18n/locales/pl/common.json b/src/i18n/locales/pl/common.json index 33c58b47527..80a299c7df2 100644 --- a/src/i18n/locales/pl/common.json +++ b/src/i18n/locales/pl/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "Strona nie została znaleziona. Sprawdź, czy URL jest poprawny.", "url_fetch_failed": "Błąd pobierania zawartości URL: {{error}}", "url_fetch_error_with_url": "Błąd pobierania zawartości dla {{url}}: {{error}}", + "command_timeout": "Przekroczono limit czasu wykonania polecenia po {{seconds}} sekundach", "share_task_failed": "Nie udało się udostępnić zadania", "share_no_active_task": "Brak aktywnego zadania do udostępnienia", "share_auth_required": "Wymagana autoryzacja. Zaloguj się, aby udostępniać zadania.", diff --git a/src/i18n/locales/pt-BR/common.json b/src/i18n/locales/pt-BR/common.json index ce9dc113e2d..6205a5fb7aa 100644 --- a/src/i18n/locales/pt-BR/common.json +++ b/src/i18n/locales/pt-BR/common.json @@ -71,6 +71,7 @@ "url_page_not_found": "A página não foi encontrada. Verifique se a URL está correta.", "url_fetch_failed": "Falha ao buscar conteúdo da URL: {{error}}", "url_fetch_error_with_url": "Erro ao buscar conteúdo para {{url}}: {{error}}", + "command_timeout": "A execução do comando excedeu o tempo limite após {{seconds}} segundos", "share_task_failed": "Falha ao compartilhar tarefa", "share_no_active_task": "Nenhuma tarefa ativa para compartilhar", "share_auth_required": "Autenticação necessária. Faça login para compartilhar tarefas.", diff --git a/src/i18n/locales/ru/common.json b/src/i18n/locales/ru/common.json index a3b6c322b26..f537d1a2d37 100644 --- a/src/i18n/locales/ru/common.json +++ b/src/i18n/locales/ru/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "Страница не найдена. Проверь правильность URL.", "url_fetch_failed": "Ошибка получения содержимого URL: {{error}}", "url_fetch_error_with_url": "Ошибка получения содержимого для {{url}}: {{error}}", + "command_timeout": "Время выполнения команды истекло через {{seconds}} секунд", "share_task_failed": "Не удалось поделиться задачей", "share_no_active_task": "Нет активной задачи для совместного использования", "share_auth_required": "Требуется аутентификация. Войдите в систему для совместного доступа к задачам.", diff --git a/src/i18n/locales/tr/common.json b/src/i18n/locales/tr/common.json index 042fa88d15a..61e244186ec 100644 --- a/src/i18n/locales/tr/common.json +++ b/src/i18n/locales/tr/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "Sayfa bulunamadı. URL'nin doğru olup olmadığını kontrol et.", "url_fetch_failed": "URL içeriği getirme hatası: {{error}}", "url_fetch_error_with_url": "{{url}} için içerik getirme hatası: {{error}}", + "command_timeout": "Komut çalıştırma {{seconds}} saniye sonra zaman aşımına uğradı", "share_task_failed": "Görev paylaşılamadı", "share_no_active_task": "Paylaşılacak aktif görev yok", "share_auth_required": "Kimlik doğrulama gerekli. Görevleri paylaşmak için lütfen giriş yapın.", diff --git a/src/i18n/locales/vi/common.json b/src/i18n/locales/vi/common.json index 183ae7b41af..6106f71fa0e 100644 --- a/src/i18n/locales/vi/common.json +++ b/src/i18n/locales/vi/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "Không tìm thấy trang. Vui lòng kiểm tra URL có đúng không.", "url_fetch_failed": "Lỗi lấy nội dung URL: {{error}}", "url_fetch_error_with_url": "Lỗi lấy nội dung cho {{url}}: {{error}}", + "command_timeout": "Thực thi lệnh đã hết thời gian chờ sau {{seconds}} giây", "share_task_failed": "Không thể chia sẻ nhiệm vụ", "share_no_active_task": "Không có nhiệm vụ hoạt động để chia sẻ", "share_auth_required": "Cần xác thực. Vui lòng đăng nhập để chia sẻ nhiệm vụ.", diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json index a45efa4b1c6..a629ba65071 100644 --- a/src/i18n/locales/zh-CN/common.json +++ b/src/i18n/locales/zh-CN/common.json @@ -72,6 +72,7 @@ "url_page_not_found": "页面未找到。请检查 URL 是否正确。", "url_fetch_failed": "获取 URL 内容失败:{{error}}", "url_fetch_error_with_url": "获取 {{url}} 内容时出错:{{error}}", + "command_timeout": "命令执行超时,{{seconds}} 秒后", "share_task_failed": "分享任务失败。请重试。", "share_no_active_task": "没有活跃任务可分享", "share_auth_required": "需要身份验证。请登录以分享任务。", diff --git a/src/i18n/locales/zh-TW/common.json b/src/i18n/locales/zh-TW/common.json index 3fbbc050f4b..48a37c1438d 100644 --- a/src/i18n/locales/zh-TW/common.json +++ b/src/i18n/locales/zh-TW/common.json @@ -67,6 +67,7 @@ "url_page_not_found": "找不到頁面。請檢查 URL 是否正確。", "url_fetch_failed": "取得 URL 內容失敗:{{error}}", "url_fetch_error_with_url": "取得 {{url}} 內容時發生錯誤:{{error}}", + "command_timeout": "命令執行超時,{{seconds}} 秒後", "share_task_failed": "分享工作失敗。請重試。", "share_no_active_task": "沒有活躍的工作可分享", "share_auth_required": "需要身份驗證。請登入以分享工作。", From dcca042a0aaa6206c2384348a0add71f6a601592 Mon Sep 17 00:00:00 2001 From: Daniel <57051444+daniel-lxs@users.noreply.github.com> Date: Mon, 14 Jul 2025 09:19:01 -0500 Subject: [PATCH 11/11] Update src/i18n/locales/id/common.json Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> --- src/i18n/locales/id/common.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/locales/id/common.json b/src/i18n/locales/id/common.json index 1e8f9dbbbdd..df3fe2cefbe 100644 --- a/src/i18n/locales/id/common.json +++ b/src/i18n/locales/id/common.json @@ -67,7 +67,7 @@ "url_page_not_found": "Halaman tidak ditemukan. Silakan periksa apakah URL sudah benar.", "url_fetch_failed": "Gagal mengambil konten URL: {{error}}", "url_fetch_error_with_url": "Error mengambil konten untuk {{url}}: {{error}}", - "command_timeout": "Eksekusi perintah timed out setelah {{seconds}} detik", + "command_timeout": "Eksekusi perintah waktu habis setelah {{seconds}} detik", "share_task_failed": "Gagal membagikan tugas. Silakan coba lagi.", "share_no_active_task": "Tidak ada tugas aktif untuk dibagikan", "share_auth_required": "Autentikasi diperlukan. Silakan masuk untuk berbagi tugas.",