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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **fix(grok-cli):** Grok Build discovery prefers the grok-cli registry context window over the 256k that Grok Build `/v1/models` reports for every model, and never stamps a default; the reconciler drops stale `auto:discovery` pins when discovery reports no window, so `grok-4.5`/`4.6`/`4.7` advertise their real 500k window ([#15412](https://github.com/diegosouzapw/OmniRoute/pull/15412))
1 change: 0 additions & 1 deletion open-sse/config/grokBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export const GROK_BUILD_DEVICE_CODE_URL = `${GROK_BUILD_OAUTH_ISSUER}/oauth2/dev
export const GROK_BUILD_TOKEN_URL = `${GROK_BUILD_OAUTH_ISSUER}/oauth2/token`;

export const GROK_BUILD_DEFAULT_CLIENT_VERSION = "1.0.41";
export const GROK_BUILD_DEFAULT_CONTEXT_WINDOW = 256_000;
export const GROK_BUILD_DEFAULT_REASONING_EFFORT = "high";
export const GROK_BUILD_SUPPORTED_REASONING_EFFORTS = Object.freeze([
"low",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { getAntigravityModelsDiscoveryUrls } from "@omniroute/open-sse/config/antigravityUpstream.ts";
import {
GROK_BUILD_DEFAULT_CONTEXT_WINDOW,
getGrokBuildModelsHeaders,
GROK_BUILD_MODELS_URL,
GROK_BUILD_SUPPORTED_REASONING_EFFORTS,
} from "@omniroute/open-sse/config/grokBuild.ts";
import { grok_cliProvider } from "@omniroute/open-sse/config/providers/registry/grok-cli/index.ts";
import { getAntigravityContentHeaders } from "@omniroute/open-sse/services/antigravityHeaders.ts";
import { parseGeminiModelsList } from "@/lib/providerModels/geminiModelsParser";
import { buildClaudeModelsHeaders } from "@/lib/providerModels/claudeModelsHeaders";
Expand Down Expand Up @@ -246,6 +246,37 @@ function grokBuildPositiveNumber(...values: unknown[]): number | undefined {
);
}

const GROK_CLI_REGISTRY_CONTEXT_BY_ID = new Map<string, number>(
grok_cliProvider.models.flatMap((model) => {
const window = model.contextLength;
return typeof window === "number" && Number.isInteger(window) && window > 0
? ([[model.id, window]] as Array<[string, number]>)
: [];
})
);

function resolveGrokBuildInputTokenLimit(
model: GrokBuildModelRecord,
metadata: GrokBuildModelRecord,
id: string
): number | undefined {
// Registry first. Grok Build's /v1/models advertises contextWindow 256000 for every
// model, yet the backend serves grok-4.6 up to 500k (prod: 88 successful requests
// with 256k-485k input; upstream rejects at "> 500000 tokens"). Trusting the
// advertised number pinned 256k auto:discovery overrides over the verified window.
// Models the registry does not know keep the upstream number — under-advertising
// only makes clients compact early — and never get an invented default.
return (
GROK_CLI_REGISTRY_CONTEXT_BY_ID.get(id) ??
grokBuildPositiveNumber(
model.contextWindow,
model.context_window,
metadata.contextWindow,
metadata.totalContextTokens
)
);
}

function getGrokBuildModelItems(data: unknown): unknown[] {
const envelope = asGrokBuildRecord(data);
if (Array.isArray(data)) return data;
Expand Down Expand Up @@ -349,13 +380,7 @@ function normalizeGrokBuildModel(value: unknown): GrokBuildModelRecord | null {
// here would route their request shape to the wrong upstream endpoint.
if (backend !== "responses") return null;

const inputTokenLimit =
grokBuildPositiveNumber(
model.contextWindow,
model.context_window,
metadata.contextWindow,
metadata.totalContextTokens
) || GROK_BUILD_DEFAULT_CONTEXT_WINDOW;
const inputTokenLimit = resolveGrokBuildInputTokenLimit(model, metadata, id);
const outputTokenLimit = grokBuildPositiveNumber(
model.maxCompletionTokens,
model.max_completion_tokens
Expand All @@ -369,7 +394,7 @@ function normalizeGrokBuildModel(value: unknown): GrokBuildModelRecord | null {
name: grokBuildString(model.name, id) || id,
owned_by: "grok-cli",
...(description ? { description } : {}),
inputTokenLimit,
...(typeof inputTokenLimit === "number" ? { inputTokenLimit } : {}),
...(outputTokenLimit ? { outputTokenLimit } : {}),
...(supportsThinking ? { supportsThinking: true } : {}),
...(supportedThinkingEfforts.length > 0 ? { supportedThinkingEfforts } : {}),
Expand Down
10 changes: 9 additions & 1 deletion src/lib/contextWindowResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,15 @@ export function reconcileContextWindows(
for (const { provider, modelId, window } of discovered) {
result.scanned++;
if (!provider || !modelId) continue;
if (typeof window !== "number" || !Number.isInteger(window) || window <= 0) continue;
if (typeof window !== "number" || !Number.isInteger(window) || window <= 0) {
// Discovery omitted a real window. Drop a stale auto:discovery pin
// (e.g. grok-cli's old 256k fallback) so registry/models.dev can win.
if (deps.getExistingSource(provider, modelId) === "auto:discovery") {
deps.removeOverride(provider, modelId);
result.removed++;
}
continue;
}

const existingSource = deps.getExistingSource(provider, modelId);
if (existingSource === "manual") {
Expand Down
62 changes: 51 additions & 11 deletions tests/unit/context-window-reconcile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import {

// Feature 5004 — pure reconcile logic (auto:discovery overrides), deps injected.

function makeDeps(
catalog: Record<string, number | null>,
existing: Record<string, string> = {}
) {
function makeDeps(catalog: Record<string, number | null>, existing: Record<string, string> = {}) {
const writes: Array<[string, string, number]> = [];
const removes: Array<[string, string]> = [];
const deps: ReconcileDeps = {
Expand All @@ -25,7 +22,9 @@ function makeDeps(

describe("reconcileContextWindows (5004)", () => {
it("writes an auto override when the discovered window diverges from the catalog", () => {
const discovered: DiscoveredWindow[] = [{ provider: "openai", modelId: "gpt-x", window: 400000 }];
const discovered: DiscoveredWindow[] = [
{ provider: "openai", modelId: "gpt-x", window: 400000 },
];
const { deps, writes } = makeDeps({ "openai/gpt-x": 128000 });
const r = reconcileContextWindows(discovered, deps);
assert.deepEqual(writes, [["openai", "gpt-x", 400000]]);
Expand All @@ -34,7 +33,9 @@ describe("reconcileContextWindows (5004)", () => {
});

it("does nothing when the discovered window already matches the catalog", () => {
const discovered: DiscoveredWindow[] = [{ provider: "openai", modelId: "gpt-x", window: 128000 }];
const discovered: DiscoveredWindow[] = [
{ provider: "openai", modelId: "gpt-x", window: 128000 },
];
const { deps, writes, removes } = makeDeps({ "openai/gpt-x": 128000 });
const r = reconcileContextWindows(discovered, deps);
assert.deepEqual(writes, []);
Expand All @@ -43,16 +44,26 @@ describe("reconcileContextWindows (5004)", () => {
});

it("self-heals: removes a stale auto override once the catalog catches up", () => {
const discovered: DiscoveredWindow[] = [{ provider: "openai", modelId: "gpt-x", window: 128000 }];
const { deps, removes } = makeDeps({ "openai/gpt-x": 128000 }, { "openai/gpt-x": "auto:discovery" });
const discovered: DiscoveredWindow[] = [
{ provider: "openai", modelId: "gpt-x", window: 128000 },
];
const { deps, removes } = makeDeps(
{ "openai/gpt-x": 128000 },
{ "openai/gpt-x": "auto:discovery" }
);
const r = reconcileContextWindows(discovered, deps);
assert.deepEqual(removes, [["openai", "gpt-x"]]);
assert.equal(r.removed, 1);
});

it("never overwrites or removes a manual override", () => {
const discovered: DiscoveredWindow[] = [{ provider: "openai", modelId: "gpt-x", window: 999999 }];
const { deps, writes, removes } = makeDeps({ "openai/gpt-x": 128000 }, { "openai/gpt-x": "manual" });
const discovered: DiscoveredWindow[] = [
{ provider: "openai", modelId: "gpt-x", window: 999999 },
];
const { deps, writes, removes } = makeDeps(
{ "openai/gpt-x": 128000 },
{ "openai/gpt-x": "manual" }
);
const r = reconcileContextWindows(discovered, deps);
assert.deepEqual(writes, []);
assert.deepEqual(removes, []);
Expand All @@ -77,10 +88,39 @@ describe("reconcileContextWindows (5004)", () => {
});

it("writes an override when the catalog does not know the model (catalog null)", () => {
const discovered: DiscoveredWindow[] = [{ provider: "local", modelId: "my-7b", window: 131072 }];
const discovered: DiscoveredWindow[] = [
{ provider: "local", modelId: "my-7b", window: 131072 },
];
const { deps, writes } = makeDeps({}); // catalog null for everything
const r = reconcileContextWindows(discovered, deps);
assert.deepEqual(writes, [["local", "my-7b", 131072]]);
assert.equal(r.written, 1);
});

it("removes a stale auto:discovery pin when discovery omits the window", () => {
const discovered: DiscoveredWindow[] = [
{ provider: "grok-cli", modelId: "grok-4.6", window: null },
];
const { deps, writes } = makeDeps(
{ "grok-cli/grok-4.6": 256000 },
{ "grok-cli/grok-4.6": "auto:discovery" }
);
const r = reconcileContextWindows(discovered, deps);
assert.deepEqual(writes, []);
assert.equal(r.removed, 1);
assert.equal(r.written, 0);
});

it("keeps a manual override when discovery omits the window", () => {
const discovered: DiscoveredWindow[] = [
{ provider: "grok-cli", modelId: "grok-4.6", window: null },
];
const { deps, writes } = makeDeps(
{ "grok-cli/grok-4.6": 256000 },
{ "grok-cli/grok-4.6": "manual" }
);
const r = reconcileContextWindows(discovered, deps);
assert.deepEqual(writes, []);
assert.equal(r.removed, 0);
});
});
45 changes: 43 additions & 2 deletions tests/unit/grok-cli-responses-compat.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import assert from "node:assert/strict";

import { grok_cliProvider } from "../../open-sse/config/providers/registry/grok-cli/index.ts";
import {
GROK_BUILD_DEFAULT_CONTEXT_WINDOW,
getGrokBuildClientVersion,
getGrokBuildUserAgent,
GROK_BUILD_MODELS_URL,
Expand Down Expand Up @@ -206,9 +205,51 @@ test("grok-cli live model discovery uses the authenticated session contract", ()
id: "session-only-alias",
name: "Session Only",
owned_by: "grok-cli",
inputTokenLimit: GROK_BUILD_DEFAULT_CONTEXT_WINDOW,
apiFormat: "responses",
supportedEndpoints: ["responses"],
},
]);
});

test("grok-cli discovery prefers the registry window over Grok Build's advertised one", () => {
// Grok Build /v1/models advertises contextWindow 256000 for every model, but the
// backend serves grok-4.6 up to 500k: prod logged 88 successful grok-4.6 requests
// with 256k-485k input tokens and upstream rejects at "> 500000 tokens". Trusting
// the advertised number pinned 256k auto:discovery overrides over the verified
// registry window. Unknown models keep the upstream number (under-advertising is
// safe), and models with neither stay unadvertised.
const config = PROVIDER_MODELS_CONFIG["grok-cli"];
const models = config.parseResponse({
data: [
{
id: "grok-4.6",
model: "grok-4.6",
name: "Grok 4.6",
contextWindow: 256000,
apiBackend: "responses",
},
{
id: "grok-4.5",
model: "grok-4.5",
name: "Grok 4.5",
apiBackend: "responses",
},
{
id: "grok-next-build",
name: "Grok Next Build",
contextWindow: 256000,
apiBackend: "responses",
},
{
id: "session-only-alias",
name: "Session Only",
apiBackend: "responses",
},
],
});
const byId = Object.fromEntries(models.map((model) => [model.id, model]));
assert.equal(byId["grok-4.6"].inputTokenLimit, 500000);
assert.equal(byId["grok-4.5"].inputTokenLimit, 500000);
assert.equal(byId["grok-next-build"].inputTokenLimit, 256000);
assert.equal("inputTokenLimit" in byId["session-only-alias"], false);
});
Loading