fix: route compaction auth and proxy payloads safely

This commit is contained in:
Peter Steinberger
2026-05-27 17:01:46 +01:00
parent d583b43b25
commit 77a7b52c05
4 changed files with 14 additions and 6 deletions

View File

@@ -539,11 +539,11 @@ describe("compactEmbeddedAgentSessionDirect hooks", () => {
});
findMockCall(
resolveModelMock,
([provider, modelId]) => provider === "openai" && modelId === "gpt-primary",
([provider, modelId]) => provider === "openai-codex" && modelId === "gpt-primary",
);
findMockCall(
resolveModelMock,
([provider, modelId]) => provider === "openai" && modelId === "gpt-fallback",
([provider, modelId]) => provider === "openai-codex" && modelId === "gpt-fallback",
);
expectRecordFields(mockCallArg(resolveEmbeddedAgentStreamFnMock, 1), {
authProfileId: "openai-codex:default",
@@ -655,7 +655,7 @@ describe("compactEmbeddedAgentSessionDirect hooks", () => {
});
expect(result.ok).toBe(true);
expect(mockCallArg(resolveModelMock)).toBe("openai");
expect(mockCallArg(resolveModelMock)).toBe("openai-codex");
expectRecordFields(mockCallArg(resolveContextWindowInfoMock), {
provider: "openai",
modelId: "gpt-5.5",

View File

@@ -501,6 +501,7 @@ async function compactEmbeddedAgentSessionDirectOnce(
// Keep the configured provider for harness policy, while auth/model loading below can
// route OpenAI compaction through Codex OAuth when that runtime owns the session credentials.
const provider = resolvedCompactionTarget.provider ?? DEFAULT_PROVIDER;
const runtimeProvider = resolvedCompactionTarget.runtimeProvider ?? provider;
const modelId = resolvedCompactionTarget.model ?? DEFAULT_MODEL;
const authProfileId = resolvedCompactionTarget.authProfileId;
let thinkLevel: ThinkLevel = params.thinkLevel ?? "off";
@@ -541,13 +542,13 @@ async function compactEmbeddedAgentSessionDirectOnce(
workspaceDir: resolvedWorkspace,
});
const { model, error, authStorage, modelRegistry } = await resolveModelAsync(
provider,
runtimeProvider,
modelId,
agentDir,
params.config,
);
if (!model) {
const reason = error ?? `Unknown model: ${provider}/${modelId}`;
const reason = error ?? `Unknown model: ${runtimeProvider}/${modelId}`;
return fail(reason);
}
let runtimeModel = model;

View File

@@ -75,9 +75,11 @@ describe("streamProxy", () => {
usage,
});
const body = JSON.parse(String(fetchMock.mock.calls[0]?.[1]?.body)) as {
model?: { headers?: unknown };
options?: { headers?: unknown };
};
expect(body.options).not.toHaveProperty("headers");
expect(body.model).not.toHaveProperty("headers");
});
it("returns an error result when EOF arrives without a terminal event", async () => {

View File

@@ -117,6 +117,11 @@ function buildProxyRequestOptions(options: ProxyStreamOptions): ProxySerializabl
};
}
function sanitizeProxyModel(model: Model): Model {
const { headers: _headers, ...safeModel } = model;
return safeModel as Model;
}
export function streamProxy(
model: Model,
context: Context,
@@ -164,7 +169,7 @@ export function streamProxy(
"Content-Type": "application/json",
},
body: JSON.stringify({
model,
model: sanitizeProxyModel(model),
context,
options: buildProxyRequestOptions(options),
}),