| 1 | import type { |
| 2 | OrchestrationV2Run, |
| 3 | OrchestrationV2RunAttempt, |
| 4 | OrchestrationV2TurnItem, |
| 5 | OrchestrationV2UserMessageInputIntent, |
| 6 | } from "@t3tools/contracts"; |
| 7 | |
| 8 | type TimelineRun = Pick<OrchestrationV2Run, "id" | "status">; |
| 9 | type TimelineRunAttempt = Pick<OrchestrationV2RunAttempt, "runId" | "rootNodeId" | "status">; |
| 10 | type TimelineTurnItem = Pick<OrchestrationV2TurnItem, "type" | "runId" | "nodeId"> & { |
| 11 | readonly inputIntent?: OrchestrationV2UserMessageInputIntent; |
| 12 | }; |
| 13 | |
| 14 | export function isOrchestrationV2SupersededInterrupt(input: { |
| 15 | readonly item: TimelineTurnItem; |
| 16 | readonly attempts: ReadonlyArray<TimelineRunAttempt>; |
| 17 | readonly items: ReadonlyArray<TimelineTurnItem>; |
| 18 | }): boolean { |
| 19 | const { item } = input; |
| 20 | if (item.type !== "run_interrupt_result" || item.runId === null || item.nodeId === null) { |
| 21 | return false; |
| 22 | } |
| 23 | |
| 24 | const isSuperseded = input.attempts.some( |
| 25 | (attempt) => |
| 26 | attempt.runId === item.runId && |
| 27 | attempt.rootNodeId === item.nodeId && |
| 28 | attempt.status === "superseded", |
| 29 | ); |
| 30 | if (!isSuperseded) { |
| 31 | return false; |
| 32 | } |
| 33 | |
| 34 | // Paired stop-then-steer results have a matching request on the same run and |
| 35 | // must stay visible. Legacy plain-steer results have no request and stay hidden. |
| 36 | const hasMatchingRequest = input.items.some( |
| 37 | (candidate) => candidate.type === "run_interrupt_request" && candidate.runId === item.runId, |
| 38 | ); |
| 39 | return !hasMatchingRequest; |
| 40 | } |
| 41 | |
| 42 | export function isOrchestrationV2TurnItemVisible(input: { |
| 43 | readonly item: TimelineTurnItem; |
| 44 | readonly runs: ReadonlyArray<TimelineRun>; |
| 45 | readonly attempts: ReadonlyArray<TimelineRunAttempt>; |
| 46 | readonly items: ReadonlyArray<TimelineTurnItem>; |
| 47 | }): boolean { |
| 48 | const { item } = input; |
| 49 | if ( |
| 50 | item.runId !== null && |
| 51 | input.runs.some((run) => run.id === item.runId && run.status === "rolled_back") |
| 52 | ) { |
| 53 | return false; |
| 54 | } |
| 55 | |
| 56 | // A queued message is composer state, not conversation history. When its run |
| 57 | // is cancelled the input never reached the provider, so it must not surface |
| 58 | // as a transcript row. |
| 59 | if ( |
| 60 | item.type === "user_message" && |
| 61 | item.inputIntent === "queued_turn" && |
| 62 | item.runId !== null && |
| 63 | input.runs.some((run) => run.id === item.runId && run.status === "cancelled") |
| 64 | ) { |
| 65 | return false; |
| 66 | } |
| 67 | |
| 68 | return !isOrchestrationV2SupersededInterrupt({ |
| 69 | item, |
| 70 | attempts: input.attempts, |
| 71 | items: input.items, |
| 72 | }); |
| 73 | } |
| 74 | |
| 75 | /** Index once when reconciling a whole timeline after run/attempt state changes. */ |
| 76 | export function createOrchestrationV2TurnItemVisibility(input: { |
| 77 | readonly runs: ReadonlyArray<TimelineRun>; |
| 78 | readonly attempts: ReadonlyArray<TimelineRunAttempt>; |
| 79 | readonly items: ReadonlyArray<TimelineTurnItem>; |
| 80 | }): (item: TimelineTurnItem) => boolean { |
| 81 | const statuses = new Map(input.runs.map((run) => [run.id, run.status])); |
| 82 | const supersededRoots = new Map< |
| 83 | TimelineRunAttempt["runId"], |
| 84 | Set<TimelineRunAttempt["rootNodeId"]> |
| 85 | >(); |
| 86 | for (const attempt of input.attempts) { |
| 87 | if (attempt.status !== "superseded") continue; |
| 88 | let roots = supersededRoots.get(attempt.runId); |
| 89 | if (roots === undefined) supersededRoots.set(attempt.runId, (roots = new Set())); |
| 90 | roots.add(attempt.rootNodeId); |
| 91 | } |
| 92 | const interruptRuns = new Set( |
| 93 | input.items.filter((item) => item.type === "run_interrupt_request").map((item) => item.runId), |
| 94 | ); |
| 95 | return (item) => { |
| 96 | const status = item.runId === null ? undefined : statuses.get(item.runId); |
| 97 | if (status === "rolled_back") return false; |
| 98 | if ( |
| 99 | status === "cancelled" && |
| 100 | item.type === "user_message" && |
| 101 | item.inputIntent === "queued_turn" |
| 102 | ) |
| 103 | return false; |
| 104 | return !( |
| 105 | item.type === "run_interrupt_result" && |
| 106 | item.runId !== null && |
| 107 | item.nodeId !== null && |
| 108 | supersededRoots.get(item.runId)?.has(item.nodeId) === true && |
| 109 | !interruptRuns.has(item.runId) |
| 110 | ); |
| 111 | }; |
| 112 | } |