import { beforeEach, describe, expect, it, vi } from "vitest"; import { callGatewayToolMock, COMPUTER_ACT_COMMAND, type ComputerActBody, type ComputerTool, type ComputerToolOptions, createVisionComputerTool, EFFECTIVE_REF_WIDTH, listNodesMock, macComputerNode, readFrameId, readLastComputerActParams, resetComputerToolMocks, screenshotPayload, TINY_PNG_BASE64, } from "./computer-tool.test-helpers.js"; const INVALID_SCROLL_AMOUNT = /scrollAmount must be a positive integer/; const INVALID_HOLD_DURATION = /duration must be >0 and <=10 seconds/; function expectedAct(action: string, fields: Record = {}) { return { action, screenIndex: 0, refWidth: EFFECTIVE_REF_WIDTH, ...fields }; } function twoMacComputerNodes() { return [ macComputerNode({ nodeId: "mac-a" }), macComputerNode({ nodeId: "mac-b", displayName: "Studio B" }), ]; } function computerActBodies(): ComputerActBody[] { return callGatewayToolMock.mock.calls .map((call) => call[2] as ComputerActBody) .filter((body) => body.command === COMPUTER_ACT_COMMAND) .map((body) => { if (!body.params) { return body; } const { executionId: _executionId, ...params } = body.params; const sanitizedBody = Object.assign({}, body); sanitizedBody.params = params; return sanitizedBody; }); } async function captureFrame( tool: ComputerTool, input: Record = {}, callId = "shot", ) { return readFrameId(await tool.execute(callId, { action: "screenshot", ...input })); } async function createToolWithFrame( options: ComputerToolOptions = {}, input: Record = {}, callId = "shot", ) { const tool = createVisionComputerTool(options); return { tool, frameId: await captureFrame(tool, input, callId) }; } function executeClick( tool: ComputerTool, frameId: string, input: Record = {}, callId = "click", signal?: AbortSignal, ) { return tool.execute( callId, { action: "left_click", coordinate: [1, 2], frameId, ...input }, signal, ); } function executeMouseDown( tool: ComputerTool, frameId: string, input: Record = {}, signal?: AbortSignal, ) { return tool.execute( "down", { action: "left_mouse_down", coordinate: [1, 2], frameId, ...input }, signal, ); } function retargetToMacB(tool: ComputerTool, callId = "retarget") { return tool.execute(callId, { action: "screenshot", node: "mac-b" }); } type InvalidCase = [string, Record, RegExp]; function invalidScrollCase(name: string, scrollAmount: unknown): InvalidCase { return [name, { action: "scroll", scrollDirection: "down", scrollAmount }, INVALID_SCROLL_AMOUNT]; } function invalidHoldCase(name: string, duration: unknown): InvalidCase { return [name, { action: "hold_key", text: "space", duration }, INVALID_HOLD_DURATION]; } function mockComputerActError(error: Error, action?: string) { callGatewayToolMock.mockImplementation(async (_method, _opts, body) => { const request = body as ComputerActBody; if ( request.command === COMPUTER_ACT_COMMAND && (!action || request.params?.action === action) ) { throw error; } return request.command === COMPUTER_ACT_COMMAND ? { payload: { ok: true } } : screenshotPayload(); }); } function mockFirstScreenshotThenFailure(screenIndex = 0) { let screenshotCalls = 0; callGatewayToolMock.mockImplementation(async (_method, _opts, body) => { if ((body as ComputerActBody).command === COMPUTER_ACT_COMMAND) { return { payload: { ok: true } }; } if ((screenshotCalls += 1) === 1) { return screenshotPayload(screenIndex); } throw new Error("capture failed"); }); } async function executeComputerAction(params: Record) { const tool = createVisionComputerTool(); const actionParams = { ...params }; if (Object.hasOwn(params, "coordinate") || Object.hasOwn(params, "startCoordinate")) { const screenshot = await tool.execute("shot", { action: "screenshot" }); actionParams.frameId = readFrameId(screenshot); } await tool.execute("act", actionParams); return readLastComputerActParams(); } describe("createComputerTool v1 execution", () => { beforeEach(resetComputerToolMocks); it.each([ [ "maps left click through the computer.act execution path", { action: "left_click", coordinate: [12, 34], text: "shift" }, expectedAct("left_click", { displayFrameId: "display-0-frame", x: 12, y: 34, modifiers: "shift", }), ], [ "maps drag through the computer.act execution path", { action: "left_click_drag", startCoordinate: [1, 2], coordinate: [3, 4] }, expectedAct("left_click_drag", { displayFrameId: "display-0-frame", fromX: 1, fromY: 2, x: 3, y: 4, }), ], [ "maps scroll input without leaking pointer fields", { action: "scroll", scrollDirection: "Down", scrollAmount: 999, text: "cmd" }, expectedAct("scroll", { scrollDirection: "down", scrollAmount: 100, modifiers: "cmd", }), ], [ "maps type input without leaking pointer fields", { action: "type", text: "hello", coordinate: [5, 6] }, expectedAct("type", { text: "hello" }), ], [ "maps key input without leaking pointer fields", { action: "key", text: "cmd+shift+t" }, expectedAct("key", { keys: "cmd+shift+t" }), ], [ "maps hold key input without leaking pointer fields", { action: "hold_key", text: "space", duration: 10 }, expectedAct("hold_key", { keys: "space", durationMs: 10_000 }), ], ])("%s", async (_name, params, expected) => { await expect(executeComputerAction(params)).resolves.toEqual(expected); }); it("requires coordinates through the public execution path", async () => { const { tool, frameId } = await createToolWithFrame(); await expect(tool.execute("act", { action: "double_click", frameId })).rejects.toThrow( /coordinate/, ); expect(() => readLastComputerActParams()).toThrow(/missing computer\.act request/); }); it.each([ { coordinate: [null, 2] }, { coordinate: [false, 2] }, { coordinate: ["1", 2] }, { coordinate: [-1, 2] }, { coordinate: [1.5, 2] }, { coordinate: [1] }, { coordinate: [1, 2, 3] }, ])("rejects malformed required coordinate input %#", async ({ coordinate }) => { await expect(executeComputerAction({ action: "left_click", coordinate })).rejects.toThrow( /coordinate/, ); }); it.each([ { coordinate: null }, { coordinate: "1,2" }, { coordinate: [1] }, { coordinate: [1, 2, 3] }, { coordinate: [1, false] }, ])( "rejects malformed optional coordinate input %# instead of acting at the cursor", async ({ coordinate }) => { await expect( executeComputerAction({ action: "left_mouse_down", coordinate }), ).rejects.toThrow(/coordinate/); }, ); it("captures a screenshot through screen.snapshot and keeps it model-only", async () => { const result = await createVisionComputerTool().execute("call", { action: "screenshot" }); expect(callGatewayToolMock).toHaveBeenCalledWith( "node.invoke", expect.anything(), expect.objectContaining({ nodeId: "mac-1", command: "screen.snapshot", params: expect.objectContaining({ maxWidth: EFFECTIVE_REF_WIDTH, format: "jpeg" }), }), { signal: undefined }, ); // Desktop pixels stay model-only (#44759): never auto-delivered to chat. expect(result.details).toMatchObject({ media: { outbound: false }, refWidth: EFFECTIVE_REF_WIDTH, }); }); it("omits an unchanged screenshot while retaining its frame and refreshing node coordinates", async () => { let screenshotCalls = 0; callGatewayToolMock.mockImplementation(async (_method, _opts, body) => { if ((body as ComputerActBody).command === COMPUTER_ACT_COMMAND) { return { payload: { ok: true } }; } const result = screenshotPayload(); result.payload.displayFrameId = `display-frame-${++screenshotCalls}`; return result; }); const contextEpoch = { value: 0 }; const tool = createVisionComputerTool({ contextEpoch }); const first = await tool.execute("shot-1", { action: "screenshot" }); const frameId = readFrameId(first); const second = await tool.execute("shot-2", { action: "screenshot" }); expect(second.content).toEqual([ { type: "text", text: `screen unchanged since previous frame (frameId ${frameId}); screenshot omitted — keep using this frameId for coordinates`, }, ]); expect(second.details).toMatchObject({ frameId, screenIndex: 0, refWidth: EFFECTIVE_REF_WIDTH, }); expect(contextEpoch).toMatchObject({ frameToolCallId: "shot-1" }); await expect(executeClick(tool, frameId)).resolves.toBeDefined(); expect(readLastComputerActParams()).toMatchObject({ displayFrameId: "display-frame-2" }); }); it("delivers changed screenshot pixels under a new coordinate frame", async () => { const changedPng = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAADUlEQVR4nGP4////KwAJ5gPoxLp9owAAAABJRU5ErkJggg=="; callGatewayToolMock .mockResolvedValueOnce(screenshotPayload()) .mockResolvedValueOnce(screenshotPayload(0, changedPng)); const tool = createVisionComputerTool({ contextEpoch: { value: 0 } }); const firstFrameId = await captureFrame(tool, {}, "shot-1"); const changed = await tool.execute("shot-2", { action: "screenshot" }); expect(changed.content).toContainEqual(expect.objectContaining({ type: "image" })); expect(readFrameId(changed)).not.toBe(firstFrameId); await expect(executeClick(tool, firstFrameId)).rejects.toThrow(/frameId does not match/); }); it("preserves an input action's result when its follow-up screenshot is unchanged", async () => { const tool = createVisionComputerTool({ contextEpoch: { value: 0 } }); const frameId = await captureFrame(tool, {}, "shot-1"); const result = await executeClick(tool, frameId); expect(result.content).toEqual([ { type: "text", text: `{"action":"left_click","ok":true}\nscreen unchanged since previous frame (frameId ${frameId}); screenshot omitted — keep using this frameId for coordinates`, }, ]); expect(readFrameId(result)).toBe(frameId); }); it("preserves wait metadata when its follow-up screenshot is unchanged", async () => { const tool = createVisionComputerTool({ contextEpoch: { value: 0 } }); const frameId = await captureFrame(tool, {}, "shot-1"); const result = await tool.execute("wait", { action: "wait", duration: 0 }); expect(result.content).toEqual([ { type: "text", text: `waited 0s\nscreen unchanged since previous frame (frameId ${frameId}); screenshot omitted — keep using this frameId for coordinates`, }, ]); }); it.each([ ["another screen", { screenIndex: 1 }], ["another node", { node: "mac-b" }], ])("does not reuse identical screenshot pixels from %s", async (_name, input) => { listNodesMock.mockResolvedValue(twoMacComputerNodes()); const tool = createVisionComputerTool({ contextEpoch: { value: 0 } }); const firstFrameId = await captureFrame(tool, { node: "mac-a" }, "shot-1"); const result = await tool.execute("shot-2", { action: "screenshot", ...input }); expect(result.content).toContainEqual(expect.objectContaining({ type: "image" })); expect(readFrameId(result)).not.toBe(firstFrameId); }); it("keeps duplicate screenshots when their context presence cannot be tracked", async () => { const tool = createVisionComputerTool(); const first = await tool.execute("shot-1", { action: "screenshot" }); const second = await tool.execute("shot-2", { action: "screenshot" }); expect(first.content).toContainEqual(expect.objectContaining({ type: "image" })); expect(second.content).toContainEqual(expect.objectContaining({ type: "image" })); expect(readFrameId(second)).not.toBe(readFrameId(first)); }); it("derives a stable node idempotency key from the run and tool call", async () => { for (let attempt = 0; attempt < 2; attempt += 1) { const tool = createVisionComputerTool({ idempotencyScope: "run-1" }); await tool.execute("call-computer-1", { action: "type", text: "hello" }); } const actKeys = computerActBodies().map((body) => body.idempotencyKey); expect(actKeys).toHaveLength(2); expect(actKeys[0]).toMatch(/^computer\.act:v1:[0-9a-f]{64}$/); expect(actKeys[1]).toBe(actKeys[0]); }); it("does not share node receipts across runs that reuse a tool call id", async () => { for (const idempotencyScope of ["run-1", "run-2"]) { const tool = createVisionComputerTool({ idempotencyScope }); await tool.execute("call-computer-1", { action: "type", text: "hello" }); } const actKeys = computerActBodies().map((body) => body.idempotencyKey); expect(actKeys).toHaveLength(2); expect(actKeys[1]).not.toBe(actKeys[0]); }); it("does not share node receipts when no stable run scope is available", async () => { const tool = createVisionComputerTool(); await tool.execute("reused-call-id", { action: "type", text: "first" }); await tool.execute("reused-call-id", { action: "type", text: "second" }); const actKeys = computerActBodies().map((body) => body.idempotencyKey); expect(actKeys).toHaveLength(2); expect(actKeys[0]).not.toBe(actKeys[1]); }); it.each([ [ "surfaces the node enablement hint when computer.act is not allowlisted", Object.assign( new Error( 'node command not allowed: "computer.act" is not in the allowlist for platform "macos"', ), { name: "GatewayClientRequestError", details: { reason: "command not allowlisted", command: "computer.act" }, }, ), /enable Computer Control.*approve the pairing update/i, ], [ "surfaces the persistent deny remediation", new Error( 'node command not allowed: "computer.act" is blocked by gateway.nodes.commands.deny', ), /remove computer\.act from gateway\.nodes\.commands\.deny/, ], ])("%s", async (_name, error, expected) => { mockComputerActError(error); const { tool, frameId } = await createToolWithFrame({}, {}, "call"); await expect(executeClick(tool, frameId, { coordinate: [10, 10] }, "call")).rejects.toThrow( expected, ); }); it("expires screenshot coordinates when compaction removes the image context", async () => { const contextEpoch = { value: 0 }; const { tool, frameId } = await createToolWithFrame({ contextEpoch }); contextEpoch.value += 1; await expect(executeClick(tool, frameId, { coordinate: [5, 5] })).rejects.toThrow( /screenshot/i, ); expect(computerActBodies()).toHaveLength(0); }); it.each([ [ "fails closed when a coordinate action has no observed screenshot frame", { action: "left_click", coordinate: [5, 5] }, /screenshot/i, ], [ "does not let an explicit screen index substitute for an observed frame", { action: "left_click", coordinate: [5, 5], screenIndex: 0, frameId: "guessed", }, /screenshot/i, ], [ "rejects an invalid screen index instead of clamping it to display zero", { action: "screenshot", screenIndex: -1 }, /screenIndex must be a non-negative integer/, ], ])("%s", async (_name, input, error) => { await expect(createVisionComputerTool().execute("call", input)).rejects.toThrow(error); expect(callGatewayToolMock).not.toHaveBeenCalled(); }); it.each([ invalidScrollCase("fractional scroll amount", 1.5), invalidScrollCase("zero scroll amount", 0), invalidScrollCase("negative scroll amount", -1), invalidScrollCase("boolean scroll amount", true), invalidScrollCase("string scroll amount", "many"), ["missing scroll direction", { action: "scroll" }, /scrollDirection/], invalidHoldCase("boolean hold duration", true), invalidHoldCase("zero hold duration", 0), invalidHoldCase("oversized hold duration", 11), ["boolean wait duration", { action: "wait", duration: true }, /duration must be 0-100 seconds/], ])("rejects invalid %s before invoking the node", async (_label, params, error) => { await expect(createVisionComputerTool().execute("call", params)).rejects.toThrow(error); expect(callGatewayToolMock).not.toHaveBeenCalled(); }); it("targets the last screenshot's display when a coordinate action omits screenIndex", async () => { callGatewayToolMock.mockImplementation(async (_method, _opts, body) => (body as ComputerActBody).command === COMPUTER_ACT_COMMAND ? { payload: { ok: true } } : screenshotPayload(1), ); const { tool, frameId } = await createToolWithFrame({}, { screenIndex: 1 }, "call"); // The model looks at display 1, then clicks a coordinate from that screenshot // without repeating screenIndex. await executeClick(tool, frameId, { coordinate: [10, 20] }, "call"); // Without display retention this would silently target display 0. expect(computerActBodies()[0]?.params).toMatchObject({ action: "left_click", displayFrameId: "display-1-frame", screenIndex: 1, }); }); it("refuses to arm coordinates from a snapshot without physical display identity", async () => { callGatewayToolMock.mockResolvedValue({ payload: { format: "png", base64: TINY_PNG_BASE64, width: 1280, height: 800, screenIndex: 0 }, }); await expect( createVisionComputerTool().execute("call", { action: "screenshot" }), ).rejects.toThrow(/missing displayFrameId/); }); it("rejects a coordinate action that retargets a different display", async () => { callGatewayToolMock.mockImplementation(async (_method, _opts, body) => (body as ComputerActBody).command === COMPUTER_ACT_COMMAND ? { payload: { ok: true } } : screenshotPayload(1), ); const { tool, frameId } = await createToolWithFrame({}, { screenIndex: 1 }, "call"); await expect( executeClick(tool, frameId, { coordinate: [10, 20], screenIndex: 0 }, "call"), ).rejects.toThrow(/screenIndex does not match/); expect(computerActBodies()).toHaveLength(0); }); it("does not inherit another node's frame when a coordinate action names a different node", async () => { listNodesMock.mockResolvedValue(twoMacComputerNodes()); // Observe a frame on node A (screen 1). const { tool, frameId } = await createToolWithFrame( {}, { node: "mac-a", screenIndex: 1 }, "call", ); // A click naming node B must not apply node A's frame; it needs its own screenshot. await expect(executeClick(tool, frameId, { node: "mac-b" }, "call")).rejects.toThrow( /no screenshot of this computer/i, ); }); it.each([ [ "does not authorize coordinates when the model received no image", { modelHasVision: false }, TINY_PNG_BASE64, ], [ "does not authorize coordinates when screenshot sanitization omits the image", {}, "not-base64!!!", ], ])("%s", async (_name, options, base64) => { callGatewayToolMock.mockResolvedValue(screenshotPayload(0, base64)); const { tool, frameId } = await createToolWithFrame(options, {}, "call"); await expect(executeClick(tool, frameId, {}, "call")).rejects.toThrow(/no screenshot/i); }); it("invalidates the old frame when the post-action screenshot fails", async () => { mockFirstScreenshotThenFailure(); const contextEpoch = { value: 0 }; const { tool, frameId } = await createToolWithFrame({ contextEpoch }, {}, "call"); await expect(executeClick(tool, frameId, {}, "call")).resolves.toMatchObject({ details: { action: "left_click" }, }); expect(contextEpoch).toEqual({ value: 0 }); await expect(executeClick(tool, frameId, { coordinate: [2, 3] }, "call")).rejects.toThrow( /no screenshot/i, ); }); it("keeps target affinity for button release after a failed screenshot", async () => { listNodesMock.mockResolvedValue(twoMacComputerNodes()); mockFirstScreenshotThenFailure(1); const { tool, frameId } = await createToolWithFrame({}, { node: "mac-a", screenIndex: 1 }); await executeMouseDown(tool, frameId); await expect(retargetToMacB(tool)).rejects.toThrow( /left button may still be held on node mac-a/, ); await tool.execute("up", { action: "left_mouse_up" }); const actBodies = computerActBodies(); expect(actBodies).toHaveLength(2); expect(actBodies[0]).toMatchObject({ nodeId: "mac-a", params: { action: "left_mouse_down", screenIndex: 1 }, }); expect(actBodies[1]).toMatchObject({ nodeId: "mac-a", params: { action: "left_mouse_up", screenIndex: 1 }, }); expect(actBodies[1]?.params).not.toHaveProperty("displayFrameId"); }); it.each([ [ "clears button affinity when the gateway definitively rejects mouse down", Object.assign(new Error("node command rejected before dispatch"), { name: "GatewayClientRequestError", details: { reason: "command not allowlisted", command: "computer.act" }, }), /enable Computer Control.*approve the pairing update/i, ], [ "clears button affinity after a structured pre-dispatch policy rejection", Object.assign(new Error("phone policy denied computer control"), { name: "GatewayClientRequestError", gatewayCode: "INVALID_REQUEST", details: { code: "POLICY_DENIED", nodeCommandDispatched: false }, }), "phone policy denied computer control", ], ])("%s", async (_name, error, expected) => { listNodesMock.mockResolvedValue(twoMacComputerNodes()); mockComputerActError(error); const { tool, frameId } = await createToolWithFrame({}, { node: "mac-a" }); await expect(executeMouseDown(tool, frameId)).rejects.toThrow(expected); await expect(retargetToMacB(tool)).resolves.toMatchObject({ details: { node: "mac-b" } }); }); it.each([ ["node timeout", "TIMEOUT: node invoke timed out", "UNAVAILABLE", undefined], ["gateway unavailable", "node disconnected (computer.act)", "UNAVAILABLE", undefined], [ "post-dispatch policy rejection", "plugin rejected after dispatch", "INVALID_REQUEST", { nodeCommandDispatched: true }, ], ])( "keeps button affinity after an ambiguous %s request error", async (_label, message, gatewayCode, details) => { listNodesMock.mockResolvedValue(twoMacComputerNodes()); mockComputerActError( Object.assign(new Error(message), { name: "GatewayClientRequestError", gatewayCode, details, }), "left_mouse_down", ); const { tool, frameId } = await createToolWithFrame({}, { node: "mac-a" }); await expect(executeMouseDown(tool, frameId)).rejects.toThrow(message); await expect(retargetToMacB(tool)).rejects.toThrow( /left button may still be held on node mac-a/, ); await expect(tool.execute("up", { action: "left_mouse_up" })).resolves.toBeDefined(); await expect(retargetToMacB(tool, "retarget-after-release")).resolves.toMatchObject({ details: { node: "mac-b" }, }); }, ); it("does not claim button affinity when cancellation wins during target resolution", async () => { const controller = new AbortController(); let listCalls = 0; listNodesMock.mockImplementation(async () => { listCalls += 1; if (listCalls === 2) { controller.abort(new Error("cancelled before dispatch")); } return twoMacComputerNodes(); }); const { tool, frameId } = await createToolWithFrame({}, { node: "mac-a" }); await expect( executeMouseDown(tool, frameId, { node: "mac-a" }, controller.signal), ).rejects.toThrow("cancelled before dispatch"); expect(callGatewayToolMock).toHaveBeenCalledTimes(1); await expect(retargetToMacB(tool)).resolves.toMatchObject({ details: { node: "mac-b" } }); }); it("treats mouse up as idempotent after lifecycle cleanup released the button", async () => { listNodesMock.mockResolvedValue(twoMacComputerNodes()); let actCalls = 0; callGatewayToolMock.mockImplementation(async (_method, _opts, body) => { if ((body as { command?: string }).command === COMPUTER_ACT_COMMAND) { actCalls += 1; if (actCalls === 2) { throw Object.assign( new Error("INVALID_REQUEST: left button is not held by computer control"), { name: "GatewayClientRequestError" }, ); } return { payload: { ok: true } }; } return screenshotPayload(); }); const { tool, frameId } = await createToolWithFrame({}, { node: "mac-a" }); await executeMouseDown(tool, frameId); await expect(tool.execute("up", { action: "left_mouse_up" })).resolves.toBeDefined(); await expect(retargetToMacB(tool)).resolves.toMatchObject({ details: { node: "mac-b" } }); }); it("aborts a wait without taking the delayed screenshot", async () => { const controller = new AbortController(); const tool = createVisionComputerTool(); const pending = tool.execute("call", { action: "wait", duration: 100 }, controller.signal); await Promise.resolve(); controller.abort(new Error("cancelled")); await expect(pending).rejects.toThrow(/Aborted/); expect(callGatewayToolMock).not.toHaveBeenCalled(); }); it("propagates cancellation from the follow-up screenshot after input lands", async () => { let screenshotCalls = 0; let followupStarted!: () => void; const started = new Promise((resolve) => { followupStarted = resolve; }); callGatewayToolMock.mockImplementation(async (_method, _opts, body, extra) => { if ((body as { command?: string }).command === COMPUTER_ACT_COMMAND) { return { payload: { ok: true } }; } screenshotCalls += 1; if (screenshotCalls === 1) { return screenshotPayload(); } followupStarted(); const signal = (extra as { signal?: AbortSignal } | undefined)?.signal; return await new Promise((_, reject) => { signal?.addEventListener( "abort", () => reject(signal.reason instanceof Error ? signal.reason : new Error("aborted")), { once: true }, ); }); }); const controller = new AbortController(); const { tool, frameId } = await createToolWithFrame(); const pending = executeClick(tool, frameId, {}, "click", controller.signal); await started; controller.abort(new Error("cancelled during follow-up")); await expect(pending).rejects.toThrow(/cancelled during follow-up/); }); it("does not run a dangerous action that was aborted while queued", async () => { let releaseScreenshot!: () => void; callGatewayToolMock.mockImplementation(async (_method, _opts, body) => { if ((body as { command?: string }).command === COMPUTER_ACT_COMMAND) { return { payload: { ok: true } }; } await new Promise((resolve) => { releaseScreenshot = resolve; }); return screenshotPayload(); }); const tool = createVisionComputerTool(); const first = tool.execute("first", { action: "screenshot" }); await vi.waitFor(() => expect(releaseScreenshot).toBeTypeOf("function")); const controller = new AbortController(); const queued = tool.execute("queued", { action: "type", text: "never" }, controller.signal); controller.abort(new Error("cancelled")); releaseScreenshot(); await first; await expect(queued).rejects.toThrow(/cancelled/); expect(computerActBodies()).toHaveLength(0); }); });