diff --git a/src/agents/bash-tools.exec-runtime.test.ts b/src/agents/bash-tools.exec-runtime.test.ts index 962d0139fee..54ff1ee05bb 100644 --- a/src/agents/bash-tools.exec-runtime.test.ts +++ b/src/agents/bash-tools.exec-runtime.test.ts @@ -323,6 +323,7 @@ describe("emitExecSystemEvent", () => { }); expect(requestHeartbeatNowMock).toHaveBeenCalledWith( expect.objectContaining({ + coalesceMs: 0, reason: "exec-event", sessionKey: "agent:ops:main", }), @@ -341,6 +342,7 @@ describe("emitExecSystemEvent", () => { }); expect(requestHeartbeatNowMock).toHaveBeenCalledWith( expect.objectContaining({ + coalesceMs: 0, reason: "exec-event", }), ); diff --git a/src/agents/bash-tools.exec.approval-id.test.ts b/src/agents/bash-tools.exec.approval-id.test.ts index 337191b5e48..d045a24efa2 100644 --- a/src/agents/bash-tools.exec.approval-id.test.ts +++ b/src/agents/bash-tools.exec.approval-id.test.ts @@ -305,7 +305,7 @@ describe("exec approvals", () => { await expect .poll(() => (invokeParams as { params?: { runId?: string } } | undefined)?.params?.runId, { timeout: 2000, - interval: 20, + interval: 1, }) .toBe(approvalId); expect( @@ -313,7 +313,7 @@ describe("exec approvals", () => { ).toMatchObject({ suppressNotifyOnExit: true, }); - await expect.poll(() => agentParams, { timeout: 2_000, interval: 20 }).toBeTruthy(); + await expect.poll(() => agentParams, { timeout: 2_000, interval: 1 }).toBeTruthy(); }); it("skips approval when node allowlist is satisfied", async () => { @@ -768,7 +768,7 @@ describe("exec approvals", () => { }); expect(result.details.status).toBe("approval-pending"); - await expect.poll(() => agentCalls.length, { timeout: 3_000, interval: 20 }).toBe(1); + await expect.poll(() => agentCalls.length, { timeout: 3_000, interval: 1 }).toBe(1); expect(agentCalls[0]).toEqual( expect.objectContaining({ sessionKey: "agent:main:main", @@ -809,7 +809,7 @@ describe("exec approvals", () => { }); expect(result.details.status).toBe("approval-pending"); - await expect.poll(() => agentCalls.length, { timeout: 3_000, interval: 20 }).toBe(1); + await expect.poll(() => agentCalls.length, { timeout: 3_000, interval: 1 }).toBe(1); expect(agentCalls[0]).toEqual( expect.objectContaining({ sessionKey: "agent:main:discord:channel:123", @@ -887,7 +887,7 @@ describe("exec approvals", () => { resolveDecision?.({ decision: "allow-once" }); - await expect.poll(() => agentCalls.length, { timeout: 3_000, interval: 20 }).toBe(1); + await expect.poll(() => agentCalls.length, { timeout: 3_000, interval: 1 }).toBe(1); expect(agentCalls[0]).toEqual( expect.objectContaining({ sessionKey: "agent:main:discord:channel:123", @@ -945,7 +945,7 @@ describe("exec approvals", () => { expect(result.details.status).toBe("approval-pending"); - await expect.poll(() => agentCalls.length, { timeout: 3_000, interval: 20 }).toBe(1); + await expect.poll(() => agentCalls.length, { timeout: 3_000, interval: 1 }).toBe(1); expect(agentCalls[0]).toEqual( expect.objectContaining({ sessionKey: "agent:main:main", @@ -998,7 +998,7 @@ describe("exec approvals", () => { }); expect(result.details.status).toBe("approval-pending"); - await expect.poll(() => agentCalls.length, { timeout: 3_000, interval: 20 }).toBe(1); + await expect.poll(() => agentCalls.length, { timeout: 3_000, interval: 1 }).toBe(1); expect(typeof agentCalls[0]?.message).toBe("string"); expect(agentCalls[0]?.message).toContain("An async command did not run."); expect(agentCalls[0]?.message).toContain( diff --git a/src/agents/sandbox/browser.create.test.ts b/src/agents/sandbox/browser.create.test.ts index ddfcff61224..0cf9d9d5881 100644 --- a/src/agents/sandbox/browser.create.test.ts +++ b/src/agents/sandbox/browser.create.test.ts @@ -106,6 +106,15 @@ function buildConfig(enableNoVnc: boolean): SandboxConfig { }; } +type EnsureSandboxBrowserParams = Parameters[0]; + +async function ensureTestSandboxBrowser(params: Omit) { + return await ensureSandboxBrowser({ + ...params, + bridgeAuth: { token: "test-bridge-token" }, + }); +} + describe("ensureSandboxBrowser create args", () => { beforeAll(async () => { await loadFreshBrowserModulesForTest(); @@ -164,7 +173,7 @@ describe("ensureSandboxBrowser create args", () => { }); it("publishes noVNC on loopback and injects noVNC password env", async () => { - const result = await ensureSandboxBrowser({ + const result = await ensureTestSandboxBrowser({ scopeKey: "session:test", workspaceDir: "/tmp/workspace", agentWorkspaceDir: "/tmp/workspace", @@ -186,7 +195,7 @@ describe("ensureSandboxBrowser create args", () => { }); it("does not inject noVNC password env when noVNC is disabled", async () => { - const result = await ensureSandboxBrowser({ + const result = await ensureTestSandboxBrowser({ scopeKey: "session:test", workspaceDir: "/tmp/workspace", agentWorkspaceDir: "/tmp/workspace", @@ -205,7 +214,7 @@ describe("ensureSandboxBrowser create args", () => { const cfg = buildConfig(false); cfg.workspaceAccess = "none"; - await ensureSandboxBrowser({ + await ensureTestSandboxBrowser({ scopeKey: "session:test", workspaceDir: "/tmp/workspace", agentWorkspaceDir: "/tmp/workspace", @@ -222,7 +231,7 @@ describe("ensureSandboxBrowser create args", () => { const cfg = buildConfig(false); cfg.workspaceAccess = "rw"; - await ensureSandboxBrowser({ + await ensureTestSandboxBrowser({ scopeKey: "session:test", workspaceDir: "/tmp/workspace", agentWorkspaceDir: "/tmp/workspace", @@ -237,7 +246,7 @@ describe("ensureSandboxBrowser create args", () => { }); it("stamps the mount format version label on browser containers", async () => { - await ensureSandboxBrowser({ + await ensureTestSandboxBrowser({ scopeKey: "session:test", workspaceDir: "/tmp/workspace", agentWorkspaceDir: "/tmp/workspace", @@ -270,7 +279,7 @@ describe("ensureSandboxBrowser create args", () => { cfg.browser.autoStartTimeoutMs = 1; await expect( - ensureSandboxBrowser({ + ensureTestSandboxBrowser({ scopeKey: "session:test", workspaceDir: "/tmp/workspace", agentWorkspaceDir: "/tmp/workspace", @@ -287,7 +296,7 @@ describe("ensureSandboxBrowser create args", () => { it("auto-derives CDP source range from Docker network gateway", async () => { dockerMocks.readDockerNetworkGateway.mockResolvedValue("172.21.0.1"); - await ensureSandboxBrowser({ + await ensureTestSandboxBrowser({ scopeKey: "session:test", workspaceDir: "/tmp/workspace", agentWorkspaceDir: "/tmp/workspace", @@ -304,7 +313,7 @@ describe("ensureSandboxBrowser create args", () => { const cfg = buildConfig(false); cfg.browser.cdpSourceRange = "10.0.0.0/24"; - await ensureSandboxBrowser({ + await ensureTestSandboxBrowser({ scopeKey: "session:test", workspaceDir: "/tmp/workspace", agentWorkspaceDir: "/tmp/workspace", @@ -321,7 +330,7 @@ describe("ensureSandboxBrowser create args", () => { dockerMocks.readDockerNetworkGateway.mockResolvedValue("fd12::1"); await expect( - ensureSandboxBrowser({ + ensureTestSandboxBrowser({ scopeKey: "session:test", workspaceDir: "/tmp/workspace", agentWorkspaceDir: "/tmp/workspace", @@ -334,7 +343,7 @@ describe("ensureSandboxBrowser create args", () => { dockerMocks.readDockerNetworkGateway.mockResolvedValue(null); await expect( - ensureSandboxBrowser({ + ensureTestSandboxBrowser({ scopeKey: "session:test", workspaceDir: "/tmp/workspace", agentWorkspaceDir: "/tmp/workspace", @@ -348,7 +357,7 @@ describe("ensureSandboxBrowser create args", () => { dockerMocks.readDockerNetworkGateway.mockResolvedValue("172.21.0.1"); await expect( - ensureSandboxBrowser({ + ensureTestSandboxBrowser({ scopeKey: "session:test", workspaceDir: "/tmp/workspace", agentWorkspaceDir: "/tmp/workspace", @@ -364,7 +373,7 @@ describe("ensureSandboxBrowser create args", () => { const cfg = buildConfig(false); cfg.browser.network = "none"; - const result = await ensureSandboxBrowser({ + const result = await ensureTestSandboxBrowser({ scopeKey: "session:test", workspaceDir: "/tmp/workspace", agentWorkspaceDir: "/tmp/workspace", diff --git a/src/agents/sandbox/browser.ts b/src/agents/sandbox/browser.ts index 035fa3b7d97..7ec821c2391 100644 --- a/src/agents/sandbox/browser.ts +++ b/src/agents/sandbox/browser.ts @@ -66,7 +66,11 @@ async function waitForSandboxCdp(params: { cdpPort: number; timeoutMs: number }) } catch { // ignore } - await new Promise((r) => setTimeout(r, 150)); + const remainingMs = deadline - Date.now(); + if (remainingMs <= 0) { + break; + } + await new Promise((r) => setTimeout(r, Math.min(150, remainingMs))); } return false; } diff --git a/src/agents/session-write-lock.test.ts b/src/agents/session-write-lock.test.ts index c440e6576b0..c7addeb2db7 100644 --- a/src/agents/session-write-lock.test.ts +++ b/src/agents/session-write-lock.test.ts @@ -85,7 +85,7 @@ async function expectActiveInProcessLockIsNotReclaimed(params?: { await expect( acquireSessionWriteLock({ sessionFile, - timeoutMs: 50, + timeoutMs: 5, allowReentrant: false, }), ).rejects.toThrow(/session file locked/); @@ -165,7 +165,7 @@ describe("acquireSessionWriteLock", () => { const lockPath = `${sessionFile}.lock`; await fs.writeFile( lockPath, - JSON.stringify({ pid: 123456, createdAt: new Date(Date.now() - 60_000).toISOString() }), + JSON.stringify({ pid: 2 ** 30, createdAt: new Date(Date.now() - 60_000).toISOString() }), "utf8", ); @@ -183,7 +183,7 @@ describe("acquireSessionWriteLock", () => { await fs.writeFile(lockPath, "{}", "utf8"); await expect( - acquireSessionWriteLock({ sessionFile, timeoutMs: 50, staleMs: 60_000 }), + acquireSessionWriteLock({ sessionFile, timeoutMs: 5, staleMs: 60_000 }), ).rejects.toThrow(/session file locked/); await expect(fs.access(lockPath)).resolves.toBeUndefined(); } finally { diff --git a/src/agents/session-write-lock.ts b/src/agents/session-write-lock.ts index 8f7205ff323..3890a759338 100644 --- a/src/agents/session-write-lock.ts +++ b/src/agents/session-write-lock.ts @@ -566,7 +566,11 @@ export async function acquireSessionWriteLock(params: { continue; } - const delay = Math.min(1000, 50 * attempt); + const remainingMs = timeoutMs - (Date.now() - startedAt); + if (remainingMs <= 0) { + break; + } + const delay = Math.min(1000, 50 * attempt, remainingMs); await new Promise((r) => setTimeout(r, delay)); } }