79 lines
2.7 KiB
TypeScript
79 lines
2.7 KiB
TypeScript
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<Message[]>
|
|
sessionMessages: Accessor<SessionMessageInfo[]>
|
|
parts: (messageID: string) => Part[]
|
|
status: Accessor<SessionStatus>
|
|
showReasoningSummaries: Accessor<boolean>
|
|
inlineComments: Accessor<boolean>
|
|
}) {
|
|
const messageByID = createMemo(() => new Map(input.messages().map((message) => [message.id, message] as const)))
|
|
const assistantMessagesByParent = createMemo(() => {
|
|
const result = new Map<string, AssistantMessage[]>()
|
|
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(),
|
|
),
|
|
)
|
|
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<string, number>()
|
|
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<string, number>()
|
|
rows().forEach((row, index) => {
|
|
if ("userMessageID" in row) result.set(row.userMessageID, index)
|
|
})
|
|
return result
|
|
})
|
|
const lastAssistantGroupKey = createMemo(() => {
|
|
const result = new Map<string, string>()
|
|
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,
|
|
}
|
|
}
|