From 8764ed25c1da6c4f45bdbacf5c4089fee41f7699 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Mon, 2 Nov 2026 05:26:03 +0100 Subject: [PATCH] fix(pi): accept native system messages with text blocks --- .../agent/providers/pi/history-mapper.test.ts | 30 +++++++++++++++++++ .../server/agent/providers/pi/transcript.ts | 4 ++- .../daemon-e2e/pi-rewind.real.e2e.test.ts | 6 +++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/server/src/server/agent/providers/pi/history-mapper.test.ts b/packages/server/src/server/agent/providers/pi/history-mapper.test.ts index 1606e1b2f6..b6f4349f47 100644 --- a/packages/server/src/server/agent/providers/pi/history-mapper.test.ts +++ b/packages/server/src/server/agent/providers/pi/history-mapper.test.ts @@ -497,3 +497,33 @@ test("traverses native system and summary messages without displaying private co userEntries: [{ id: "1", text: "question" }], }); }); + +test("restores surrounding chat when native system content uses text blocks", async () => { + const records = [ + { type: "session", version: 3 }, + { type: "message", id: "u", parentId: null, message: { role: "user", content: "question" } }, + { + type: "message", + id: "s", + parentId: "u", + message: { role: "system", content: [{ type: "text", text: "private instructions" }] }, + }, + { + type: "message", + id: "a", + parentId: "s", + message: { role: "assistant", content: [{ type: "text", text: "answer" }] }, + }, + ]; + const history = readPiTranscript(records.map((record) => JSON.stringify(record)).join("\n")); + expect(history.messages).toEqual([ + { role: "user", content: "question" }, + { role: "assistant", content: [{ type: "text", text: "answer" }] }, + ]); + expect(history.userEntries).toEqual([{ id: "u", text: "question" }]); + const events = await collectHistory(history.messages, history.userEntries); + expect(events.map((event) => event.item)).toEqual([ + { type: "user_message", text: "question", messageId: "u" }, + { type: "assistant_message", text: "answer", messageId: "pi-history-assistant-1" }, + ]); +}); diff --git a/packages/server/src/server/agent/providers/pi/transcript.ts b/packages/server/src/server/agent/providers/pi/transcript.ts index 42856a69b5..b4ead7bc5c 100644 --- a/packages/server/src/server/agent/providers/pi/transcript.ts +++ b/packages/server/src/server/agent/providers/pi/transcript.ts @@ -13,7 +13,9 @@ const image = z .passthrough(); const content = z.union([z.string(), z.array(z.union([text, image]))]); const message = z.discriminatedUnion("role", [ - z.object({ role: z.literal("system"), content: z.string().nullish() }).passthrough(), + z + .object({ role: z.literal("system"), content: z.union([z.string(), z.array(text)]).nullish() }) + .passthrough(), z.object({ role: z.literal("branchSummary"), summary: z.string() }).passthrough(), z.object({ role: z.literal("compactionSummary"), summary: z.string() }).passthrough(), z.object({ role: z.literal("user"), content }).passthrough(), diff --git a/packages/server/src/server/daemon-e2e/pi-rewind.real.e2e.test.ts b/packages/server/src/server/daemon-e2e/pi-rewind.real.e2e.test.ts index 06eab7dd4a..704243d503 100644 --- a/packages/server/src/server/daemon-e2e/pi-rewind.real.e2e.test.ts +++ b/packages/server/src/server/daemon-e2e/pi-rewind.real.e2e.test.ts @@ -406,7 +406,11 @@ test("seeded compacted Pi history survives daemon reload, native rewind and Fork id: "system", parentId: null, timestamp, - message: { role: "system", content: "private system context", timestamp: Date.now() }, + message: { + role: "system", + content: [{ type: "text", text: "private system context" }], + timestamp: Date.now(), + }, }, { type: "message",