import { describe, expect, it } from "vite-plus/test"; import { canDetachThreadProviderSession, canForkProjectedAssistantItem, deriveThreadQueueWorkflowState, resolveLatestMergeBackRun, } from "./threadWorkflows.ts"; const capabilities = (input?: { readonly queued?: boolean; readonly steer?: boolean; readonly restartSteer?: boolean; readonly nativeFork?: boolean; readonly portableFork?: boolean; }) => ({ turns: { supportsQueuedMessages: input?.queued ?? false, supportsActiveSteering: input?.steer ?? false, supportsSteeringByInterruptRestart: input?.restartSteer ?? false, }, threads: { canForkThread: input?.nativeFork ?? false, canForkFromTurn: input?.nativeFork ?? false, }, identity: { nativeThreadIds: input?.nativeFork ? "strong" : "none" }, context: { supportsFullThreadHandoff: input?.portableFork ?? false }, }) as never; describe("thread workflows", () => { it("sorts queued messages and gates reorder and promotion from capabilities", () => { const state = deriveThreadQueueWorkflowState({ thread: { id: "thread", activeProviderThreadId: "provider-thread" }, runs: [ { id: "active", status: "running", providerThreadId: "provider-thread", activeAttemptId: "attempt-active", ordinal: 1, }, { id: "later", status: "queued", userMessageId: "message-later", ordinal: 3 }, { id: "first", status: "queued", userMessageId: "message-first", ordinal: 2, queuePosition: 1, }, ], messages: [ { id: "message-first", text: "First", attachments: [ { type: "image", id: "attachment-first", name: "first.png", mimeType: "image/png", sizeBytes: 64, }, ], }, { id: "message-later", text: "Later" }, ], providerTurns: [ { id: "provider-turn-active", runAttemptId: "attempt-active", status: "running", }, ], providerThreads: [ { id: "provider-thread", appThreadId: "thread", providerSessionId: "provider-session", }, ], providerSessions: [ { id: "provider-session", status: "running", capabilities: capabilities({ queued: true, restartSteer: true }), }, ], } as never); expect(state.queuedRuns.map(({ run, text }) => [run.id, text])).toEqual([ ["first", "First"], ["later", "Later"], ]); expect(state.queuedRuns.map(({ attachments }) => attachments.map(({ id }) => id))).toEqual([ ["attachment-first"], [], ]); expect(state.activeRun?.id).toBe("active"); expect(state.canReorder).toBe(true); expect(state.canPromoteToSteer).toBe(true); }); it("hides automatic completion delivery from the visible queue", () => { const state = deriveThreadQueueWorkflowState({ thread: { id: "thread", activeProviderThreadId: null }, runs: [ { id: "automatic", status: "queued", userMessageId: "message-automatic", ordinal: 2, queuePosition: 1, }, { id: "visible", status: "queued", userMessageId: "message-visible", ordinal: 3, queuePosition: 2, }, ], messages: [ { id: "message-automatic", text: "A delegated task reached a terminal state.", delegatedCompletion: { generation: 1, parentRunId: "run:parent", taskIds: ["task:child"], }, }, { id: "message-visible", text: "Visible queued message" }, ], providerTurns: [], providerThreads: [], providerSessions: [], } as never); expect(state.queuedRuns.map(({ run, text }) => [run.id, text])).toEqual([ ["visible", "Visible queued message"], ]); }); it("removes only the promoted head from the visible queue", () => { const state = deriveThreadQueueWorkflowState({ thread: { id: "thread", activeProviderThreadId: "provider-thread" }, runs: [ { id: "promoted", status: "starting", userMessageId: "message-promoted", providerThreadId: "provider-thread", ordinal: 2, queuePosition: null, }, { id: "still-queued", status: "queued", userMessageId: "message-still-queued", providerThreadId: "provider-thread", ordinal: 3, queuePosition: 2, }, ], messages: [ { id: "message-promoted", text: "Run now" }, { id: "message-still-queued", text: "Wait longer" }, ], providerTurns: [], providerThreads: [], providerSessions: [], } as never); expect(state.activeRun?.id).toBe("promoted"); expect(state.queuedRuns.map(({ run, text }) => [run.id, text])).toEqual([ ["still-queued", "Wait longer"], ]); }); it.each(["preparing", "starting", "waiting"] as const)( "does not promote queued work into a %s run", (status) => { const state = deriveThreadQueueWorkflowState({ thread: { id: "thread", activeProviderThreadId: "provider-thread" }, runs: [ { id: "active", status, providerThreadId: "provider-thread", activeAttemptId: "attempt-active", ordinal: 1, }, { id: "queued", status: "queued", userMessageId: "message", ordinal: 2 }, ], messages: [{ id: "message", text: "Queued" }], providerTurns: [ { id: "provider-turn-active", runAttemptId: "attempt-active", status: status === "waiting" ? "completed" : "starting", }, ], providerThreads: [ { id: "provider-thread", appThreadId: "thread", providerSessionId: "provider-session", }, ], providerSessions: [ { id: "provider-session", status: "running", capabilities: capabilities({ queued: true, steer: true }), }, ], } as never); expect(state.canPromoteToSteer).toBe(false); }, ); it("does not promote queued work until the running provider turn is projected", () => { const state = deriveThreadQueueWorkflowState({ thread: { id: "thread", activeProviderThreadId: "provider-thread" }, runs: [ { id: "active", status: "running", providerThreadId: "provider-thread", activeAttemptId: "attempt-active", ordinal: 1, }, { id: "queued", status: "queued", userMessageId: "message", ordinal: 2 }, ], messages: [{ id: "message", text: "Queued" }], providerTurns: [], providerThreads: [ { id: "provider-thread", appThreadId: "thread", providerSessionId: "provider-session", }, ], providerSessions: [ { id: "provider-session", status: "running", capabilities: capabilities({ queued: true, steer: true }), }, ], } as never); expect(state.canPromoteToSteer).toBe(false); }); it("does not expose known unsupported queue or fork actions", () => { const projection = { thread: { id: "thread", activeProviderThreadId: "provider-thread" }, runs: [{ id: "queued", status: "queued", userMessageId: "message", ordinal: 1 }], messages: [], providerThreads: [ { id: "provider-thread", appThreadId: "thread", providerSessionId: "provider-session", }, ], providerSessions: [ { id: "provider-session", status: "ready", capabilities: capabilities(), }, ], } as never; const queue = deriveThreadQueueWorkflowState(projection); const projectedItem = { item: { type: "assistant_message", runId: "run", status: "completed" }, } as never; expect(queue.canReorder).toBe(false); expect(queue.canPromoteToSteer).toBe(false); expect(canForkProjectedAssistantItem({ projectedItem, capabilities: capabilities() })).toBe( false, ); expect(canDetachThreadProviderSession(projection)).toBe(true); }); it("allows native, portable, and capability-unknown exact-run forks", () => { const projectedItem = { item: { type: "assistant_message", runId: "run", status: "completed" }, } as never; expect( canForkProjectedAssistantItem({ projectedItem, capabilities: capabilities({ nativeFork: true }), }), ).toBe(true); expect( canForkProjectedAssistantItem({ projectedItem, capabilities: capabilities({ portableFork: true }), }), ).toBe(true); expect(canForkProjectedAssistantItem({ projectedItem })).toBe(true); expect( canForkProjectedAssistantItem({ projectedItem: { item: { type: "assistant_message", runId: "run", status: "running" }, } as never, }), ).toBe(false); }); it("merges the newest provider-finished run while checkpoint capture is pending", () => { const projection = { runs: [ { id: "newest-queued", status: "queued", ordinal: 3 }, { id: "older-completed", status: "completed", ordinal: 1 }, { id: "newest-finished", status: "waiting", ordinal: 2 }, ], } as never; expect(resolveLatestMergeBackRun(projection)?.id).toBe("newest-finished"); }); it("does not let a stale completed run later in storage order hide the waiting checkpoint", () => { const projection = { runs: [ { id: "newest-finished", status: "waiting", ordinal: 2 }, { id: "older-completed", status: "completed", ordinal: 1 }, ], } as never; expect(resolveLatestMergeBackRun(projection)?.id).toBe("newest-finished"); }); it.each(["preparing", "starting", "running"] as const)( "does not merge older history while a newer run is %s", (status) => { const projection = { runs: [ { id: "older-completed", status: "completed", ordinal: 1 }, { id: "newer-active", status, ordinal: 2 }, ], } as never; expect(resolveLatestMergeBackRun(projection)).toBeNull(); }, ); });