import { describe, expect, it } from "vitest"; import { applyWorkspaceFocus, deriveWorkspaceFocus, isPaneArtifactMimeType, liveScreenRunId, parseScreenPaneHabit, recordScreenPaneChoice, screenPaneMode, type WorkspaceFocusSnapshot, } from "./workspace-focus.js"; const runningComputer = { kind: "docker", state: "running", screenAvailable: true, takeoverRequested: false, }; function snapshot(overrides: Partial = {}): WorkspaceFocusSnapshot { return { messages: [], run: { id: "run-1", status: "running" }, computer: runningComputer, ...overrides, }; } const report = { id: "msg-report", role: "bot", runId: "run-1", blocks: [ { kind: "file", artifactId: "art-1", name: "report.md", mimeType: "text/markdown", present: true, }, ], }; describe("deriveWorkspaceFocus", () => { it("keeps a plain conversation when the bot only chats", () => { const focus = deriveWorkspaceFocus( snapshot({ messages: [{ id: "m", runId: "run-1", blocks: [{ kind: "text" }] }] }), ); expect(focus.pane).toBeNull(); expect(focus.key).toBe("none|ask:none"); }); it("shows the screen once the working run acts on it", () => { expect(deriveWorkspaceFocus(snapshot(), { screenRunId: "run-1" }).pane).toBe("screen"); expect(deriveWorkspaceFocus(snapshot(), { screenRunId: "run-old" }).pane).toBeNull(); }); it("keeps showing the screen while the bot pointed at it moments ago", () => { const finished = snapshot({ run: { id: "run-1", status: "completed" } }); expect(deriveWorkspaceFocus(finished, { screenActive: true }).pane).toBe("screen"); expect( deriveWorkspaceFocus(finished, { screenActive: true, screenMode: "never" }).pane, ).toBeNull(); }); it("returns to the conversation when the run finishes", () => { const focus = deriveWorkspaceFocus(snapshot({ run: { id: "run-1", status: "completed" } }), { screenRunId: "run-1", }); expect(focus.pane).toBeNull(); }); it("never offers a screen it cannot embed", () => { for (const computer of [ { ...runningComputer, kind: "desktop" }, { ...runningComputer, kind: "none" }, null, ]) { expect( deriveWorkspaceFocus(snapshot({ computer }), { screenRunId: "run-1" }).pane, ).toBeNull(); } }); it("trusts screen work over a computer status that has not caught up with the boot", () => { const stale = { ...runningComputer, state: "stopped", screenAvailable: false }; expect(deriveWorkspaceFocus(snapshot({ computer: stale }), { screenRunId: "run-1" }).pane).toBe( "screen", ); expect( deriveWorkspaceFocus( snapshot({ run: { id: "run-1", status: "waiting_takeover" }, computer: { ...stale, takeoverRequested: true }, }), ).pane, ).toBe("screen"); // Without evidence of screen work, a learned default never boots a stopped computer. expect( deriveWorkspaceFocus(snapshot({ computer: stale }), { screenMode: "always" }).pane, ).toBeNull(); }); it("shows the screen for a takeover request even when the user turned auto off", () => { const focus = deriveWorkspaceFocus( snapshot({ run: { id: "run-1", status: "waiting_takeover" }, computer: { ...runningComputer, takeoverRequested: true }, }), { screenMode: "never" }, ); expect(focus).toMatchObject({ pane: "screen", takeover: true }); }); it("follows the learned screen mode", () => { expect(deriveWorkspaceFocus(snapshot(), { screenMode: "always" }).pane).toBe("screen"); expect( deriveWorkspaceFocus(snapshot(), { screenMode: "never", screenRunId: "run-1" }).pane, ).toBeNull(); expect( deriveWorkspaceFocus(snapshot({ run: { id: "run-1", status: "completed" } }), { screenMode: "always", }).pane, ).toBeNull(); }); it("shows the file the bot presented as its latest result", () => { const focus = deriveWorkspaceFocus( snapshot({ run: { id: "run-1", status: "completed" }, messages: [report] }), ); expect(focus.pane).toBe("artifact"); expect(focus.artifact).toEqual({ messageId: "msg-report", artifactId: "art-1", name: "report.md", mimeType: "text/markdown", }); expect(focus.key).toBe("artifact:art-1|ask:none"); }); it("ignores files that were only attached, presented before the user wrote again, or not previewable", () => { const attached = { ...report, blocks: [{ ...report.blocks[0]!, present: undefined }], }; expect(deriveWorkspaceFocus(snapshot({ messages: [attached] })).pane).toBeNull(); const followUp = { id: "msg-user", role: "user", runId: "run-2", blocks: [{ kind: "text" }] }; expect(deriveWorkspaceFocus(snapshot({ messages: [report, followUp] })).pane).toBeNull(); // Another member's newer run in a group does not hide the result. expect( deriveWorkspaceFocus( snapshot({ run: { id: "run-9", status: "running" }, messages: [report] }), ).pane, ).toBe("artifact"); const pdf = { ...report, blocks: [{ ...report.blocks[0]!, mimeType: "application/pdf", name: "report.pdf" }], }; expect(deriveWorkspaceFocus(snapshot({ messages: [pdf] })).pane).toBeNull(); }); it("prefers live screen work over a presented file", () => { expect( deriveWorkspaceFocus(snapshot({ messages: [report] }), { screenRunId: "run-1" }).pane, ).toBe("screen"); }); it("names the ask the bot is waiting on", () => { const focus = deriveWorkspaceFocus( snapshot({ run: { id: "run-1", status: "waiting_input" }, messages: [{ id: "ask-1", runId: "run-1", blocks: [{ kind: "ask", status: "pending" }] }], }), ); expect(focus.needsYouMessageId).toBe("ask-1"); expect(focus.key).toBe("none|ask:ask-1"); }); }); describe("applyWorkspaceFocus", () => { const plain = deriveWorkspaceFocus(snapshot()); const screen = deriveWorkspaceFocus(snapshot(), { screenRunId: "run-1" }); const artifact = deriveWorkspaceFocus( snapshot({ run: { id: "run-1", status: "completed" }, messages: [report] }), ); const closed = { open: null, auto: false } as const; it("treats the first focus of a conversation as a baseline", () => { expect(applyWorkspaceFocus(null, screen, closed)).toBeNull(); }); it("opens the pane on an edge and closes it again when the work ends", () => { const opened = applyWorkspaceFocus(plain, screen, closed); expect(opened).toEqual({ open: "screen", auto: true }); expect(applyWorkspaceFocus(screen, plain, opened!)).toEqual(closed); }); it("moves from the screen to the presented result", () => { expect(applyWorkspaceFocus(screen, artifact, { open: "screen", auto: true })).toEqual({ open: "artifact", auto: true, }); }); it("keeps a presented file open while the user follows up", () => { const followUp = deriveWorkspaceFocus( snapshot({ run: { id: "run-2", status: "running" }, messages: [report, { id: "msg-user", role: "user", blocks: [{ kind: "text" }] }], }), ); expect(followUp.pane).toBeNull(); expect(applyWorkspaceFocus(artifact, followUp, { open: "artifact", auto: true })).toBeNull(); }); it("never replaces or closes what the user opened by hand", () => { expect(applyWorkspaceFocus(plain, screen, { open: "other", auto: false })).toBeNull(); expect(applyWorkspaceFocus(plain, artifact, { open: "screen", auto: false })).toBeNull(); expect(applyWorkspaceFocus(screen, plain, { open: "screen", auto: false })).toBeNull(); expect(applyWorkspaceFocus(plain, screen, { open: "screen", auto: false })).toBeNull(); }); it("swaps in a newer presented file", () => { const newer = deriveWorkspaceFocus( snapshot({ run: { id: "run-1", status: "completed" }, messages: [ report, { ...report, id: "msg-2", blocks: [{ ...report.blocks[0]!, artifactId: "art-2", name: "v2.md" }], }, ], }), ); expect(applyWorkspaceFocus(artifact, newer, { open: "artifact", auto: false })).toEqual({ open: "artifact", auto: false, }); }); it("ignores focus changes that only concern a new ask", () => { const asking = { ...plain, needsYouMessageId: "ask-1", key: "none|ask:ask-1" }; expect(applyWorkspaceFocus(plain, asking, closed)).toBeNull(); }); }); describe("screen pane habit", () => { it("learns to always show the screen after repeated manual opens", () => { let habit = 0; for (let index = 0; index < 3; index += 1) habit = recordScreenPaneChoice(habit, "opened"); expect(screenPaneMode(habit)).toBe("always"); expect(recordScreenPaneChoice(habit, "opened")).toBe(3); }); it("learns to stop opening it after repeated dismissals, and recovers on a manual open", () => { let habit = recordScreenPaneChoice(2, "dismissed"); expect(screenPaneMode(habit)).toBe("auto"); habit = recordScreenPaneChoice(habit, "dismissed"); expect(screenPaneMode(habit)).toBe("never"); expect(screenPaneMode(recordScreenPaneChoice(habit, "opened"))).toBe("auto"); }); it("parses stored habits defensively", () => { expect(parseScreenPaneHabit(null)).toBe(0); expect(parseScreenPaneHabit("2")).toBe(2); expect(parseScreenPaneHabit("99")).toBe(3); expect(parseScreenPaneHabit("-9")).toBe(-2); expect(parseScreenPaneHabit("x")).toBe(0); }); }); describe("isPaneArtifactMimeType", () => { it("accepts text and images, not PDFs", () => { expect(isPaneArtifactMimeType("text/csv")).toBe(true); expect(isPaneArtifactMimeType("image/png")).toBe(true); expect(isPaneArtifactMimeType("application/pdf")).toBe(false); }); }); describe("liveScreenRunId", () => { const pointer = { type: "thread.computer", runId: "run-1", createdAt: "2026-01-01T00:00:10.000Z", payload: { kind: "pointer", screen: { width: 1280, height: 800 }, steps: [{ action: "click", x: 640, y: 400 }], }, }; const now = Date.parse("2026-01-01T00:00:20.000Z"); it("names the run that is pointing at the screen right now", () => { expect(liveScreenRunId(pointer, now)).toBe("run-1"); }); it("ignores stale, malformed and unrelated events", () => { expect(liveScreenRunId(pointer, now + 60_000)).toBeNull(); expect(liveScreenRunId({ ...pointer, payload: { kind: "pointer" } }, now)).toBeNull(); expect(liveScreenRunId({ ...pointer, runId: undefined }, now)).toBeNull(); expect(liveScreenRunId({ ...pointer, type: "thread.progress" }, now)).toBeNull(); }); });