import { describe, expect, test } from "bun:test" import type { Message, OpencodeClient, Part } from "@opencode-ai/sdk/v2/client" import { ChildStoreManager } from "./child-store" import { SessionMessageLoader } from "./session-message-loader" import { createFirstVisibleSessionPerformanceTracker, startSessionLoadPerformanceEvent, } from "./session-load-performance" const createRecord = (sessionID: string, id = "msg_1", created = 1) => ({ info: { id, sessionID, role: "user", time: { created } } as Message, parts: [{ id: `part_${id}`, messageID: id, sessionID, type: "text", text: "hello" }] as Part[], }) const deferred = () => { let resolve!: (value: T) => void const promise = new Promise((next) => { resolve = next }) return { promise, resolve } } const response = (data: ReturnType[], cursor?: string) => ({ data, response: { headers: { get: (name: string) => name === "x-next-cursor" ? cursor ?? null : null } }, }) const createLoader = (messages: (input: { sessionID: string directory?: string limit?: number before?: string }) => Promise) => { const childStores = new ChildStoreManager() const sdk = { session: { messages } } as unknown as OpencodeClient const loader = new SessionMessageLoader(childStores, { sdk, runtimeKey: "runtime-a" }) return { childStores, loader } } describe("SessionMessageLoader", () => { test("deduplicates navigation and reactive loading for the same target", async () => { const pending = deferred>() let calls = 0 const { childStores, loader } = createLoader(async () => { calls += 1 return pending.promise }) const target = { directory: "/repo", sessionID: "session-a" } const navigation = loader.ensure(target, { reason: "navigation" }) const reactive = loader.ensure(target, { reason: "reactive" }) expect(calls).toBe(1) pending.resolve(response([createRecord(target.sessionID)])) await Promise.all([navigation, reactive]) expect(loader.getSnapshot(target).status).toBe("ready") expect(childStores.getChild(target.directory)?.getState().message[target.sessionID]?.length).toBe(1) loader.dispose() childStores.disposeAll() }) test("leaves older history loading to explicit viewport demand", async () => { const calls: Array<{ limit?: number; before?: string }> = [] const { childStores, loader } = createLoader(async ({ sessionID, limit, before }) => { calls.push({ limit, before }) return before ? response([createRecord(sessionID, "msg_older", 1)]) : response([createRecord(sessionID, "msg_latest", 2)], "older-cursor") }) const target = { directory: "/repo", sessionID: "session-a" } await loader.ensure(target, { reason: "prefetch" }) await Promise.resolve() expect(calls).toEqual([{ limit: 50, before: undefined }]) expect(loader.getSnapshot(target).cursor).toBe("older-cursor") await loader.loadOlder(target) expect(calls).toEqual([ { limit: 50, before: undefined }, { limit: 100, before: "older-cursor" }, ]) expect(childStores.getChild(target.directory)?.getState().message[target.sessionID]?.map((message) => message.id)) .toEqual(["msg_older", "msg_latest"]) loader.dispose() childStores.disposeAll() }) test("keeps a post-rollover tail after legacy messages for shared runtime identities", async () => { const runtimes = ["web", "desktop", "vscode", "mobile"] for (const runtimeKey of runtimes) { const childStores = new ChildStoreManager() const sdk = { session: { messages: async ({ sessionID }: { sessionID: string }) => response([ createRecord(sessionID, "msg_000000000000Current", 200), createRecord(sessionID, "msg_ffffffffffffLegacy", 100), ]), }, } as unknown as OpencodeClient const loader = new SessionMessageLoader(childStores, { sdk, runtimeKey }) const target = { directory: `/repo-${runtimeKey}`, sessionID: "session-a" } await loader.ensure(target) expect(childStores.getChild(target.directory)?.getState().message[target.sessionID]?.map((message) => message.id)) .toEqual(["msg_ffffffffffffLegacy", "msg_000000000000Current"]) loader.dispose() childStores.disposeAll() } }) test("loads every history page for an explicit complete-history request", async () => { const calls: Array<{ before?: string }> = [] const { childStores, loader } = createLoader(async ({ sessionID, before }) => { calls.push({ before }) if (!before) return response([createRecord(sessionID, "msg_latest")], "cursor-2") if (before === "cursor-2") return response([createRecord(sessionID, "msg_middle")], "cursor-1") return response([createRecord(sessionID, "msg_oldest")]) }) const target = { directory: "/repo", sessionID: "session-a" } await loader.loadComplete(target) expect(calls).toEqual([ { before: undefined }, { before: "cursor-2" }, { before: "cursor-1" }, ]) expect(loader.getSnapshot(target).complete).toBe(true) expect(childStores.getChild(target.directory)?.getState().message[target.sessionID]).toHaveLength(3) loader.dispose() childStores.disposeAll() }) test("rejects a complete-history request when its initial load fails", async () => { const { childStores, loader } = createLoader(async () => ({ error: { message: "rejected" }, response: { status: 400 }, })) const target = { directory: "/repo", sessionID: "session-a" } await expect(loader.loadComplete(target)).rejects.toThrow("session.messages failed (400): rejected") loader.dispose() childStores.disposeAll() }) test("rejects a complete-history request when an older page fails", async () => { const { childStores, loader } = createLoader(async ({ sessionID, before }) => before ? { error: { message: "older rejected" }, response: { status: 400 } } : response([createRecord(sessionID)], "older-cursor")) const target = { directory: "/repo", sessionID: "session-a" } await expect(loader.loadComplete(target)).rejects.toThrow("session.messages failed (400): older rejected") expect(loader.getSnapshot(target).cursor).toBe("older-cursor") loader.dispose() childStores.disposeAll() }) test("fetches authoritative coverage when renderable messages have no loader metadata", async () => { let calls = 0 const { childStores, loader } = createLoader(async ({ sessionID }) => { calls += 1 return response([createRecord(sessionID)]) }) const target = { directory: "/repo", sessionID: "session-a" } childStores.ensureChild(target.directory, { bootstrap: false }).setState({ message: { [target.sessionID]: [createRecord(target.sessionID, "cached").info] }, }) await loader.loadComplete(target) expect(calls).toBe(1) expect(loader.getSnapshot(target).complete).toBe(true) loader.dispose() childStores.disposeAll() }) test("rejects repeated pagination cursors instead of looping forever", async () => { let calls = 0 const { childStores, loader } = createLoader(async ({ sessionID, before }) => { calls += 1 if (!before) return response([createRecord(sessionID, "latest")], "cursor-a") if (before === "cursor-a") return response([createRecord(sessionID, "middle")], "cursor-b") return response([createRecord(sessionID, "older")], "cursor-a") }) const target = { directory: "/repo", sessionID: "session-a" } await expect(loader.loadComplete(target)).rejects.toThrow("Session history pagination made no progress") expect(calls).toBe(3) loader.dispose() childStores.disposeAll() }) test("runs a requested tail refresh after an older in-flight load", async () => { const initial = deferred>() const refresh = deferred>() let calls = 0 const limits: number[] = [] const { childStores, loader } = createLoader(async ({ limit }) => { calls += 1 limits.push(limit ?? 0) return calls === 1 ? initial.promise : refresh.promise }) const target = { directory: "/repo", sessionID: "session-a" } const loading = loader.ensure(target, { reason: "navigation" }) const refreshing = loader.refreshTail(target, 30) const duplicateRefresh = loader.refreshTail(target, 80) expect(calls).toBe(1) expect(duplicateRefresh).toBe(refreshing) initial.resolve(response([createRecord(target.sessionID, "msg_1")])) await loading await Promise.resolve() expect(calls).toBe(2) expect(limits).toEqual([50, 80]) refresh.resolve(response([createRecord(target.sessionID, "msg_2")])) await Promise.all([refreshing, duplicateRefresh]) expect(childStores.getChild(target.directory)?.getState().message[target.sessionID]?.map((message) => message.id)) .toEqual(["msg_1", "msg_2"]) loader.dispose() childStores.disposeAll() }) test("preserves complete history coverage across a tail refresh", async () => { let calls = 0 const { childStores, loader } = createLoader(async ({ sessionID }) => { calls += 1 return calls === 1 ? response([createRecord(sessionID, "msg_1")]) : response([createRecord(sessionID, "msg_2")], "stale-tail-cursor") }) const target = { directory: "/repo", sessionID: "session-a" } await loader.ensure(target) expect(loader.getSnapshot(target).complete).toBe(true) expect(loader.getSnapshot(target).cursor).toBe(undefined) await loader.refreshTail(target, 2) expect(loader.getSnapshot(target).complete).toBe(true) expect(loader.getSnapshot(target).cursor).toBe(undefined) loader.dispose() childStores.disposeAll() }) test("does not deduplicate identical session IDs across directories", async () => { const calls: string[] = [] const { childStores, loader } = createLoader(async ({ directory, sessionID }) => { calls.push(directory ?? "") return response([createRecord(sessionID)]) }) await Promise.all([ loader.ensure({ directory: "/repo-a", sessionID: "shared" }), loader.ensure({ directory: "/repo-b", sessionID: "shared" }), ]) expect(calls.sort()).toEqual(["/repo-a", "/repo-b"]) loader.dispose() childStores.disposeAll() }) test("loads older history with the selected directory's cursor for duplicate session IDs", async () => { const providerDirectory = "/repo/provider" const selectedDirectory = "/repo/selected-worktree" const sessionID = "shared" const calls: Array<{ directory?: string; before?: string }> = [] const { childStores, loader } = createLoader(async ({ directory, before }) => { calls.push({ directory, before }) return before ? response([createRecord(sessionID, `older-${directory}`)]) : response([createRecord(sessionID, `latest-${directory}`)], `${directory}-cursor`) }) await Promise.all([ loader.ensure({ directory: providerDirectory, sessionID }), loader.ensure({ directory: selectedDirectory, sessionID }), ]) calls.length = 0 await loader.loadOlder({ directory: selectedDirectory, sessionID }) expect(calls).toEqual([{ directory: selectedDirectory, before: `${selectedDirectory}-cursor`, }]) loader.dispose() childStores.disposeAll() }) test("exposes a retryable error without clearing an existing snapshot", async () => { let fail = true const { childStores, loader } = createLoader(async ({ sessionID }) => { if (fail) return { error: { message: "rejected" }, response: { status: 400 } } return response([createRecord(sessionID)]) }) const target = { directory: "/repo", sessionID: "session-a" } const store = childStores.ensureChild(target.directory, { bootstrap: false }) store.setState({ message: { [target.sessionID]: [{ id: "cached", sessionID: target.sessionID, role: "user", time: { created: 0 } } as Message] } }) await loader.ensure(target, { force: true }) expect(loader.getSnapshot(target).status).toBe("error") expect((loader.getSnapshot(target).error as Error & { status?: number }).status).toBe(400) expect(store.getState().message[target.sessionID]?.[0]?.id).toBe("cached") fail = false await loader.ensure(target, { force: true }) expect(loader.getSnapshot(target).status).toBe("ready") loader.dispose() childStores.disposeAll() }) test("propagates a zero response status on SDK errors", async () => { const { childStores, loader } = createLoader(async () => ({ error: { message: "network rejected" }, response: { status: 0 }, })) const target = { directory: "/repo", sessionID: "session-a" } await loader.ensure(target, { force: true }) expect((loader.getSnapshot(target).error as Error & { status?: number }).status).toBe(0) loader.dispose() childStores.disposeAll() }) test("prevents an evicted in-flight request from repopulating the store", async () => { const pending = deferred>() const { childStores, loader } = createLoader(async () => pending.promise) const target = { directory: "/repo", sessionID: "session-a" } const loading = loader.ensure(target) loader.invalidateSession(target) pending.resolve(response([createRecord(target.sessionID)])) await loading expect(childStores.getChild(target.directory)?.getState().message[target.sessionID]).toBe(undefined) expect(loader.getSnapshot(target).status).toBe("idle") loader.dispose() childStores.disposeAll() }) test("treats an empty successful response as resolved authoritative state", async () => { const { childStores, loader } = createLoader(async () => response([])) const target = { directory: "/repo", sessionID: "empty" } await loader.ensure(target) expect(loader.getSnapshot(target).resolved).toBe(true) expect(loader.getSnapshot(target).complete).toBe(true) expect(childStores.getChild(target.directory)?.getState().message[target.sessionID]).toEqual([]) loader.dispose() childStores.disposeAll() }) test("retries a missing message payload instead of treating it as an empty snapshot", async () => { let calls = 0 const { childStores, loader } = createLoader(async ({ sessionID }) => { calls += 1 return calls === 1 ? {} : response([createRecord(sessionID)]) }) const target = { directory: "/repo", sessionID: "session-a" } await loader.ensure(target) expect(calls).toBe(2) expect(loader.getSnapshot(target).status).toBe("ready") expect(childStores.getChild(target.directory)?.getState().message[target.sessionID]?.length).toBe(1) loader.dispose() childStores.disposeAll() }) test("reports retries and every downloaded initial expansion record", async () => { const originalWindow = Object.getOwnPropertyDescriptor(globalThis, "window") const diagnosticWindow = { location: { search: "" }, localStorage: { getItem: (key: string) => key === "openchamber_session_load_perf" ? "1" : null, }, } as unknown as Window Object.defineProperty(globalThis, "window", { configurable: true, value: diagnosticWindow }) const target = { directory: "/repo", sessionID: "session-a" } let calls = 0 const { childStores, loader } = createLoader(async () => { calls += 1 if (calls === 1) return {} if (calls === 2) { const assistant = createRecord(target.sessionID, "msg_assistant") assistant.info = { ...assistant.info, role: "assistant" } as Message return response([assistant], "older") } return response([createRecord(target.sessionID, "msg_user")]) }) try { await loader.ensure(target) const events = diagnosticWindow.__openchamberSessionLoadPerformance?.events ?? [] const initialEvent = events.find((event) => event.operation === "session-messages.initial") const pageEvents = events.filter((event) => event.operation === "session-messages.page") expect(calls).toBe(3) expect(pageEvents.map((event) => event.requestLimit)).toEqual([50, 100]) expect(pageEvents.map((event) => event.cursorPresent)).toEqual([false, false]) expect(pageEvents.map((event) => event.recordCount)).toEqual([1, 1]) expect(initialEvent?.outcome).toBe("complete") expect(initialEvent?.retryCount).toBe(1) expect(initialEvent?.recordCount).toBe(2) expect("runtimeKey" in initialEvent!).toBe(false) expect("directory" in initialEvent!).toBe(false) expect("sessionID" in initialEvent!).toBe(false) } finally { loader.dispose() childStores.disposeAll() if (originalWindow) Object.defineProperty(globalThis, "window", originalWindow) else Reflect.deleteProperty(globalThis, "window") } }) }) describe("session load performance diagnostics", () => { test("rejects unknown raw labels and preserves approved input counts", () => { const originalWindow = Object.getOwnPropertyDescriptor(globalThis, "window") const diagnosticWindow = { localStorage: { getItem: (key: string) => key === "openchamber_session_load_perf" ? "1" : null, }, } as unknown as Window Object.defineProperty(globalThis, "window", { configurable: true, value: diagnosticWindow }) try { const finishUnknown = startSessionLoadPerformanceEvent({ operation: "secret-operation", caller: "secret-caller", recordCount: 999, }) finishUnknown("complete") const finishVisible = startSessionLoadPerformanceEvent({ operation: "session-messages.visible", caller: "selected-session", recordCount: 30, }) finishVisible("complete") expect(diagnosticWindow.__openchamberSessionLoadPerformance?.events).toHaveLength(1) const event = diagnosticWindow.__openchamberSessionLoadPerformance?.events[0] expect(event?.operation).toBe("session-messages.visible") expect(event?.caller).toBe("selected-session") expect(event?.recordCount).toBe(30) expect(JSON.stringify(diagnosticWindow.__openchamberSessionLoadPerformance)).not.toContain("secret") } finally { if (originalWindow) Object.defineProperty(globalThis, "window", originalWindow) else Reflect.deleteProperty(globalThis, "window") } }) test("does not schedule visibility work while diagnostics are disabled", () => { let requestedFrames = 0 let visibleMarks = 0 const tracker = createFirstVisibleSessionPerformanceTracker({ enabled: () => false, requestFrame: () => { requestedFrames += 1 return 1 }, cancelFrame: () => undefined, markVisible: () => { visibleMarks += 1 }, }) tracker.schedule("session-a", 10) expect(requestedFrames).toBe(0) expect(visibleMarks).toBe(0) }) test("reschedules an identity when its pending visibility frame was canceled", () => { let nextFrame = 0 const frames = new Map() const marks: string[] = [] const tracker = createFirstVisibleSessionPerformanceTracker({ enabled: () => true, requestFrame: (callback) => { nextFrame += 1 frames.set(nextFrame, callback) return nextFrame }, cancelFrame: (frame) => { frames.delete(frame) }, markVisible: () => marks.push("visible"), startEvent: () => () => undefined, }) const cancelFirstA = tracker.schedule("session-a", 10) cancelFirstA() const cancelB = tracker.schedule("session-b", 10) cancelB() tracker.schedule("session-a", 10) frames.get(3)?.(0) expect(marks).toEqual(["visible"]) }) test("does not remeasure a completed identity after another session", () => { let nextFrame = 0 const frames = new Map() const marks: string[] = [] const tracker = createFirstVisibleSessionPerformanceTracker({ enabled: () => true, requestFrame: (callback) => { nextFrame += 1 frames.set(nextFrame, callback) return nextFrame }, cancelFrame: (frame) => { frames.delete(frame) }, markVisible: () => marks.push("visible"), startEvent: () => () => undefined, }) tracker.schedule("session-a", 10) frames.get(1)?.(0) tracker.schedule("session-b", 10) frames.get(2)?.(0) tracker.schedule("session-a", 10) expect(nextFrame).toBe(2) expect(marks).toEqual(["visible", "visible"]) }) })