fix(codex): keep context engine on canonical session key

Ensure Codex context-engine history uses the run session key even when sandbox policy uses a per-peer key.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Neerav Makwana
2026-05-21 09:02:11 -04:00
committed by Josh Lehman
parent 1b1580cbc3
commit ceb458c973
2 changed files with 47 additions and 13 deletions
@@ -348,6 +348,39 @@ describe("runCodexAppServerAttempt context-engine lifecycle", () => {
expect(openSpy).not.toHaveBeenCalled();
});
it("keeps context-engine history bound to the run session when sandbox key differs", async () => {
const sessionFile = path.join(tempDir, "session.jsonl");
const workspaceDir = path.join(tempDir, "workspace");
SessionManager.open(sessionFile).appendMessage(
assistantMessage("canonical main context", Date.now()) as never,
);
const contextEngine = createContextEngine();
const harness = createStartedThreadHarness();
const params = createParams(sessionFile, workspaceDir);
params.sessionKey = "agent:main:main";
params.sandboxSessionKey = "agent:main:telegram:default:direct:12345";
params.contextEngine = contextEngine;
const run = runCodexAppServerAttempt(params);
await harness.waitForMethod("turn/start");
if (!contextEngine.bootstrap) {
throw new Error("expected bootstrap hook");
}
const bootstrapParams = requireFirstCallArg(contextEngine.bootstrap, "bootstrap") as Parameters<
NonNullable<ContextEngine["bootstrap"]>
>[0];
expect(bootstrapParams.sessionKey).toBe("agent:main:main");
const assembleParams = requireFirstCallArg(contextEngine.assemble, "assemble") as Parameters<
ContextEngine["assemble"]
>[0];
expect(assembleParams.sessionKey).toBe("agent:main:main");
await harness.completeTurn();
await run;
});
it("uses the runtime token budget for large Codex context-engine projections", async () => {
const sessionFile = path.join(tempDir, "session.jsonl");
const workspaceDir = path.join(tempDir, "workspace");
+14 -13
View File
@@ -808,6 +808,7 @@ export async function runCodexAppServerAttempt(
await fs.mkdir(resolvedWorkspace, { recursive: true });
const sandboxSessionKey =
params.sandboxSessionKey?.trim() || params.sessionKey?.trim() || params.sessionId;
const contextSessionKey = params.sessionKey?.trim() || sandboxSessionKey;
const sandbox = await resolveSandboxContext({
config: params.config,
sessionKey: sandboxSessionKey,
@@ -882,7 +883,7 @@ export async function runCodexAppServerAttempt(
});
const runtimeParams = {
...params,
sessionKey: sandboxSessionKey,
sessionKey: contextSessionKey,
...(startupAuthProfileId ? { authProfileId: startupAuthProfileId } : {}),
};
let activeSessionId = params.sessionId;
@@ -1000,7 +1001,7 @@ export async function runCodexAppServerAttempt(
hadSessionFile,
contextEngine: activeContextEngine,
sessionId: activeSessionId,
sessionKey: sandboxSessionKey,
sessionKey: contextSessionKey,
sessionFile: activeSessionFile,
runtimeContext: buildActiveContextEngineRuntimeContext(),
runMaintenance: runHarnessContextEngineMaintenance,
@@ -1014,7 +1015,7 @@ export async function runCodexAppServerAttempt(
params,
resolvedWorkspace,
effectiveWorkspace,
sessionKey: sandboxSessionKey,
sessionKey: contextSessionKey,
sessionAgentId,
});
const baseDeveloperInstructions = joinPresentSections(
@@ -1047,7 +1048,7 @@ export async function runCodexAppServerAttempt(
const assembled = await assembleHarnessContextEngine({
contextEngine: activeContextEngine,
sessionId: activeSessionId,
sessionKey: sandboxSessionKey,
sessionKey: contextSessionKey,
messages: historyMessages,
tokenBudget: params.contextTokenBudget,
availableTools: new Set(toolBridge.specs.map((tool) => tool.name).filter(isNonEmptyString)),
@@ -1087,7 +1088,7 @@ export async function runCodexAppServerAttempt(
: { project: true, reason: "per-turn-projection" };
embeddedAgentLog.info("codex app-server context-engine projection decision", {
sessionId: params.sessionId,
sessionKey: sandboxSessionKey,
sessionKey: contextSessionKey,
engineId: activeContextEngine.info.id,
mode: contextEngineProjection?.mode ?? assembled.contextProjection?.mode ?? "per_turn",
epoch: contextEngineProjection?.epoch,
@@ -1148,7 +1149,7 @@ export async function runCodexAppServerAttempt(
};
const systemPromptReport = buildCodexSystemPromptReport({
attempt: params,
sessionKey: sandboxSessionKey,
sessionKey: contextSessionKey,
workspaceDir: effectiveWorkspace,
developerInstructions: promptBuild.developerInstructions,
workspaceBootstrapContext,
@@ -2254,7 +2255,7 @@ export async function runCodexAppServerAttempt(
"codex app-server context-engine turn overflowed; forcing context-engine compaction",
{
sessionId: activeSessionId,
sessionKey: sandboxSessionKey,
sessionKey: contextSessionKey,
threadId: thread.threadId,
engineId: activeContextEngine.info.id,
tokenBudget: params.contextTokenBudget,
@@ -2273,7 +2274,7 @@ export async function runCodexAppServerAttempt(
activeContextEngine,
{
sessionId: activeSessionId,
sessionKey: sandboxSessionKey,
sessionKey: contextSessionKey,
sessionFile: activeSessionFile,
tokenBudget: params.contextTokenBudget,
force: true,
@@ -2291,7 +2292,7 @@ export async function runCodexAppServerAttempt(
);
embeddedAgentLog.info("codex app-server context-engine forced compaction result", {
sessionId: activeSessionId,
sessionKey: sandboxSessionKey,
sessionKey: contextSessionKey,
engineId: activeContextEngine.info.id,
ok: compactResult.ok,
compacted: compactResult.compacted,
@@ -2307,7 +2308,7 @@ export async function runCodexAppServerAttempt(
await runHarnessContextEngineMaintenance({
contextEngine: activeContextEngine,
sessionId: activeSessionId,
sessionKey: sandboxSessionKey,
sessionKey: contextSessionKey,
sessionFile: activeSessionFile,
reason: "compaction",
runtimeContext: maintenanceRuntimeContext,
@@ -2317,7 +2318,7 @@ export async function runCodexAppServerAttempt(
} catch (compactErr) {
embeddedAgentLog.warn("codex app-server context-engine forced compaction failed", {
sessionId: params.sessionId,
sessionKey: sandboxSessionKey,
sessionKey: contextSessionKey,
engineId: activeContextEngine.info.id,
error: formatErrorMessage(compactErr),
});
@@ -2682,7 +2683,7 @@ export async function runCodexAppServerAttempt(
params,
agentId: sessionAgentId,
result,
sessionKey: sandboxSessionKey,
sessionKey: contextSessionKey,
threadId: thread.threadId,
turnId: activeTurnId,
});
@@ -2715,7 +2716,7 @@ export async function runCodexAppServerAttempt(
aborted: finalAborted,
yieldAborted: Boolean(result.yieldDetected),
sessionIdUsed: activeSessionId,
sessionKey: sandboxSessionKey,
sessionKey: contextSessionKey,
sessionFile: activeSessionFile,
messagesSnapshot: finalMessages,
prePromptMessageCount,