



















@@ -9,6 +9,27 @@ import {
991010const j = (obj: unknown): string => `${JSON.stringify(obj)}\n`;
111112+type ReplayRecord = {
13+type?: string;
14+id?: string;
15+message?: {
16+role?: string;
17+content?: string;
18+};
19+};
20+21+async function readJsonlRecords(filePath: string): Promise<ReplayRecord[]> {
22+const records: ReplayRecord[] = [];
23+const raw = await fs.readFile(filePath, "utf8");
24+for (const line of raw.split(/\r?\n/)) {
25+if (line.trim().length === 0) {
26+continue;
27+}
28+records.push(JSON.parse(line) as ReplayRecord);
29+}
30+return records;
31+}
32+1233describe("replayRecentUserAssistantMessages", () => {
1334let root = "";
1435beforeEach(async () => {
@@ -37,14 +58,11 @@ describe("replayRecentUserAssistantMessages", () => {
3758await fs.writeFile(source, lines.join(""), "utf8");
38593960expect(await call(source, target)).toBe(DEFAULT_REPLAY_MAX_MESSAGES);
40-const records = (await fs.readFile(target, "utf8"))
41-.split(/\r?\n/)
42-.filter((line) => line.trim().length > 0)
43-.map((line) => JSON.parse(line));
61+const records = await readJsonlRecords(target);
4462expect(records[0]).toMatchObject({ type: "session", id: "new-session" });
4563expect(records).toHaveLength(1 + DEFAULT_REPLAY_MAX_MESSAGES);
4664for (const r of records.slice(1)) {
47-expect(["user", "assistant"]).toContain(r.message.role);
65+expect(["user", "assistant"]).toContain(r.message?.role);
4866}
4967expect(await call(path.join(root, "missing.jsonl"), path.join(root, "out.jsonl"))).toBe(0);
5068@@ -69,13 +87,10 @@ describe("replayRecentUserAssistantMessages", () => {
6987await fs.writeFile(source, lines.join(""), "utf8");
70887189expect(await call(source, target)).toBe(DEFAULT_REPLAY_MAX_MESSAGES - 1);
72-const records = (await fs.readFile(target, "utf8"))
73-.split(/\r?\n/)
74-.filter((line) => line.trim().length > 0)
75-.map((line) => JSON.parse(line));
90+const records = await readJsonlRecords(target);
7691expect(records.reduce((count, r) => count + (r.type === "session" ? 1 : 0), 0)).toBe(1);
7792expect(records[0]).toMatchObject({ id: "existing" });
78-expect(records[1].message.role).toBe("user");
93+expect(records[1].message?.role).toBe("user");
7994});
80958196it("coalesces same-role runs so replayed records strictly alternate", async () => {
@@ -95,17 +110,14 @@ describe("replayRecentUserAssistantMessages", () => {
95110);
9611197112expect(await call(source, target)).toBe(4);
98-const records = (await fs.readFile(target, "utf8"))
99-.split(/\r?\n/)
100-.filter((line) => line.trim().length > 0)
101-.map((line) => JSON.parse(line));
102-expect(records.slice(1).map((r) => r.message.role)).toEqual([
113+const records = await readJsonlRecords(target);
114+expect(records.slice(1).map((r) => r.message?.role)).toEqual([
103115"user",
104116"assistant",
105117"user",
106118"assistant",
107119]);
108-expect(records.slice(1).map((r) => r.message.content)).toEqual([
120+expect(records.slice(1).map((r) => r.message?.content)).toEqual([
109121"latest user",
110122"latest assistant",
111123"follow-up",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。