refactor: centralize exec approval timeout

This commit is contained in:
Peter Steinberger
2026-02-15 01:10:18 +01:00
parent 27eef96380
commit ea0ef18704
5 changed files with 69 additions and 42 deletions

View File

@@ -5,6 +5,7 @@ import { resolveAgentConfig, resolveDefaultAgentId } from "../../agents/agent-sc
import { loadConfig } from "../../config/config.js";
import { randomIdempotencyKey } from "../../gateway/call.js";
import {
DEFAULT_EXEC_APPROVAL_TIMEOUT_MS,
type ExecApprovalsFile,
type ExecAsk,
type ExecSecurity,
@@ -272,30 +273,33 @@ export function registerNodesInvokeCommands(nodes: Command) {
let approvalId: string | null = null;
if (requiresAsk) {
approvalId = crypto.randomUUID();
const approvalTimeoutMs = 120_000;
const approvalTimeoutMs = DEFAULT_EXEC_APPROVAL_TIMEOUT_MS;
// The CLI transport timeout (opts.timeout) must be longer than the
// gateway-side approval wait so the connection stays alive while the
// user decides. Without this override the default 35 s transport
// timeout races — and always loses — against the 120 s approval
// timeout, causing "gateway timeout after 35000ms" (#12098).
const approvalOpts = {
...opts,
timeout: String(
Math.max(parseTimeoutMs(opts.timeout) ?? 0, approvalTimeoutMs + 10_000),
),
};
const decisionResult = (await callGatewayCli("exec.approval.request", approvalOpts, {
id: approvalId,
command: rawCommand ?? argv.join(" "),
cwd: opts.cwd,
host: "node",
security: hostSecurity,
ask: hostAsk,
agentId,
resolvedPath: undefined,
sessionKey: undefined,
timeoutMs: approvalTimeoutMs,
})) as { decision?: string } | null;
const transportTimeoutMs = Math.max(
parseTimeoutMs(opts.timeout) ?? 0,
approvalTimeoutMs + 10_000,
);
const decisionResult = (await callGatewayCli(
"exec.approval.request",
opts,
{
id: approvalId,
command: rawCommand ?? argv.join(" "),
cwd: opts.cwd,
host: "node",
security: hostSecurity,
ask: hostAsk,
agentId,
resolvedPath: undefined,
sessionKey: undefined,
timeoutMs: approvalTimeoutMs,
},
{ transportTimeoutMs },
)) as { decision?: string } | null;
const decision =
decisionResult && typeof decisionResult === "object"
? (decisionResult.decision ?? null)