Skip to content
Source
Sign inSign up

session-logic.runtime-diagnostics.test.ts

149 lines4.5 KB

1import { RunId, ThreadId, TurnItemId, type OrchestrationV2TurnItem } from "@t3tools/contracts";
2import * as DateTime from "effect/DateTime";
3import { describe, expect, it } from "vite-plus/test";
4​
5import { deriveTimelineEntriesFromVisibleTurnItems } from "./session-logic";
6import {
7 deriveMessagesTimelineRows,
8 workEntryDisplayLabel,
9} from "./components/chat/MessagesTimeline.logic";
10​
11const retainedMessage =
12 "2026-03-14T16:11:12.550224Z ERROR codex_core::codex: failed to load skill /home/sebherrerabe/repos/devsuite/.agent/skills/monorepo-scaffolding/SKILL.md: invalid YAML: mapping va...";
13const now = DateTime.makeUnsafe("2026-09-05T00:00:00.000Z");
14const baseItem = {
15 id: TurnItemId.make("diagnostic"),
16 threadId: ThreadId.make("thread-1"),
17 runId: RunId.make("run-1"),
18 nodeId: null,
19 providerThreadId: null,
20 providerTurnId: null,
21 nativeItemRef: null,
22 parentItemId: null,
23 ordinal: 0,
24 status: "completed" as const,
25 title: "Runtime error",
26 startedAt: now,
27 completedAt: now,
28 updatedAt: now,
29};
30​
31function workEntry(item: OrchestrationV2TurnItem) {
32 const [entry] = deriveTimelineEntriesFromVisibleTurnItems({
33 visibleTurnItems: [
34 {
35 position: 0,
36 visibility: "local",
37 sourceThreadId: item.threadId,
38 sourceItemId: item.id,
39 item,
40 },
41 ],
42 optimisticMessages: [],
43 });
44 if (entry?.kind !== "work") throw new Error("Expected a work-log entry");
45 return entry.entry;
47​
48function errorItem(
49 overrides: Partial<Extract<OrchestrationV2TurnItem, { type: "error" }>> = {},
50): Extract<OrchestrationV2TurnItem, { type: "error" }> {
51 return {
52 ...baseItem,
53 type: "error",
54 failure: {
55 class: "provider_error",
56 message: retainedMessage,
57 code: "runtime_error",
58 retryable: false,
59 },
60 ...overrides,
61 };
63​
64describe("runtime diagnostics in the v2 work log", () => {
65 it("shows the retained error message in place of a generic row label", () => {
66 const entry = workEntry(errorItem());
67​
68 expect(entry).toMatchObject({ label: "Runtime error", detail: retainedMessage });
69 expect(workEntryDisplayLabel(entry, undefined)).toBe(retainedMessage);
70 });
71​
72 it("keeps retry progress visible while retaining its diagnostic detail", () => {
73 const entry = workEntry(
74 errorItem({
75 title: "Provider retry",
76 status: "running",
77 retry: { attempt: 2, maxAttempts: 5, retryDelayMs: 1_500 },
78 }),
79 );
80​
81 expect(workEntryDisplayLabel(entry, undefined)).toBe("Retrying provider (2/5)");
82 expect(entry.detail).toBe(`${retainedMessage} Retrying in 1.5s.`);
83 });
84​
85 it("keeps a diagnostic separate from adjacent tool summaries", () => {
86 const entries = deriveTimelineEntriesFromVisibleTurnItems({
87 visibleTurnItems: [
88 {
89 ...baseItem,
90 type: "command_execution" as const,
91 id: TurnItemId.make("command-before"),
92 input: "git status",
93 output: "clean",
94 exitCode: 0,
95 },
96 errorItem(),
97 {
98 ...baseItem,
99 type: "command_execution" as const,
100 id: TurnItemId.make("command-after"),
101 input: "git diff",
102 output: "",
103 exitCode: 0,
104 },
105 ].map((item, position) => ({
106 position,
107 visibility: "local" as const,
108 sourceThreadId: item.threadId,
109 sourceItemId: item.id,
110 item,
111 })),
112 optimisticMessages: [],
113 });
114 const rows = deriveMessagesTimelineRows({
115 timelineEntries: entries,
116 isWorking: true,
117 activeTurnStartedAt: DateTime.formatIso(now),
118 latestRun: {
119 runId: baseItem.runId,
120 status: "running",
121 startedAt: DateTime.formatIso(now),
122 completedAt: null,
123 },
124 turnDiffSummaries: [],
125 supportsConversationRollback: false,
126 });
127 const diagnostic = rows.find((row) => row.id === baseItem.id);
128​
129 expect(diagnostic?.kind).toBe("work");
130 if (diagnostic?.kind !== "work") throw new Error("Expected a diagnostic row");
131 expect(diagnostic.isExpandedToolGroup).toBe(false);
132 expect(diagnostic.groupedEntries).toHaveLength(1);
133 expect(workEntryDisplayLabel(diagnostic.groupedEntries[0]!, undefined)).toBe(retainedMessage);
134 });
135​
136 it("does not turn an unrelated tool payload message into a diagnostic", () => {
137 const entry = workEntry({
138 ...baseItem,
139 type: "dynamic_tool",
140 title: "Read file",
141 toolName: "read_file",
142 input: {},
143 output: { message: retainedMessage },
144 });
145​
146 expect(entry.label).toBe("Read file");
147 expect(entry.detail).toBeUndefined();
148 });
149});