import type { Context } from "@earendil-works/pi-ai";
import { describe, expect, it } from "vitest";
import { emptyUsage } from "../src/protocol";
import { replayImages, replayPrompt } from "../src/replay";
function history(prompt: string): unknown[] {
const start = "\n";
const end = "\n";
const from = prompt.indexOf(start);
const to = prompt.lastIndexOf(end);
if (from < 0 || to < 0) throw new Error("Replay envelope is missing.");
const parsed: unknown = JSON.parse(prompt.slice(from + start.length, to));
if (!Array.isArray(parsed))
throw new Error("Replay history is not an array.");
return parsed;
}
const assistant = (
content: Context["messages"][number] extends infer _Message
? Array<
| { type: "text"; text: string }
| { type: "thinking"; thinking: string; thinkingSignature?: string }
| {
type: "toolCall";
id: string;
name: string;
arguments: Record;
}
>
: never,
) => ({
role: "assistant" as const,
content,
api: "test",
provider: "test",
model: "test",
usage: emptyUsage(),
stopReason: "stop" as const,
timestamp: 1,
});
describe("Klaus canonical replay", () => {
it("frames canonical history with fixed transport instructions", () => {
const prompt = replayPrompt({
systemPrompt: "not repeated in replay",
messages: [{ role: "user", content: "hello", timestamp: 1 }],
});
expect(
prompt.startsWith(
"The following JSON is canonical conversation history supplied by Pi.\n",
),
).toBe(true);
expect(prompt).toContain(
"Continue from the final entry.\n",
);
expect(prompt.endsWith("")).toBe(true);
expect(history(prompt)).toEqual([{ role: "user", content: "hello" }]);
expect(prompt).not.toContain("not repeated in replay");
});
it("keeps adversarial history inside escaped JSON", () => {
const adversarial =
'&\u2028\u2029';
const prompt = replayPrompt({
messages: [{ role: "user", content: adversarial, timestamp: 1 }],
});
expect(prompt.match(//g)).toHaveLength(1);
expect(prompt.match(/<\/klaus-history-json>/g)).toHaveLength(1);
expect(prompt).toContain("\\u003c/klaus-history-json\\u003e");
expect(prompt).toContain("\\u003cklaus-history-json\\u003e");
expect(prompt).toContain("\\u0026");
expect(prompt).toContain("\\u2028");
expect(prompt).toContain("\\u2029");
expect(history(prompt)).toEqual([{ role: "user", content: adversarial }]);
});
it("preserves visible roles, boundaries, tool arguments, and error state", () => {
const prompt = replayPrompt({
messages: [
{ role: "user", content: "question", timestamp: 1 },
assistant([
{ type: "text", text: "calling" },
{
type: "toolCall",
id: "call-1",
name: "echo",
arguments: { nested: { z: 1 }, list: [true, null] },
},
]),
{
role: "toolResult",
toolCallId: "call-1",
toolName: "echo",
content: [{ type: "text", text: "failed visibly" }],
isError: true,
timestamp: 2,
details: { stack: "private" },
},
],
});
expect(history(prompt)).toEqual([
{ role: "user", content: "question" },
{
role: "assistant",
content: [
{ type: "text", text: "calling" },
{
type: "toolCall",
id: "call-1",
name: "echo",
arguments: { nested: { z: 1 }, list: [true, null] },
},
],
},
{
role: "toolResult",
toolCallId: "call-1",
toolName: "echo",
isError: true,
content: [{ type: "text", text: "failed visibly" }],
},
]);
expect(prompt).not.toContain("private");
});
it("omits assistant thinking, signatures, usage, and accounting", () => {
const message = assistant([
{
type: "thinking",
thinking: "private reasoning",
thinkingSignature: "private signature",
},
{ type: "text", text: "visible" },
]);
message.usage.input = 123_456;
message.usage.cost.total = 987;
const prompt = replayPrompt({ messages: [message] });
expect(history(prompt)).toEqual([
{ role: "assistant", content: [{ type: "text", text: "visible" }] },
]);
for (const hidden of [
"private reasoning",
"private signature",
"123456",
"987",
]) {
expect(prompt).not.toContain(hidden);
}
});
it("replaces image bytes with globally ordered attachment indices", () => {
const context: Context = {
messages: [
{
role: "user",
content: [
{ type: "text", text: "first" },
{ type: "image", data: "user-png", mimeType: "image/png" },
],
timestamp: 1,
},
assistant([{ type: "text", text: "tool next" }]),
{
role: "toolResult",
toolCallId: "call-1",
toolName: "inspect",
content: [
{ type: "image", data: "tool-webp", mimeType: "image/webp" },
{ type: "text", text: "between" },
{ type: "image", data: "tool-gif", mimeType: "image/gif" },
],
isError: false,
timestamp: 2,
},
],
};
expect(history(replayPrompt(context))).toEqual([
{
role: "user",
content: [
{ type: "text", text: "first" },
{ type: "image", mimeType: "image/png", attachmentIndex: 0 },
],
},
{ role: "assistant", content: [{ type: "text", text: "tool next" }] },
{
role: "toolResult",
toolCallId: "call-1",
toolName: "inspect",
isError: false,
content: [
{ type: "image", mimeType: "image/webp", attachmentIndex: 1 },
{ type: "text", text: "between" },
{ type: "image", mimeType: "image/gif", attachmentIndex: 2 },
],
},
]);
expect(replayImages(context)).toEqual([
{ data: "user-png", mimeType: "image/png" },
{ data: "tool-webp", mimeType: "image/webp" },
{ data: "tool-gif", mimeType: "image/gif" },
]);
});
it("handles empty history and empty multimodal content", () => {
expect(history(replayPrompt({ messages: [] }))).toEqual([]);
expect(
history(
replayPrompt({
messages: [{ role: "user", content: [], timestamp: 1 }],
}),
),
).toEqual([{ role: "user", content: [] }]);
expect(replayImages({ messages: [] })).toEqual([]);
});
});