Files
clawdbot/src/agents/pi-embedded-helpers.sanitize-session-messages-images.keeps-tool-call-tool-result-ids-unchanged.test.ts
2026-01-16 02:16:17 +00:00

147 lines
4.9 KiB
TypeScript

import type { AgentMessage } from "@mariozechner/pi-agent-core";
import { describe, expect, it } from "vitest";
import { sanitizeSessionMessagesImages } from "./pi-embedded-helpers.js";
import { DEFAULT_AGENTS_FILENAME } from "./workspace.js";
const _makeFile = (overrides: Partial<WorkspaceBootstrapFile>): WorkspaceBootstrapFile => ({
name: DEFAULT_AGENTS_FILENAME,
path: "/tmp/AGENTS.md",
content: "",
missing: false,
...overrides,
});
describe("sanitizeSessionMessagesImages", () => {
it("keeps tool call + tool result IDs unchanged by default", async () => {
const input = [
{
role: "assistant",
content: [
{
type: "toolCall",
id: "call_123|fc_456",
name: "read",
arguments: { path: "package.json" },
},
],
},
{
role: "toolResult",
toolCallId: "call_123|fc_456",
toolName: "read",
content: [{ type: "text", text: "ok" }],
isError: false,
},
] satisfies AgentMessage[];
const out = await sanitizeSessionMessagesImages(input, "test");
const assistant = out[0] as unknown as { role?: string; content?: unknown };
expect(assistant.role).toBe("assistant");
expect(Array.isArray(assistant.content)).toBe(true);
const toolCall = (assistant.content as Array<{ type?: string; id?: string }>).find(
(b) => b.type === "toolCall",
);
expect(toolCall?.id).toBe("call_123|fc_456");
const toolResult = out[1] as unknown as {
role?: string;
toolCallId?: string;
};
expect(toolResult.role).toBe("toolResult");
expect(toolResult.toolCallId).toBe("call_123|fc_456");
});
it("sanitizes tool call + tool result IDs when enabled", async () => {
const input = [
{
role: "assistant",
content: [
{
type: "toolCall",
id: "call_123|fc_456",
name: "read",
arguments: { path: "package.json" },
},
],
},
{
role: "toolResult",
toolCallId: "call_123|fc_456",
toolName: "read",
content: [{ type: "text", text: "ok" }],
isError: false,
},
] satisfies AgentMessage[];
const out = await sanitizeSessionMessagesImages(input, "test", {
sanitizeToolCallIds: true,
});
const assistant = out[0] as unknown as { role?: string; content?: unknown };
expect(assistant.role).toBe("assistant");
expect(Array.isArray(assistant.content)).toBe(true);
const toolCall = (assistant.content as Array<{ type?: string; id?: string }>).find(
(b) => b.type === "toolCall",
);
expect(toolCall?.id).toBe("call_123_fc_456");
const toolResult = out[1] as unknown as {
role?: string;
toolCallId?: string;
};
expect(toolResult.role).toBe("toolResult");
expect(toolResult.toolCallId).toBe("call_123_fc_456");
});
it("drops assistant blocks after a tool call when enforceToolCallLast is enabled", async () => {
const input = [
{
role: "assistant",
content: [
{ type: "text", text: "before" },
{ type: "toolCall", id: "call_1", name: "read", arguments: {} },
{ type: "thinking", thinking: "after", thinkingSignature: "sig" },
{ type: "text", text: "after text" },
],
},
] satisfies AgentMessage[];
const out = await sanitizeSessionMessagesImages(input, "test", {
enforceToolCallLast: true,
});
const assistant = out[0] as { content?: Array<{ type?: string }> };
expect(assistant.content?.map((b) => b.type)).toEqual(["text", "toolCall"]);
});
it("keeps assistant blocks after a tool call when enforceToolCallLast is disabled", async () => {
const input = [
{
role: "assistant",
content: [
{ type: "text", text: "before" },
{ type: "toolCall", id: "call_1", name: "read", arguments: {} },
{ type: "thinking", thinking: "after", thinkingSignature: "sig" },
{ type: "text", text: "after text" },
],
},
] satisfies AgentMessage[];
const out = await sanitizeSessionMessagesImages(input, "test");
const assistant = out[0] as { content?: Array<{ type?: string }> };
expect(assistant.content?.map((b) => b.type)).toEqual(["text", "toolCall", "thinking", "text"]);
});
it("does not synthesize tool call input when missing", async () => {
const input = [
{
role: "assistant",
content: [{ type: "toolCall", id: "call_1", name: "read" }],
},
] satisfies AgentMessage[];
const out = await sanitizeSessionMessagesImages(input, "test");
const assistant = out[0] as { content?: Array<Record<string, unknown>> };
const toolCall = assistant.content?.find((b) => b.type === "toolCall");
expect(toolCall).toBeTruthy();
expect("input" in (toolCall ?? {})).toBe(false);
expect("arguments" in (toolCall ?? {})).toBe(false);
});
});