返回 DeepSeek-Reasonix
session-reader-mock.test.ts
根目录 / desktop / frontend / src / __tests__ / session-reader-mock.test.ts
1 import assert from "node:assert/strict";
2 import { JSDOM } from "jsdom";
3 import { canonicalHistorySlice, canonicalMessage } from "../lib/canonicalTranscriptBackend";
4 import { installDesktopHostStub } from "./desktopHostStub";
5 import { mockHistoryContentField, mockHistorySlice } from "../lib/bridgeHistoryFixtures";
6 import { makeMockSessionReaderBindings } from "../lib/sessionReaderBridge";
7 import type { HistoryContentRef, HistoryMessage, HistorySliceRequest } from "../lib/types";
8
9 const marker = "ASYNC LAYOUT EXPANSION COMPLETE";
10 const messages: HistoryMessage[] = [
11 { role: "user", content: "question", reasoning: "inline reasoning", toolCalls: [{ id: "call-1", name: "read", arguments: "{}" }] },
12 { role: "assistant", content: `${"preview ".repeat(700)}\n${marker}`, reasoning: "complete reasoning" },
13 ];
14 let contentReads = 0;
15 const host = Object.assign({
16 async HistoryForTab() { return messages; },
17 async HistorySliceForTab(tabID: string, req: HistorySliceRequest) { return mockHistorySlice(tabID, messages, req, true); },
18 async HistoryContentForTab(_tabID: string, ref: HistoryContentRef) {
19 contentReads += 1;
20 return { entryId: ref.entryId, field: ref.field, chunk: 0, chunks: 1, data: mockHistoryContentField(messages[1], ref), done: true, stale: false };
21 },
22 }, makeMockSessionReaderBindings());
23
24 const view = await host.SessionOpenForTab("tab-1");
25 assert.equal(view.recent.entries.length, 2);
26 const inline = canonicalMessage(view.recent.entries[0], view.recent.entries[0].inline);
27 assert.equal(inline.reasoning, "inline reasoning");
28 assert.equal(inline.toolCalls?.[0].id, "call-1");
29 const persistent = view.recent.entries[1];
30 assert.ok(persistent.contentRef, "lazy fixture keeps a canonical content reference");
31 assert.equal((persistent.inline as HistoryMessage | undefined)?.content.includes(marker), false, "open response contains only the legacy preview");
32
33 const chunk = await host.SessionHistoryContentForTab("tab-1", persistent.contentRef!, 0);
34 assert.equal(contentReads, 1, "canonical hydration preserves the legacy asynchronous read path");
35 const decoded = new TextDecoder().decode(Uint8Array.from(atob(chunk.data), character => character.charCodeAt(0)));
36 const hydrated = canonicalMessage(persistent, JSON.parse(decoded));
37 assert.equal(hydrated.messageId, persistent.messageId, "hydration keeps the stable message identity");
38 assert.ok(hydrated.content.includes(marker));
39 assert.equal(hydrated.reasoning, "complete reasoning");
40
41 const dom = new JSDOM("", { url: "http://localhost/" });
42 globalThis.window = dom.window as unknown as Window & typeof globalThis;
43 const stub = installDesktopHostStub({ SessionHistoryWindowForTab: async () => ({
44 messages: [{ ...view.recent.entries[0], position: 50, visibleTurn: 4 }], status: "ready", snapshotSequence: 0,
45 coverageSequence: 0, generation: "mock", totalTurns: 4, hasOlder: true, hasNewer: false, olderCursor: "older",
46 }) });
47 const limited = await canonicalHistorySlice("tab-1", { cursor: "" });
48 assert.equal(limited.entries.length, 1);
49 assert.equal(limited.hasOlder, true, "a byte-limited recent window still exposes older history");
50 assert.ok(limited.nextCursor);
51 assert.equal(limited.revisionKnown, false, "zero sequence does not invent a durable fingerprint");
52 stub.commands.SessionHistoryWindowForTab = async () => ({ messages: [], status: "ready", snapshotSequence: 0, coverageSequence: 0, totalTurns: 0, hasOlder: false, hasNewer: false });
53 const empty = await canonicalHistorySlice("tab-1", { cursor: "" });
54 assert.equal(empty.entries.length, 0, "an empty recent snapshot does not require a locator read");
55 stub.uninstall();
56 dom.window.close();
57
58 console.log("PASS protocol 7 mock sessions preserve benchmark history and lazy hydration");
59
59 lines TYPESCRIPT