🤖 fix: preserve openai reasoning replay ids (#17792)

What:
- disable tool-call id sanitization for OpenAI/OpenAI Codex transcript policy
- gate id sanitization in image sanitizer to full mode only
- keep orphan reasoning downgrade scoped to OpenAI model-switch replay path
- update transcript policy, session-history, sanitizer, and reasoning replay tests
- document OpenAI model-switch orphan-reasoning cleanup behavior in transcript hygiene reference

Why:
- OpenAI Responses replay depends on canonical call_id|fc_id pairings for reasoning followers
- strict id rewriting in OpenAI path breaks follower matching and triggers rs_* orphan 400s
- limiting scope avoids behavior expansion while fixing the identified regression

Tests:
- pnpm vitest run src/agents/transcript-policy.test.ts src/agents/pi-embedded-runner.sanitize-session-history.test.ts src/agents/openai-responses.reasoning-replay.test.ts
- pnpm vitest run --config vitest.e2e.config.ts src/agents/transcript-policy.e2e.test.ts src/agents/pi-embedded-runner.sanitize-session-history.e2e.test.ts src/agents/pi-embedded-helpers.sanitize-session-messages-images.removes-empty-assistant-text-blocks-but-preserves.e2e.test.ts src/agents/pi-embedded-helpers.sanitizeuserfacingtext.e2e.test.ts
- pnpm lint
- pnpm format:check
- pnpm check:docs
- pnpm test (fails in current macOS bash 3.2 env at test/git-hooks-pre-commit.integration.test.ts: mapfile not found)
This commit is contained in:
the sun gif man
2026-02-15 22:45:01 -08:00
committed by GitHub
parent eefda1314f
commit 68ea063958
10 changed files with 126 additions and 21 deletions

View File

@@ -98,7 +98,7 @@ describe("sanitizeSessionHistory", () => {
);
});
it("sanitizes tool call ids for openai-responses while keeping images-only mode", async () => {
it("does not sanitize tool call ids for openai-responses", async () => {
vi.mocked(helpers.isGoogleModelApi).mockReturnValue(false);
await sanitizeSessionHistory({
@@ -112,11 +112,7 @@ describe("sanitizeSessionHistory", () => {
expect(helpers.sanitizeSessionMessagesImages).toHaveBeenCalledWith(
mockMessages,
"session:history",
expect.objectContaining({
sanitizeMode: "images-only",
sanitizeToolCallIds: true,
toolCallIdMode: "strict",
}),
expect.objectContaining({ sanitizeMode: "images-only", sanitizeToolCallIds: false }),
);
});
@@ -243,7 +239,7 @@ describe("sanitizeSessionHistory", () => {
expect(result).toEqual(messages);
});
it("downgrades openai reasoning only when the model changes", async () => {
it("downgrades openai reasoning when the model changes", async () => {
const sessionEntries = [
makeModelSnapshotEntry({
provider: "anthropic",