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(); }, );});
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();
},
);
});