diff --git a/scripts/src/agentrun-events-long-poll.test.ts b/scripts/src/agentrun-events-long-poll.test.ts index 9b421f2f..97046357 100644 --- a/scripts/src/agentrun-events-long-poll.test.ts +++ b/scripts/src/agentrun-events-long-poll.test.ts @@ -164,7 +164,7 @@ describe.serial("AgentRun events manager-held long polling", () => { }, async () => { const invalid = await runAgentRunCommand(null, ["events", `run/${RUN_ID}`, "--expect", "2", "--timeout", "3minutes", "-o", "json"]); expect(invalid.ok).toBe(false); - expect(renderedText(invalid)).toContain("--timeout must use an integer duration"); + expect(renderedText(invalid)).toContain("--timeout must use a positive integer duration with ms, s, or m units"); expect(requests).toBe(0); const failed = await runAgentRunCommand(null, ["events", `run/${RUN_ID}`, "--expect", "2", "--timeout", "1s", "-o", "json"]); @@ -182,4 +182,24 @@ describe.serial("AgentRun events manager-held long polling", () => { expect(renderedText(result)).toContain("must include boolean timedOut and non-negative observed fields"); }); }); + + test("accepts 60m and rejects zero, values above 60m, and hour units before request", async () => { + let requests = 0; + await withManager((request) => { + requests += 1; + const url = new URL(request.url); + expect(url.searchParams.get("timeoutMs")).toBe("3600000"); + return Response.json({ ok: true, data: { items: [], timedOut: true, observed: 0, nextAfterSeq: 0, completionReason: "timeout" } }); + }, async () => { + const accepted = await runAgentRunCommand(null, ["events", `run/${RUN_ID}`, "--expect", "1", "--timeout", "60m", "-o", "json"]); + expect(accepted.ok).toBe(true); + expect(requests).toBe(1); + + for (const invalidDuration of ["0ms", "61m", "1h"]) { + const invalid = await runAgentRunCommand(null, ["events", `run/${RUN_ID}`, "--expect", "1", "--timeout", invalidDuration, "-o", "json"]); + expect(invalid.ok).toBe(false); + } + expect(requests).toBe(1); + }); + }); }); diff --git a/scripts/src/agentrun/resource-actions.ts b/scripts/src/agentrun/resource-actions.ts index ac0458e1..3bcf360f 100644 --- a/scripts/src/agentrun/resource-actions.ts +++ b/scripts/src/agentrun/resource-actions.ts @@ -360,12 +360,12 @@ function parsePositiveInt(raw: string | null, flag: string): number { export function parseDurationMs(raw: string | null, flag: string): number { if (raw === null || raw.length === 0) throw new Error(`${flag} requires a duration`); - const match = /^(\d+)(ms|s|m|h)$/u.exec(raw.trim()); - if (match === null) throw new Error(`${flag} must use an integer duration such as 500ms, 120s, 3m, or 1h`); + const match = /^(\d+)(ms|s|m)$/u.exec(raw.trim()); + if (match === null) throw new Error(`${flag} must use a positive integer duration with ms, s, or m units, such as 500ms, 120s, or 3m`); const amount = Number(match[1]); - const multiplier = match[2] === "ms" ? 1 : match[2] === "s" ? 1_000 : match[2] === "m" ? 60_000 : 3_600_000; + const multiplier = match[2] === "ms" ? 1 : match[2] === "s" ? 1_000 : 60_000; const value = amount * multiplier; - if (!Number.isSafeInteger(value) || value < 1 || value > 86_400_000) throw new Error(`${flag} must be between 1ms and 24h`); + if (!Number.isSafeInteger(value) || value < 1 || value > 3_600_000) throw new Error(`${flag} must be between 1ms and 60m`); return value; }