Skip to content
Closed
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
11 changes: 5 additions & 6 deletions src/claude/context-windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,12 @@ export function buildClaudeContextWindows(
m.contextWindow > 0 &&
!(m.provider === "anthropic" && m.contextWindow < ONE_MILLION),
);
// Bare routed ids are registered only when unambiguous across providers (audit
// 021 #5) — natives are registered first, so a native slug always wins the bare
// key. Counted over the rows that can actually claim the key: a row this loop
// skips contributes no window, so letting it veto the bare key withholds an
// answer that was never in doubt.
// Bare routed ids are registered only when unambiguous across every provider
// that can route the id (audit 021 #5) — natives are registered first, so a
// native slug always wins the bare key. Rows without a registrable window must
// still count because they remain valid routing candidates for the bare id.
const bareCounts = new Map<string, number>();
for (const m of registrable) bareCounts.set(m.id, (bareCounts.get(m.id) ?? 0) + 1);
for (const m of routedModels) bareCounts.set(m.id, (bareCounts.get(m.id) ?? 0) + 1);
for (const m of registrable) {
const window = m.contextWindow as number;
put(`${m.provider}/${m.id}`, window);
Expand Down
19 changes: 10 additions & 9 deletions tests/claude-context-windows.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,30 +133,31 @@ describe("auto-context (devlog 260712 020 + audit 021)", () => {
expect(map["gpt-5.6-sol"]).toBe(272_000); // native default, not 999k
});

test("a row that registers nothing does not make a bare id ambiguous", () => {
// Only one of these two rows can claim the bare key, so there is nothing to
// be ambiguous about — withholding it left a 1M model with no window, and a
// slot set to the bare id lost its [1m] marker.
test("rows without a registrable window still make a bare id ambiguous", () => {
// Both rows remain routing candidates even though only one has a window, so
// the bare selector cannot safely inherit either provider's metadata.
const noWindow = buildClaudeContextWindows([], [
{ provider: "a", id: "shared-model", contextWindow: 1_000_000 },
{ provider: "b", id: "shared-model" } as CatalogModel,
]);
expect(noWindow["shared-model"]).toBe(1_000_000);
expect(noWindow["shared-model"]).toBeUndefined();
expect(noWindow["a/shared-model"]).toBe(1_000_000);

// Same for a row the anthropic sub-1M guard skips.
// Same for a row the anthropic sub-1M guard skips from registration.
const anthropicSkipped = buildClaudeContextWindows([], [
{ provider: "openrouter", id: "claude-x", contextWindow: 1_000_000 },
{ provider: "anthropic", id: "claude-x", contextWindow: 200_000 },
]);
expect(anthropicSkipped["claude-x"]).toBe(1_000_000);
expect(anthropicSkipped["claude-x"]).toBeUndefined();
expect(anthropicSkipped["openrouter/claude-x"]).toBe(1_000_000);
expect(anthropicSkipped["anthropic/claude-x"]).toBeUndefined();

// A zero or negative window is not a claim either.
// Zero and negative windows also remain routing candidates.
const zeroWindow = buildClaudeContextWindows([], [
{ provider: "a", id: "shared-model", contextWindow: 400_000 },
{ provider: "b", id: "shared-model", contextWindow: 0 },
]);
expect(zeroWindow["shared-model"]).toBe(400_000);
expect(zeroWindow["shared-model"]).toBeUndefined();
});

test("two providers that both register keep the bare id withheld", () => {
Expand Down
Loading