mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-31 03:41:51 +00:00
* Gateway: preserve Pi transcript parentId for injected messages Thread: unknown When: 2026-02-08 20:08 CST Repo: https://github.com/openclaw/openclaw.git Branch: codex/wip/2026-02-09/compact-post-compaction-parentid-fix Problem - Post-compaction turns sometimes lost the compaction summary + kept suffix in the *next* provider request. - Root cause was session graph corruption: gateway appended "stopReason: injected" transcript lines via raw JSONL writes without `parentId`. - Pi's `SessionManager.buildSessionContext()` walks the `parentId` chain from the current leaf; missing `parentId` can sever the active branch and hide the compaction entry. Fix - Use `SessionManager.appendMessage(...)` for injected assistant transcript writes so `parentId` is set to the current leaf. - Route `chat.inject` through the same helper to avoid duplicating the broken raw JSONL append logic. Why This Matters - The compaction algorithm may be correct, but if the leaf chain is broken right after compaction, the provider payload cannot include the summary/suffix "shape" Pi expects. Testing - pnpm test src/agents/pi-embedded-helpers.post-compaction-shape.test.ts src/agents/pi-embedded-runner/run.overflow-compaction.post-context.test.ts - pnpm build Notes - This is provider-shape agnostic: it fixes transcript structure so Anthropic/Gemini/etc all see the same post-compaction context. Resume - If post-compaction looks wrong again, inspect the session transcript for entries missing `parentId` immediately after `type: compaction`. * Gateway: guardrail test for transcript parentId (chat.inject) * Gateway: guardrail against raw transcript appends (chat.ts) * Gateway: add local AGENTS.md note to preserve Pi transcript parentId chain * Changelog: note gateway post-compaction amnesia fix * Gateway: store injected transcript messages with valid stopReason * Gateway: use valid stopReason in injected fallback
24 lines
1.2 KiB
TypeScript
24 lines
1.2 KiB
TypeScript
import fs from "node:fs";
|
|
import { fileURLToPath } from "node:url";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
// Guardrail: the "empty post-compaction context" regression came from gateway code appending
|
|
// Pi transcript message entries as raw JSONL without `parentId`.
|
|
//
|
|
// This test is intentionally simple and file-local: if someone reintroduces direct JSONL appends
|
|
// against `transcriptPath`, Pi's SessionManager parent chain can break again.
|
|
describe("gateway chat transcript writes (guardrail)", () => {
|
|
it("does not append transcript messages via raw fs.appendFileSync(transcriptPath, ...)", () => {
|
|
const chatTs = fileURLToPath(new URL("./chat.ts", import.meta.url));
|
|
const src = fs.readFileSync(chatTs, "utf-8");
|
|
|
|
// Disallow raw appends against the resolved transcript path variable.
|
|
// (The transcript header creation via writeFileSync is OK; the bug class is raw message appends.)
|
|
expect(src.includes("fs.appendFileSync(transcriptPath")).toBe(false);
|
|
|
|
// Ensure we keep using SessionManager for transcript message appends.
|
|
expect(src).toContain("SessionManager.open(transcriptPath)");
|
|
expect(src).toContain("appendMessage(");
|
|
});
|
|
});
|