Skip to content
Merged
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
7 changes: 7 additions & 0 deletions src/codex/catalog/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,13 @@ export function deriveEntry(
// Routed (namespaced) models inherit the gpt template — correct its OpenAI/GPT identity
// and advertise the reasoning ladder Codex accepts.
if (isRouted) {
// A routed model is NOT the native template: never inherit its context
// window when /models omits context metadata (#992). Known metadata
// restores exact values below; otherwise the strict-fields fallback
// supplies the conservative 128k triple.
delete e.context_window;
delete e.max_context_window;
delete e.auto_compact_token_limit;
// Native id for identity text + metadata lookups — the slug may be an encoded
// alias (`provider/vendor-model`); the model object carries the native id.
const modelName = model?.id ?? slug.slice(slug.indexOf("/") + 1);
Expand Down
47 changes: 39 additions & 8 deletions tests/codex-catalog.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,7 @@ describe("Codex catalog routed normalization", () => {
expect(anthropic?.supports_parallel_tool_calls).toBe(false);
});

test("routed entries fill auto compact when context already exists on the template", () => {
test("routed entries fall to the conservative triple instead of inheriting template context (#992)", () => {
const template = {
...nativeTemplate(),
context_window: 272_000,
Expand All @@ -1060,9 +1060,11 @@ describe("Codex catalog routed normalization", () => {
]);
const routed = entries.find(e => e.slug === "local/qwen3-coder");

expect(routed?.context_window).toBe(272_000);
expect(routed?.max_context_window).toBe(272_000);
expect(routed?.auto_compact_token_limit).toBe(244_800);
// A routed model is not the native template: without known metadata the
// entry falls back to the conservative 128k triple.
expect(routed?.context_window).toBe(128_000);
expect(routed?.max_context_window).toBe(128_000);
expect(routed?.auto_compact_token_limit).toBe(115_200);
});

test("native gpt-5.4 uses its 1M context window override", () => {
Expand Down Expand Up @@ -1196,7 +1198,7 @@ describe("Codex catalog routed normalization", () => {
expect(sol?.priority).toBe(1);
});

test("routed entries still cap stale native max context to their active context window", () => {
test("routed entries drop stale native max context with the template window (#992)", () => {
const template = {
...nativeTemplate(),
context_window: 272_000,
Expand All @@ -1207,9 +1209,9 @@ describe("Codex catalog routed normalization", () => {
]);
const routed = entries.find(e => e.slug === "local/qwen3-coder");

expect(routed?.context_window).toBe(272_000);
expect(routed?.max_context_window).toBe(272_000);
expect(routed?.auto_compact_token_limit).toBe(244_800);
expect(routed?.context_window).toBe(128_000);
expect(routed?.max_context_window).toBe(128_000);
expect(routed?.auto_compact_token_limit).toBe(115_200);
});

test("buildCatalogEntries preserves native bare GPT template fields", () => {
Expand Down Expand Up @@ -2301,6 +2303,35 @@ describe("Codex catalog routed normalization", () => {
expect(routed?.default_reasoning_summary).toBe("none");
});

test("a routed model never inherits the native template's context window (#992)", () => {
// /models returns only the id: the routed entry must fall to the
// conservative 128k triple, never the native template's larger window.
const entries = buildCatalogEntries({ context_window: 372_000 }, [], [
{ provider: "relay", id: "relay-model" },
]);
const routed = entries.find(e => e.slug === "relay/relay-model");
expect(routed?.context_window).toBe(128_000);
expect(routed?.max_context_window).toBe(128_000);
expect(routed?.auto_compact_token_limit).toBe(115_200);
});

test("a provider context cap never invents routed capacity (#992)", () => {
const entries = buildCatalogEntries({ context_window: 372_000 }, [], [
{ provider: "relay", id: "relay-model", contextCap: 950_000 },
]);
const routed = entries.find(e => e.slug === "relay/relay-model");
expect(routed?.context_window).toBe(128_000);
});

test("known routed metadata still restores the exact context window (#992)", () => {
const entries = buildCatalogEntries({ context_window: 372_000 }, [], [
{ provider: "relay", id: "relay-model", contextWindow: 256_000 },
]);
const routed = entries.find(e => e.slug === "relay/relay-model");
expect(routed?.context_window).toBe(256_000);
expect(routed?.auto_compact_token_limit).toBe(Math.floor(256_000 * 0.9));
});
Comment on lines +2318 to +2333

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Assert the complete routed context contract.

Lines 2318-2324 assert only context_window for an oversized contextCap. A regression can advertise capacity through max_context_window or auto_compact_token_limit and still pass this test.

Lines 2326-2333 also omit max_context_window for explicit contextWindow metadata. Assert the full expected triples in both tests.

Proposed test additions
     expect(routed?.context_window).toBe(128_000);
+    expect(routed?.max_context_window).toBe(128_000);
+    expect(routed?.auto_compact_token_limit).toBe(115_200);
@@
     expect(routed?.context_window).toBe(256_000);
+    expect(routed?.max_context_window).toBe(256_000);
     expect(routed?.auto_compact_token_limit).toBe(Math.floor(256_000 * 0.9));

As per path instructions, “A behavior change in src/ should come with a focused regression test near the existing tests for that subsystem.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
test("a provider context cap never invents routed capacity (#992)", () => {
const entries = buildCatalogEntries({ context_window: 372_000 }, [], [
{ provider: "relay", id: "relay-model", contextCap: 950_000 },
]);
const routed = entries.find(e => e.slug === "relay/relay-model");
expect(routed?.context_window).toBe(128_000);
});
test("known routed metadata still restores the exact context window (#992)", () => {
const entries = buildCatalogEntries({ context_window: 372_000 }, [], [
{ provider: "relay", id: "relay-model", contextWindow: 256_000 },
]);
const routed = entries.find(e => e.slug === "relay/relay-model");
expect(routed?.context_window).toBe(256_000);
expect(routed?.auto_compact_token_limit).toBe(Math.floor(256_000 * 0.9));
});
test("a provider context cap never invents routed capacity (`#992`)", () => {
const entries = buildCatalogEntries({ context_window: 372_000 }, [], [
{ provider: "relay", id: "relay-model", contextCap: 950_000 },
]);
const routed = entries.find(e => e.slug === "relay/relay-model");
expect(routed?.context_window).toBe(128_000);
expect(routed?.max_context_window).toBe(128_000);
expect(routed?.auto_compact_token_limit).toBe(115_200);
});
test("known routed metadata still restores the exact context window (`#992`)", () => {
const entries = buildCatalogEntries({ context_window: 372_000 }, [], [
{ provider: "relay", id: "relay-model", contextWindow: 256_000 },
]);
const routed = entries.find(e => e.slug === "relay/relay-model");
expect(routed?.context_window).toBe(256_000);
expect(routed?.max_context_window).toBe(256_000);
expect(routed?.auto_compact_token_limit).toBe(Math.floor(256_000 * 0.9));
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/codex-catalog.test.ts` around lines 2318 - 2333, Extend both
routed-capacity tests around buildCatalogEntries to assert the complete context
contract: context_window, max_context_window, and auto_compact_token_limit. For
the oversized contextCap case, verify all three values remain capped at the
expected routed capacity; for explicit contextWindow metadata, verify
max_context_window matches 256,000 and auto_compact_token_limit remains
floor(256,000 × 0.9), alongside the existing context_window assertions.

Source: Path instructions


test("model-specific reasoning-summary opt-out reaches the routed catalog (#323)", async () => {
const models = await gatherRoutedModels({
providers: {
Expand Down
Loading