mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-06 23:44:36 +00:00
Replayed thinking is often not part of the live context (for example, radius drops it, and Anthropic drops blocks that do not match their request), but serializeConversation included all of it. A Pi Mobile session at ~996K of 1M context tokens produced 1.38M-token summarization requests that failed on every attempt. Providers only return summaries of the reasoning anyway; visible text, tool calls, and tool results record what happened.
109 lines
2.8 KiB
TypeScript
109 lines
2.8 KiB
TypeScript
import type { Message } from "@earendil-works/pi-ai";
|
|
import { describe, expect, it } from "vitest";
|
|
import { serializeConversation } from "../src/core/compaction/utils.ts";
|
|
|
|
describe("serializeConversation", () => {
|
|
it("should truncate long tool results", () => {
|
|
const longContent = "x".repeat(5000);
|
|
const messages: Message[] = [
|
|
{
|
|
role: "toolResult",
|
|
toolCallId: "tc1",
|
|
toolName: "read",
|
|
content: [{ type: "text", text: longContent }],
|
|
isError: false,
|
|
timestamp: Date.now(),
|
|
},
|
|
];
|
|
|
|
const result = serializeConversation(messages);
|
|
|
|
expect(result).toContain("[Tool result]:");
|
|
expect(result).toContain("[... 3000 more characters truncated]");
|
|
expect(result).not.toContain("x".repeat(3000));
|
|
// First 2000 chars should be present
|
|
expect(result).toContain("x".repeat(2000));
|
|
});
|
|
|
|
it("should not truncate short tool results", () => {
|
|
const shortContent = "x".repeat(1500);
|
|
const messages: Message[] = [
|
|
{
|
|
role: "toolResult",
|
|
toolCallId: "tc1",
|
|
toolName: "read",
|
|
content: [{ type: "text", text: shortContent }],
|
|
isError: false,
|
|
timestamp: Date.now(),
|
|
},
|
|
];
|
|
|
|
const result = serializeConversation(messages);
|
|
|
|
expect(result).toBe(`[Tool result]: ${shortContent}`);
|
|
expect(result).not.toContain("truncated");
|
|
});
|
|
|
|
it("should not truncate assistant or user messages", () => {
|
|
const longText = "y".repeat(5000);
|
|
const messages: Message[] = [
|
|
{
|
|
role: "user",
|
|
content: [{ type: "text", text: longText }],
|
|
timestamp: Date.now(),
|
|
},
|
|
{
|
|
role: "assistant",
|
|
content: [{ type: "text", text: longText }],
|
|
api: "anthropic",
|
|
provider: "anthropic",
|
|
model: "test",
|
|
usage: {
|
|
input: 0,
|
|
output: 0,
|
|
cacheRead: 0,
|
|
cacheWrite: 0,
|
|
totalTokens: 0,
|
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
},
|
|
stopReason: "stop",
|
|
timestamp: Date.now(),
|
|
},
|
|
];
|
|
|
|
const result = serializeConversation(messages);
|
|
|
|
expect(result).not.toContain("truncated");
|
|
expect(result).toContain(longText);
|
|
});
|
|
|
|
it("should omit thinking", () => {
|
|
const messages: Message[] = [
|
|
{
|
|
role: "assistant",
|
|
content: [
|
|
{ type: "thinking", thinking: "private reasoning", thinkingSignature: "sig" },
|
|
{ type: "text", text: "visible reply" },
|
|
{ type: "toolCall", id: "tc1", name: "read", arguments: { path: "a.ts" } },
|
|
],
|
|
api: "anthropic",
|
|
provider: "anthropic",
|
|
model: "test",
|
|
usage: {
|
|
input: 0,
|
|
output: 0,
|
|
cacheRead: 0,
|
|
cacheWrite: 0,
|
|
totalTokens: 0,
|
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
},
|
|
stopReason: "toolUse",
|
|
timestamp: Date.now(),
|
|
},
|
|
];
|
|
|
|
const result = serializeConversation(messages);
|
|
|
|
expect(result).toBe('[Assistant]: visible reply\n\n[Assistant tool calls]: read(path="a.ts")');
|
|
});
|
|
});
|