| ... | @@ -0,0 +1,51 @@ |
| 1 | import { RunId } from "@t3tools/contracts"; |
| 2 | import { describe, expect, it } from "vite-plus/test"; |
| 3 | import { deriveMessagesTimelineRows, liveWorkEntryLabel } from "./MessagesTimeline.logic"; |
| 4 | |
| 5 | describe("long active tool groups", () => { |
| 6 | it.each([false, true])( |
| 7 | "preserves chronological order and the latest activity, expanded=%s", |
| 8 | (expanded) => { |
| 9 | const runId = RunId.make("long-active-run"); |
| 10 | const createdAt = "2026-10-12T00:00:00Z"; |
| 11 | const timelineEntries = Array.from({ length: 1_000 }, (_, index) => ({ |
| 12 | id: `work-entry-${index}`, |
| 13 | kind: "work" as const, |
| 14 | createdAt, |
| 15 | entry: { |
| 16 | id: `work-${index}`, |
| 17 | createdAt, |
| 18 | runId, |
| 19 | label: `Tool ${index}`, |
| 20 | tone: index % 2 === 0 ? ("thinking" as const) : ("tool" as const), |
| 21 | itemType: index % 2 === 0 ? ("reasoning" as const) : ("command_execution" as const), |
| 22 | ...(index % 2 === 0 ? { detail: `Thought ${index}` } : {}), |
| 23 | toolLifecycleStatus: index === 999 ? ("inProgress" as const) : ("completed" as const), |
| 24 | }, |
| 25 | })); |
| 26 | const rows = deriveMessagesTimelineRows({ |
| 27 | timelineEntries, |
| 28 | isWorking: true, |
| 29 | runningRunId: runId, |
| 30 | activeTurnStartedAt: createdAt, |
| 31 | turnDiffSummaries: [], |
| 32 | supportsConversationRollback: false, |
| 33 | expandedWorkGroupIds: new Set(expanded ? ["work-group:work-entry-0"] : []), |
| 34 | }); |
| 35 | const live = rows.find((row) => row.kind === "work-live"); |
| 36 | expect(live).toBeDefined(); |
| 37 | expect(live?.entry.id).toBe("work-999"); |
| 38 | expect(live && liveWorkEntryLabel(live.entry, undefined, live.active)).toContain("999"); |
| 39 | expect(live?.thought?.id).toBe("work-998"); |
| 40 | expect(live?.groupedEntries.map(({ id }) => id)).toEqual( |
| 41 | timelineEntries.map(({ entry }) => entry.id), |
| 42 | ); |
| 43 | expect(live?.groupId).toBe("work-group:work-entry-0"); |
| 44 | const details = rows.filter((row) => row.kind === "work"); |
| 45 | expect(details).toHaveLength(expanded ? 1 : 0); |
| 46 | if (expanded) { |
| 47 | expect(details[0]?.groupedEntries).toEqual(live?.groupedEntries); |
| 48 | } |
| 49 | }, |
| 50 | ); |
| 51 | }); |