From 487951f813a8dec95c3e96a4ba8f702dbc07b3f0 Mon Sep 17 00:00:00 2001 From: Sally O'Malley Date: Wed, 24 Jun 2026 00:16:01 -0400 Subject: [PATCH] fix(compaction): route codex oauth compaction natively (#95831) Signed-off-by: sallyom --- .../compact.hooks.test.ts | 62 ++++++++++++++++--- .../embedded-agent-runner/compact.queued.ts | 6 +- .../compaction-runtime-context.test.ts | 8 ++- .../compaction-runtime-context.ts | 2 + 4 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/agents/embedded-agent-runner/compact.hooks.test.ts b/src/agents/embedded-agent-runner/compact.hooks.test.ts index bcd6ee5c1b1e..27558714e70a 100644 --- a/src/agents/embedded-agent-runner/compact.hooks.test.ts +++ b/src/agents/embedded-agent-runner/compact.hooks.test.ts @@ -1846,7 +1846,7 @@ describe("compactEmbeddedAgentSession hooks (ownsCompaction engine)", () => { }); }); - it("keeps selected Codex harness queued compaction on canonical OpenAI context", async () => { + it("runs selected Codex harness queued compaction on canonical OpenAI context", async () => { resolveAgentHarnessPolicyMock.mockReturnValue({ runtime: "codex" }); maybeCompactAgentHarnessSessionMock.mockResolvedValueOnce({ ok: true, @@ -1874,7 +1874,16 @@ describe("compactEmbeddedAgentSession hooks (ownsCompaction engine)", () => { ); expect(result.ok).toBe(true); - expect(maybeCompactAgentHarnessSessionMock).not.toHaveBeenCalled(); + expect(contextEngineCompactMock).toHaveBeenCalledTimes(1); + expect(maybeCompactAgentHarnessSessionMock).toHaveBeenCalledTimes(1); + expect(maybeCompactAgentHarnessSessionMock).toHaveBeenCalledWith( + expect.objectContaining({ + provider: "openai", + model: "gpt-5.5", + agentHarnessId: "codex", + }), + { nativeCompactionRequest: "after_context_engine" }, + ); const compactArg = mockCallArg(contextEngineCompactMock) as { runtimeContext?: Record; }; @@ -1915,7 +1924,15 @@ describe("compactEmbeddedAgentSession hooks (ownsCompaction engine)", () => { ); expect(result.ok).toBe(true); - expect(maybeCompactAgentHarnessSessionMock).not.toHaveBeenCalled(); + expect(contextEngineCompactMock).toHaveBeenCalledTimes(1); + expect(maybeCompactAgentHarnessSessionMock).toHaveBeenCalledTimes(1); + expect(maybeCompactAgentHarnessSessionMock).toHaveBeenCalledWith( + expect.objectContaining({ + provider: "openai", + model: "gpt-5.5", + }), + { nativeCompactionRequest: "after_context_engine" }, + ); const compactArg = mockCallArg(contextEngineCompactMock) as { runtimeContext?: Record; }; @@ -1968,7 +1985,7 @@ describe("compactEmbeddedAgentSession hooks (ownsCompaction engine)", () => { }); }); - it("keeps concrete Codex pins on canonical OpenAI for queued compaction", async () => { + it("uses concrete Codex pins on canonical OpenAI for queued compaction", async () => { resolveAgentHarnessPolicyMock.mockReturnValue({ runtime: "auto", runtimeSource: "model", @@ -1999,7 +2016,16 @@ describe("compactEmbeddedAgentSession hooks (ownsCompaction engine)", () => { ); expect(result.ok).toBe(true); - expect(maybeCompactAgentHarnessSessionMock).not.toHaveBeenCalled(); + expect(contextEngineCompactMock).toHaveBeenCalledTimes(1); + expect(maybeCompactAgentHarnessSessionMock).toHaveBeenCalledTimes(1); + expect(maybeCompactAgentHarnessSessionMock).toHaveBeenCalledWith( + expect.objectContaining({ + provider: "openai", + model: "gpt-5.5", + agentHarnessId: "codex", + }), + { nativeCompactionRequest: "after_context_engine" }, + ); const compactArg = mockCallArg(contextEngineCompactMock) as { runtimeContext?: Record; }; @@ -2068,7 +2094,10 @@ describe("compactEmbeddedAgentSession hooks (ownsCompaction engine)", () => { config: { models: { providers: { - openai: { models: [{ id: "gpt-5.5", contextWindow: 350_000 }] }, + openai: { + baseUrl: "https://example.test/v1", + models: [{ id: "gpt-5.5", contextWindow: 350_000 }], + }, }, }, }, @@ -2125,7 +2154,7 @@ describe("compactEmbeddedAgentSession hooks (ownsCompaction engine)", () => { expect(contextEngineCompactMock).not.toHaveBeenCalled(); }); - it("uses context-engine compaction when no Codex native binding is selected", async () => { + it("keeps context-engine compaction successful when Codex native binding is missing", async () => { resolveAgentHarnessPolicyMock.mockReturnValue({ runtime: "codex" }); maybeCompactAgentHarnessSessionMock.mockResolvedValueOnce({ ok: false, @@ -2146,8 +2175,25 @@ describe("compactEmbeddedAgentSession hooks (ownsCompaction engine)", () => { expect(result.ok).toBe(true); expect(result.compacted).toBe(true); expect(result.result?.summary).toBe("engine-summary"); - expect(maybeCompactAgentHarnessSessionMock).not.toHaveBeenCalled(); expect(contextEngineCompactMock).toHaveBeenCalledTimes(1); + expect(maybeCompactAgentHarnessSessionMock).toHaveBeenCalledTimes(1); + expect(maybeCompactAgentHarnessSessionMock).toHaveBeenCalledWith( + expect.objectContaining({ + provider: "openai", + model: "gpt-5.4", + agentHarnessId: "codex", + }), + { nativeCompactionRequest: "after_context_engine" }, + ); + const details = result.result?.details as + | { codexNativeCompaction?: Record } + | undefined; + expect(details?.codexNativeCompaction).toMatchObject({ + ok: false, + compacted: false, + reason: "no codex app-server thread binding", + failure: { reason: "missing_thread_binding" }, + }); }); it("keeps owning context-engine compaction primary for legacy Codex native sessions", async () => { diff --git a/src/agents/embedded-agent-runner/compact.queued.ts b/src/agents/embedded-agent-runner/compact.queued.ts index 3393fb8228e0..411bdaae2a60 100644 --- a/src/agents/embedded-agent-runner/compact.queued.ts +++ b/src/agents/embedded-agent-runner/compact.queued.ts @@ -252,7 +252,7 @@ export async function compactEmbeddedAgentSession( const ceModelId = resolvedCompactionTarget.model ?? DEFAULT_MODEL; const attemptNativeHarnessCompaction = shouldAttemptNativeHarnessCompaction({ provider: ceProvider, - contextProvider: resolvedCompactionTarget.contextProvider, + nativeHarnessCompaction: resolvedCompactionTarget.nativeHarnessCompaction, selectedHarnessRuntime, }); if (attemptNativeHarnessCompaction) { @@ -630,14 +630,14 @@ export async function compactEmbeddedAgentSession( function shouldAttemptNativeHarnessCompaction(params: { provider: string; - contextProvider?: string; + nativeHarnessCompaction?: boolean; selectedHarnessRuntime?: string | null; }): boolean { const selectedRuntime = normalizeOptionalAgentRuntimeId(params.selectedHarnessRuntime); if (!selectedRuntime || selectedRuntime === "auto" || selectedRuntime === "openclaw") { return false; } - return isOpenAIProvider(params.provider) ? params.contextProvider !== undefined : true; + return isOpenAIProvider(params.provider) ? params.nativeHarnessCompaction === true : true; } function buildCompactionContextEngineRuntimeContext(params: { diff --git a/src/agents/embedded-agent-runner/compaction-runtime-context.test.ts b/src/agents/embedded-agent-runner/compaction-runtime-context.test.ts index 1b59a23aa3e9..f2b315526887 100644 --- a/src/agents/embedded-agent-runner/compaction-runtime-context.test.ts +++ b/src/agents/embedded-agent-runner/compaction-runtime-context.test.ts @@ -271,6 +271,7 @@ describe("buildEmbeddedCompactionRuntimeContext", () => { expect(result.provider).toBe("openai"); expect(result.runtimeProvider).toBeUndefined(); expect(result.contextProvider).toBeUndefined(); + expect(result.nativeHarnessCompaction).toBe(true); expect(result.model).toBe("gpt-5.5"); expect(result.authProfileId).toBeUndefined(); }); @@ -315,7 +316,10 @@ describe("buildEmbeddedCompactionRuntimeContext", () => { config: { models: { providers: { - openai: { models: [{ id: "gpt-5.5" }] }, + openai: { + baseUrl: "https://example.test/v1", + models: [{ id: "gpt-5.5" }], + }, }, }, } as unknown as OpenClawConfig, @@ -328,6 +332,7 @@ describe("buildEmbeddedCompactionRuntimeContext", () => { expect(result.provider).toBe("openai"); expect(result.runtimeProvider).toBeUndefined(); expect(result.contextProvider).toBeUndefined(); + expect(result.nativeHarnessCompaction).toBeUndefined(); expect(result.model).toBe("gpt-5.5"); expect(result.authProfileId).toBeUndefined(); }); @@ -387,6 +392,7 @@ describe("buildEmbeddedCompactionRuntimeContext", () => { expect(result.provider).toBe("openai"); expect(result.runtimeProvider).toBeUndefined(); expect(result.contextProvider).toBeUndefined(); + expect(result.nativeHarnessCompaction).toBe(true); expect(result.model).toBe("gpt-5.4-mini"); expect(result.authProfileId).toBeUndefined(); }); diff --git a/src/agents/embedded-agent-runner/compaction-runtime-context.ts b/src/agents/embedded-agent-runner/compaction-runtime-context.ts index 7d0b8f492bb9..d71c353a5fc1 100644 --- a/src/agents/embedded-agent-runner/compaction-runtime-context.ts +++ b/src/agents/embedded-agent-runner/compaction-runtime-context.ts @@ -70,6 +70,7 @@ export function resolveEmbeddedCompactionTarget(params: { provider: string | undefined; runtimeProvider?: string; contextProvider?: string; + nativeHarnessCompaction?: boolean; model: string | undefined; authProfileId: string | undefined; } { @@ -99,6 +100,7 @@ export function resolveEmbeddedCompactionTarget(params: { return { runtimeProvider: routedRuntimeProvider, contextProvider: useCodexHarnessRuntime ? routedRuntimeProvider : undefined, + ...(useCodexHarnessRuntime ? { nativeHarnessCompaction: true } : {}), }; }; if (!override) {