Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 29 additions & 10 deletions src/server/responses/compact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,22 +178,41 @@ function pruneCompactHandoffRoutes(now: number): void {
}
}

function rememberCompactHandoffRoute(req: Request, model: string, now = Date.now()): void {
const key = sessionLaneIdFromRequest(req.headers);
function compactHandoffRouteKey(req: Request, admission?: DataPlaneAdmission): string | null {
const lane = sessionLaneIdFromRequest(req.headers);
// A loopback request has no authenticated principal to bind this cross-request
// state to. Fail closed rather than treating a caller-controlled lane as identity.
if (!lane || !admission || admission.kind === "loopback") return null;
const principal = admission.kind === "configured" ? `configured:${admission.keyId}` : "environment";
return `${principal}\u0000${lane}`;
}

function rememberCompactHandoffRoute(
req: Request,
admission: DataPlaneAdmission | undefined,
model: string,
now = Date.now(),
): void {
const key = compactHandoffRouteKey(req, admission);
if (!key || model.length > COMPACT_HANDOFF_MODEL_MAX_LENGTH) return;
pruneCompactHandoffRoutes(now);
compactHandoffRoutes.delete(key);
compactHandoffRoutes.set(key, { model, lastUsedAt: now });
pruneCompactHandoffRoutes(now);
}

function forgetCompactHandoffRoute(req: Request): void {
const key = sessionLaneIdFromRequest(req.headers);
function forgetCompactHandoffRoute(req: Request, admission?: DataPlaneAdmission): void {
const key = compactHandoffRouteKey(req, admission);
if (key) compactHandoffRoutes.delete(key);
}

function compactHandoffRoute(req: Request, previousModel: string, now = Date.now()): string | null {
const key = sessionLaneIdFromRequest(req.headers);
function compactHandoffRoute(
req: Request,
admission: DataPlaneAdmission | undefined,
previousModel: string,
now = Date.now(),
): string | null {
const key = compactHandoffRouteKey(req, admission);
if (!key) return null;
pruneCompactHandoffRoutes(now);
const entry = compactHandoffRoutes.get(key);
Expand Down Expand Up @@ -953,9 +972,9 @@ export async function handleResponsesCompact(
// synthetic buffer errors are not upstream bodies and stay uninspected.
if (buffered.ok) {
inspectResponseLogJson(logCtx, await buffered.clone().text());
forgetCompactHandoffRoute(req);
forgetCompactHandoffRoute(req, admission);
} else if (quotaFailure && !storedPool401ReplayAttempted) {
const fallbackModel = compactHandoffRoute(req, raw.model);
const fallbackModel = compactHandoffRoute(req, admission, raw.model);
if (fallbackModel && !req.signal.aborted) {
const fallbackReq = new Request(req.url, {
method: "POST",
Expand Down Expand Up @@ -1075,7 +1094,7 @@ export async function handleResponsesCompact(
const result = new Response(JSON.stringify({ output: compactionItems }), {
headers: { "Content-Type": "application/json" },
});
rememberCompactHandoffRoute(req, raw.model);
rememberCompactHandoffRoute(req, admission, raw.model);
return result;
}
const encrypted = compactionItems[0]!.encrypted_content;
Expand All @@ -1086,6 +1105,6 @@ export async function handleResponsesCompact(
}
const summary = decoded;
const output = buildCompactV1Output(extractCompactUserMessages(inputItems), summary);
rememberCompactHandoffRoute(req, raw.model);
rememberCompactHandoffRoute(req, admission, raw.model);
return new Response(JSON.stringify({ output }), { headers: { "Content-Type": "application/json" } });
}
37 changes: 37 additions & 0 deletions tests/responses-compaction-routing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,7 @@ describe("compact alternate-account attempt (#913)", () => {
models: ["gpt-5.6-sol"],
};
const headers = { "x-codex-parent-thread-id": "compact-routed-handoff-thread" };
const admission = { kind: "configured", keyId: "compact-client", source: "dedicated" } as const;
const calls: Array<{ model: string; nativeCompact: boolean }> = [];
globalThis.fetch = (async (input: string | URL | Request, init?: RequestInit) => {
const url = typeof input === "string"
Expand All @@ -1053,6 +1054,8 @@ describe("compact alternate-account attempt (#913)", () => {
),
config,
{ model: "", provider: "" },
undefined,
admission,
);
expect(manual.status).toBe(200);
expect(calls).toEqual([{ model: "deepseek-v4-flash", nativeCompact: false }]);
Expand All @@ -1066,6 +1069,8 @@ describe("compact alternate-account attempt (#913)", () => {
),
config,
{ model: "", provider: "" },
undefined,
admission,
);
expect(unrelated.status).toBe(502);
expect(calls.length).toBeGreaterThan(0);
Expand All @@ -1081,6 +1086,8 @@ describe("compact alternate-account attempt (#913)", () => {
),
config,
logCtx,
undefined,
admission,
);

expect(automatic.status).toBe(200);
Expand All @@ -1092,6 +1099,36 @@ describe("compact alternate-account attempt (#913)", () => {
expect(calls.slice(0, -1).every(call => (
call.model === "gpt-5.6-sol" && call.nativeCompact
))).toBe(true);

calls.length = 0;
const otherPrincipal = await handleResponsesCompact(
compactionRequest(
baseCompactionBody({ model: "openai-apikey/gpt-5.6-sol" }),
undefined,
headers,
),
config,
{ model: "", provider: "" },
undefined,
{ kind: "configured", keyId: "different-client", source: "dedicated" },
);
expect(otherPrincipal.status).toBe(502);
expect(calls.every(call => call.model === "gpt-5.6-sol" && call.nativeCompact)).toBe(true);

calls.length = 0;
const unauthenticatedLoopback = await handleResponsesCompact(
compactionRequest(
baseCompactionBody({ model: "openai-apikey/gpt-5.6-sol" }),
undefined,
headers,
),
config,
{ model: "", provider: "" },
undefined,
{ kind: "loopback", source: "loopback" },
);
expect(unauthenticatedLoopback.status).toBe(502);
expect(calls.every(call => call.model === "gpt-5.6-sol" && call.nativeCompact)).toBe(true);
});
});

Expand Down
Loading