fix(cli): ignore model-provided timeout in CLI runtime (#11835)

In CLI runtime, stdin harnesses expect command lifetime to be governed
solely by commandExecutionTimeout (user setting), not model-provided
background timeouts. Extract resolveAgentTimeoutMs() and return 0 when
ROO_CLI_RUNTIME=1.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Chris Estreich 2026-03-02 13:25:31 -08:00 committed by GitHub
parent 941e6de743
commit 7ea91fa79e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 25 additions and 1 deletions

View file

@ -29,6 +29,15 @@ interface ExecuteCommandParams {
timeout?: number | null
}
export function resolveAgentTimeoutMs(timeoutSeconds: number | null | undefined): number {
const requestedAgentTimeout = typeof timeoutSeconds === "number" && timeoutSeconds > 0 ? timeoutSeconds * 1000 : 0
// In CLI runtime, stdin harnesses expect command lifetime to be governed
// solely by commandExecutionTimeout (user setting), not model-provided
// background timeouts.
return process.env.ROO_CLI_RUNTIME === "1" ? 0 : requestedAgentTimeout
}
export class ExecuteCommandTool extends BaseTool<"execute_command"> {
readonly name = "execute_command" as const
@ -87,7 +96,7 @@ export class ExecuteCommandTool extends BaseTool<"execute_command"> {
const commandExecutionTimeout = isCommandAllowlisted ? 0 : commandExecutionTimeoutSeconds * 1000
// Convert agent-specified timeout from seconds to milliseconds
const agentTimeout = typeof timeoutSeconds === "number" && timeoutSeconds > 0 ? timeoutSeconds * 1000 : 0
const agentTimeout = resolveAgentTimeoutMs(timeoutSeconds)
const options: ExecuteCommandOptions = {
executionId,

View file

@ -48,6 +48,7 @@ describe("executeCommandTool", () => {
let mockHandleError: any
let mockPushToolResult: any
let mockToolUse: ToolUse<"execute_command">
const originalCliRuntime = process.env.ROO_CLI_RUNTIME
beforeEach(() => {
// Reset mocks
@ -106,6 +107,10 @@ describe("executeCommandTool", () => {
}
})
afterEach(() => {
process.env.ROO_CLI_RUNTIME = originalCliRuntime
})
/**
* Tests for HTML entity unescaping in commands
* This verifies that HTML entities are properly converted to their actual characters
@ -285,5 +290,15 @@ describe("executeCommandTool", () => {
expect(mockOptions.command).toBeDefined()
expect(mockOptions.commandExecutionTimeout).toBeDefined()
})
it("should ignore model timeout in CLI runtime", () => {
process.env.ROO_CLI_RUNTIME = "1"
expect(executeCommandModule.resolveAgentTimeoutMs(30)).toBe(0)
})
it("should honor model timeout outside CLI runtime", () => {
delete process.env.ROO_CLI_RUNTIME
expect(executeCommandModule.resolveAgentTimeoutMs(30)).toBe(30_000)
})
})
})