mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-12 01:31:08 +00:00
99 lines
3.2 KiB
TypeScript
99 lines
3.2 KiB
TypeScript
import fs from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
import { mirrorCodexAppServerTranscript } from "./transcript-mirror.js";
|
|
|
|
let tempDir: string;
|
|
|
|
describe("mirrorCodexAppServerTranscript", () => {
|
|
beforeEach(async () => {
|
|
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-codex-transcript-"));
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await fs.rm(tempDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it("mirrors user and assistant messages into the PI transcript", async () => {
|
|
const sessionFile = path.join(tempDir, "session.jsonl");
|
|
|
|
await mirrorCodexAppServerTranscript({
|
|
sessionFile,
|
|
sessionKey: "agent:main:session-1",
|
|
messages: [
|
|
{ role: "user", content: "hello", timestamp: 1 },
|
|
{
|
|
role: "assistant",
|
|
content: [{ type: "text", text: "hi" }],
|
|
api: "openai-codex-responses",
|
|
provider: "openai-codex",
|
|
model: "gpt-5.4-codex",
|
|
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: 2,
|
|
},
|
|
],
|
|
});
|
|
|
|
const records = (await fs.readFile(sessionFile, "utf8"))
|
|
.trim()
|
|
.split("\n")
|
|
.map((line) => JSON.parse(line) as { type?: string; message?: { role?: string } });
|
|
expect(records[0]?.type).toBe("session");
|
|
expect(records.slice(1).map((record) => record.message?.role)).toEqual(["user", "assistant"]);
|
|
});
|
|
|
|
it("deduplicates app-server turn mirrors by idempotency scope", async () => {
|
|
const sessionFile = path.join(tempDir, "session.jsonl");
|
|
const messages = [
|
|
{ role: "user" as const, content: "hello", timestamp: 1 },
|
|
{
|
|
role: "assistant" as const,
|
|
content: [{ type: "text" as const, text: "hi" }],
|
|
api: "openai-codex-responses",
|
|
provider: "openai-codex",
|
|
model: "gpt-5.4-codex",
|
|
usage: {
|
|
input: 0,
|
|
output: 0,
|
|
cacheRead: 0,
|
|
cacheWrite: 0,
|
|
totalTokens: 0,
|
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
},
|
|
stopReason: "stop" as const,
|
|
timestamp: 2,
|
|
},
|
|
];
|
|
|
|
await mirrorCodexAppServerTranscript({
|
|
sessionFile,
|
|
messages,
|
|
idempotencyScope: "codex-app-server:thread-1:turn-1",
|
|
});
|
|
await mirrorCodexAppServerTranscript({
|
|
sessionFile,
|
|
messages,
|
|
idempotencyScope: "codex-app-server:thread-1:turn-1",
|
|
});
|
|
|
|
const records = (await fs.readFile(sessionFile, "utf8"))
|
|
.trim()
|
|
.split("\n")
|
|
.map((line) => JSON.parse(line) as { message?: { role?: string; idempotencyKey?: string } });
|
|
expect(records.slice(1).map((record) => record.message?.role)).toEqual(["user", "assistant"]);
|
|
expect(records.slice(1).map((record) => record.message?.idempotencyKey)).toEqual([
|
|
"codex-app-server:thread-1:turn-1:user:0",
|
|
"codex-app-server:thread-1:turn-1:assistant:1",
|
|
]);
|
|
});
|
|
});
|