Skip to content
Merged
26 changes: 25 additions & 1 deletion src/codex/catalog/provider-fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,32 @@ export function clearGatherRoutedModelsInflight(): void {
gatherInflight.clear();
}

const NUMERIC_MODEL_ID_SEGMENT = /^\d+$/;

/**
* Resolve an unknown Claude point release or date pin from the nearest configured
* family row. Only numeric tail segments are removed so unrelated model families
* cannot inherit one another's limits.
*/
function anthropicFamilyContextWindow(
record: Record<string, number> | undefined,
id: string,
): number | undefined {
if (!record || !id.startsWith("claude-")) return undefined;
Comment thread
everton-dgn marked this conversation as resolved.
Outdated
let candidate = id;
while (true) {
const cut = candidate.lastIndexOf("-");
if (cut <= 0 || !NUMERIC_MODEL_ID_SEGMENT.test(candidate.slice(cut + 1))) return undefined;
candidate = candidate.slice(0, cut);
const value = modelRecordValue(record, candidate);
if (typeof value === "number" && value > 0) return value;
}
}

export function configuredContextWindow(prov: OcxProviderConfig, id: string): number | undefined {
const configured = modelRecordValue(prov.modelContextWindows, id) ?? prov.contextWindow;
const configured = modelRecordValue(prov.modelContextWindows, id)
?? (prov.adapter === "anthropic" ? anthropicFamilyContextWindow(prov.modelContextWindows, id) : undefined)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Share family resolution with request admission

For an Anthropic numeric variant with a smaller provider-wide fallback—for example the tested claude-fable-5-2 with contextWindow: 128000 and a 1M family entry—the catalog and ocx models now report 1M, but resolveInputCeiling in src/server/responses/input-admission.ts:149-150 still performs only an exact lookup and therefore rejects requests above the 128k fallback. candidateCapabilityEvidence and the compatibility report have the same divergent lookup. Move this resolver to a shared leaf module and use it in every runtime consumer, with an input-admission regression test for the inherited variant.

AGENTS.md reference: src/AGENTS.md:L18-L18

Useful? React with 👍 / 👎.

?? prov.contextWindow;
return typeof configured === "number" && configured > 0 ? configured : undefined;
}

Expand Down
28 changes: 28 additions & 0 deletions tests/provider-registry-parity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,34 @@ describe("provider registry parity", () => {
}
});

test("unknown Claude numeric variants inherit the nearest configured family context window", () => {
const anthropic = PROVIDER_REGISTRY.find(entry => entry.id === "anthropic");
const seed = providerConfigSeed(anthropic!);
const contextWindow = (id: string) => applyProviderConfigHints("anthropic", seed, {
id,
provider: "anthropic",
}).contextWindow;

expect(contextWindow("claude-fable-5-2")).toBe(1_000_000);
expect(contextWindow("claude-haiku-4-5-20251001")).toBe(200_000);
expect(contextWindow("claude-opus-4-1-20250805")).toBeUndefined();
expect(contextWindow("claude-3-7-sonnet-20250219")).toBeUndefined();
});

test("context-window family inheritance stays scoped to the Anthropic adapter", () => {
const minimax = PROVIDER_REGISTRY.find(entry => entry.id === "minimax");
const seed = {
...providerConfigSeed(minimax!),
modelContextWindows: { "MiniMax-M3": 204_800 },
};
const model = applyProviderConfigHints("minimax", seed, {
id: "MiniMax-M3-1",
provider: "minimax",
});

expect(model.contextWindow).toBeUndefined();
});

test("GUI preset projection preserves current featured set plus key catalog and custom", () => {
const featured = deriveFeaturedProviderIds();
expect(featured).toEqual([
Expand Down
Loading