1import {
2 RunId,
3 ThreadId,
4 TurnItemId,
5 type OrchestrationV2ProjectedTurnItem,
6 type OrchestrationV2ThreadProjection,
7 type OrchestrationV2TurnItem,
8} from "@t3tools/contracts";
9import { describe, expect, it } from "vite-plus/test";
10
11import {
12 boundedSnapshotProjection,
13 omitLocalVisibleTurnItems,
14 restoreLocalVisibleTurnItems,
15} from "./orchestrationV2BoundedSnapshot.ts";
16
17const PARENT = ThreadId.make("thread:compact-parent");
18const CHILD = ThreadId.make("thread:compact-child");
19const RUN = RunId.make("run:compact");
20
21function item(
22 threadId: ThreadId,
23 id: string,
24 ordinal: number,
25 type: "command_execution" | "run_interrupt_request" | "fork" = "command_execution",
26): OrchestrationV2TurnItem {
27 return {
28 id: TurnItemId.make(id),
29 type,
30 threadId,
31 runId: type === "command_execution" ? null : RUN,
32 nodeId: null,
33 providerThreadId: null,
34 providerTurnId: null,
35 nativeItemRef: null,
36 parentItemId: null,
37 ordinal,
38 status: "completed",
39 title: id,
40 input: id,
41 exitCode: 0,
42 startedAt: null,
43 completedAt: null,
44 updatedAt: "2026-10-01T00:00:00.000Z",
45 } as unknown as OrchestrationV2TurnItem;
46}
47
48function row(
49 visibility: OrchestrationV2ProjectedTurnItem["visibility"],
50 sourceThreadId: ThreadId,
51 value: OrchestrationV2TurnItem,
52): Omit<OrchestrationV2ProjectedTurnItem, "position"> {
53 return { visibility, sourceThreadId, sourceItemId: value.id, item: value };
54}
55
56function projection(input: {
57 readonly visible: ReadonlyArray<Omit<OrchestrationV2ProjectedTurnItem, "position">>;
58 readonly turnItems: ReadonlyArray<OrchestrationV2TurnItem>;
59}): OrchestrationV2ThreadProjection {
60 return {
61 thread: { id: CHILD },
62 turnItems: [...input.turnItems],
63 visibleTurnItems: input.visible.map((value, position) => ({ ...value, position })),
64 } as unknown as OrchestrationV2ThreadProjection;
65}
66
67/** Fork child: inherited parent rows, synthetic marker, local rows, retained interrupt request. */
68function forkWindow() {
69 const inherited = [item(PARENT, "parent-1", 1), item(PARENT, "parent-2", 2)];
70 const marker = item(PARENT, "fork-marker", 3, "fork");
71 const local = [item(CHILD, "child-1", 1), item(CHILD, "child-2", 2), item(CHILD, "child-3", 3)];
72 const retainedRequest = item(CHILD, "interrupt-request", 0, "run_interrupt_request");
73 return {
74 local,
75 retainedRequest,
76 projection: projection({
77 visible: [
78 ...inherited.map((value) => row("inherited", PARENT, value)),
79 row("synthetic", PARENT, marker),
80 ...local.map((value) => row("local", CHILD, value)),
81 ],
82 turnItems: [...local, retainedRequest],
83 }),
84 };
85}
86
87describe("compact bounded snapshot turnItems", () => {
88 it("omits only local visible items and restores the exact list and order", () => {
89 const { projection: full, local, retainedRequest } = forkWindow();
90 const compact = omitLocalVisibleTurnItems(full);
91
92 expect(compact).not.toBeNull();
93 // Inherited and synthetic rows never had turnItems; the retained request stays.
94 expect(compact!.turnItems).toEqual([retainedRequest]);
95 expect(compact!.visibleTurnItems).toBe(full.visibleTurnItems);
96
97 const restored = restoreLocalVisibleTurnItems(compact!);
98 expect(restored.turnItems).toEqual([...local, retainedRequest]);
99 expect(restored).toEqual(full);
100 });
101
102 it("round-trips through JSON as a separately decoded client would see it", () => {
103 const { projection: full } = forkWindow();
104 const wire = JSON.parse(JSON.stringify(omitLocalVisibleTurnItems(full)));
105 expect(
106 boundedSnapshotProjection({ projection: wire, turnItemsOmitLocalVisible: true }),
107 ).toEqual(JSON.parse(JSON.stringify(full)));
108 });
109
110 it("treats rows sourced from the thread itself as local", () => {
111 const own = item(CHILD, "own", 1);
112 const full = projection({ visible: [row("inherited", CHILD, own)], turnItems: [own] });
113 const compact = omitLocalVisibleTurnItems(full);
114 expect(compact?.turnItems).toEqual([]);
115 expect(restoreLocalVisibleTurnItems(compact!)).toEqual(full);
116 });
117
118 it("refuses shapes it cannot restore exactly", () => {
119 const [first, second] = [item(CHILD, "a", 1), item(CHILD, "b", 2)];
120 const visible = [row("local", CHILD, first), row("local", CHILD, second)];
121 // Different order than the visible rows.
122 expect(omitLocalVisibleTurnItems(projection({ visible, turnItems: [second, first] }))).toBe(
123 null,
124 );
125 // Equal content but a different object: restoring would not be provably exact.
126 expect(
127 omitLocalVisibleTurnItems(projection({ visible, turnItems: [{ ...first }, second] })),
128 ).toBe(null);
129 // A local row without its turn item.
130 expect(omitLocalVisibleTurnItems(projection({ visible, turnItems: [first] }))).toBe(null);
131 });
132
133 it("sends nothing compact when no local rows are visible", () => {
134 const inherited = item(PARENT, "parent", 1);
135 const request = item(CHILD, "interrupt-request", 0, "run_interrupt_request");
136 expect(
137 omitLocalVisibleTurnItems(
138 projection({ visible: [row("inherited", PARENT, inherited)], turnItems: [request] }),
139 ),
140 ).toBe(null);
141 });
142
143 it("leaves unmarked snapshots untouched", () => {
144 const { projection: full } = forkWindow();
145 expect(boundedSnapshotProjection({ projection: full })).toBe(full);
146 });
147});