import type { SessionMessageInfo } from "@opencode-ai/client/promise" import type { AssistantMessage, Message, Part, SessionStatus, UserMessage } from "@opencode-ai/sdk/v2" import { createMemo, type Accessor } from "solid-js" import { reuseTimelineRows } from "./row-reconciliation" import { Timeline, TimelineRow } from "./rows" export { reuseTimelineRows } from "./row-reconciliation" export function createTimelineProjection(input: { messages: Accessor userMessages: Accessor sessionMessages: Accessor parts: (messageID: string) => Part[] status: Accessor showReasoningSummaries: Accessor inlineComments: Accessor }) { const messageByID = createMemo(() => new Map(input.messages().map((message) => [message.id, message] as const))) const assistantMessagesByParent = createMemo(() => { const result = new Map() input.messages().forEach((message) => { if (message.role !== "assistant") return const messages = result.get(message.parentID) if (messages) { messages.push(message) return } result.set(message.parentID, [message]) }) return result }) const projection = createMemo(() => Timeline.constructSessionMessageRows( input.sessionMessages(), (messageID) => messageByID().get(messageID) as UserMessage | AssistantMessage | undefined, input.parts, input.showReasoningSummaries(), input.status().type, input.inlineComments(), input.userMessages(), ), ) const activeMessageID = createMemo(() => projection().activeMessageID) const rows = createMemo((previous: TimelineRow.TimelineRow[] | undefined) => reuseTimelineRows(previous, projection().rows), ) const rowByKey = createMemo(() => new Map(rows().map((row) => [TimelineRow.key(row), row] as const))) const messageRowIndex = createMemo(() => { const result = new Map() rows().forEach((row, index) => { if (!("userMessageID" in row) || result.has(row.userMessageID)) return result.set(row.userMessageID, index) }) return result }) const messageLastRowIndex = createMemo(() => { const result = new Map() rows().forEach((row, index) => { if ("userMessageID" in row) result.set(row.userMessageID, index) }) return result }) const lastAssistantGroupKey = createMemo(() => { const result = new Map() rows().forEach((row) => { if (row._tag === "AssistantPart") result.set(row.userMessageID, row.group.key) }) return result }) return { activeMessageID, assistantMessagesByParent, lastAssistantGroupKey, messageByID, messageRowIndex, messageLastRowIndex, rowByKey, rows, } }