import { parseFlatEntry, parseState } from "./store-file.ts"; import type { BtwStateV1, FlatEntry, FlatThread } from "./threads.ts"; export type BtwDelta = | { v: 1; op: "thread-created"; thread: FlatThread } | { v: 1; op: "entry-appended"; threadId: string; entry: FlatEntry } | { v: 1; op: "active-set"; threadId: string } | { v: 1; op: "promoted"; threadId: string; entryId: string }; type SessionEntryLike = { type?: string; customType?: string; data?: unknown }; export const emptyState = (): BtwStateV1 => ({ version: 1, threads: [] }); export function applyDelta(state: BtwStateV1, delta: unknown): void { if (typeof delta !== "object" || delta === null) return; const d = delta as Record; switch (d.op) { case "thread-created": { if (d.v !== 1) return; const thread = parseState({ version: 1, threads: [d.thread] }, 1)?.threads[0]; if (!thread || state.threads.some((item) => item.id === thread.id)) return; state.threads.push(thread); state.activeThreadId = thread.id; return; } case "entry-appended": { if (d.v !== 1 || !d.threadId || typeof d.threadId !== "string") return; const entry = parseFlatEntry(d.entry); if (!entry) return; let thread = state.threads.find((item) => item.id === d.threadId); if (!thread) { thread = { id: d.threadId, createdAt: "", entries: [] }; state.threads.push(thread); } if (!thread.entries.some((item) => item.id === entry.id)) thread.entries.push(entry); return; } case "active-set": if (d.v === 1 && typeof d.threadId === "string" && state.threads.some((item) => item.id === d.threadId)) state.activeThreadId = d.threadId; return; case "promoted": { if (d.v !== 1 || typeof d.threadId !== "string" || typeof d.entryId !== "string") return; const entry = state.threads.find((item) => item.id === d.threadId)?.entries.find((item) => item.id === d.entryId); if (entry) entry.promoted = true; return; } } } export function reconstructFromEntries(entries: readonly SessionEntryLike[]): { state: BtwStateV1; deltasSinceSnapshot: number } { let state = emptyState(), deltasSinceSnapshot = 0; for (const entry of entries) { if (!entry || entry.type !== "custom") continue; if (entry.customType === "btw-state") { const snapshot = parseState(entry.data, 1); if (snapshot?.version === 1) { state = snapshot; deltasSinceSnapshot = 0; } } else if (entry.customType === "btw-delta") { try { applyDelta(state, entry.data); } catch {} deltasSinceSnapshot++; } } const validated = parseState(state, 1); return { state: validated && validated.version === 1 ? validated : emptyState(), deltasSinceSnapshot }; }