import crypto from "node:crypto"; import type { StreamFn } from "@mariozechner/pi-agent-core"; import { describe, expect, it } from "vitest"; import { createAnthropicPayloadLogger } from "./anthropic-payload-log.js"; describe("createAnthropicPayloadLogger", () => { it("redacts image base64 payload data before writing logs", async () => { const lines: string[] = []; const logger = createAnthropicPayloadLogger({ env: { OPENCLAW_ANTHROPIC_PAYLOAD_LOG: "1" }, writer: { filePath: "memory", write: (line) => lines.push(line), }, }); expect(logger).not.toBeNull(); const payload = { messages: [ { role: "user", content: [ { type: "image", source: { type: "base64", media_type: "image/png", data: "QUJDRA==" }, }, ], }, ], }; const streamFn: StreamFn = ((model, __, options) => { options?.onPayload?.(payload, model); return {} as never; }) as StreamFn; const wrapped = logger?.wrapStreamFn(streamFn); await wrapped?.({ api: "anthropic-messages" } as never, { messages: [] } as never, {}); const event = JSON.parse(lines[0]?.trim() ?? "{}") as Record; const message = ((event.payload as { messages?: unknown[] } | undefined)?.messages ?? []) as Array>; const source = (((message[0]?.content as Array> | undefined) ?? [])[0] ?.source ?? {}) as Record; expect(source.data).toBe(""); expect(source.bytes).toBe(4); expect(source.sha256).toBe(crypto.createHash("sha256").update("QUJDRA==").digest("hex")); expect(event.payloadDigest).toBeDefined(); }); });