diff --git a/open-sse/config/grokCli.js b/open-sse/config/grokCli.js index f2e024e4..3197116e 100644 --- a/open-sse/config/grokCli.js +++ b/open-sse/config/grokCli.js @@ -1,8 +1,11 @@ -export const GROK_CLI_VERSION = "0.2.99"; +// cli-chat-proxy rejects older identities with HTTP 426. Keep this on a +// current @xai-official/grok release (1.0.44 as of 2026-10-01; minimum 1.0.13). +export const GROK_CLI_VERSION = "1.0.44"; export const GROK_CLI_MODEL = "grok-build"; export const GROK_CLI_BASE_URL = "https://cli-chat-proxy.grok.com/v1"; export const GROK_CLI_CLIENT_IDENTIFIER = "grok-shell"; export const GROK_CLI_USER_AGENT = `grok-shell/${GROK_CLI_VERSION} (linux; x86_64)`; +export const GROK_CLI_PAGER_USER_AGENT = `grok-pager/${GROK_CLI_VERSION} grok-shell/${GROK_CLI_VERSION} (linux; x86_64)`; export function supportsGrokCliReasoningEffort(model) { // ponytail: unknown models omit effort until live metadata reaches dispatch. diff --git a/open-sse/providers/registry/grok-cli.js b/open-sse/providers/registry/grok-cli.js index 403c1abe..ea87e000 100644 --- a/open-sse/providers/registry/grok-cli.js +++ b/open-sse/providers/registry/grok-cli.js @@ -1,7 +1,7 @@ /** * Grok CLI / Grok Build (cli-chat-proxy.grok.com) * - * Source of truth: wire capture of official @xai-official/grok 0.2.99 + * Source of truth: wire capture of official @xai-official/grok 1.0.44 * talking to https://cli-chat-proxy.grok.com (OpenAI Responses API). * * Distinct from: diff --git a/src/app/api/providers/[id]/test/testUtils.js b/src/app/api/providers/[id]/test/testUtils.js index 7f9eedeb..27847c2c 100644 --- a/src/app/api/providers/[id]/test/testUtils.js +++ b/src/app/api/providers/[id]/test/testUtils.js @@ -5,6 +5,7 @@ import { isOpenAICompatibleProvider, isAnthropicCompatibleProvider } from "@/sha import { getDefaultModel } from "open-sse/config/providerModels.js"; import { resolveOllamaLocalHost, PROVIDERS } from "open-sse/config/providers.js"; import { CODEX_CLI_VERSION } from "open-sse/config/appConstants.js"; +import { GROK_CLI_PAGER_USER_AGENT, GROK_CLI_VERSION } from "open-sse/config/grokCli.js"; import { refreshProviderCredentials, shouldRefreshCredentials, @@ -123,10 +124,10 @@ const OAUTH_TEST_CONFIG = { extraHeaders: { Accept: "application/json", ...(PROVIDERS["grok-cli"]?.headers || { - "User-Agent": "grok-pager/0.2.93 grok-shell/0.2.93 (linux; x86_64)", + "User-Agent": GROK_CLI_PAGER_USER_AGENT, "x-xai-token-auth": "xai-grok-cli", "x-grok-client-identifier": "grok-pager", - "x-grok-client-version": "0.2.93", + "x-grok-client-version": GROK_CLI_VERSION, }), }, refreshable: true, diff --git a/src/lib/oauth/providers/grok-cli.js b/src/lib/oauth/providers/grok-cli.js index 2bd853b2..fcc79fe8 100644 --- a/src/lib/oauth/providers/grok-cli.js +++ b/src/lib/oauth/providers/grok-cli.js @@ -1,3 +1,4 @@ +import { GROK_CLI_PAGER_USER_AGENT, GROK_CLI_VERSION } from "open-sse/config/grokCli.js"; import { GROK_CLI_CONFIG } from "../constants/oauth.js"; import { decodeXaiIdTokenEmail, extractEmailFromAccessToken } from "../providerHelpers.js"; @@ -18,7 +19,7 @@ const grokCli = { headers: { "Content-Type": "application/x-www-form-urlencoded", Accept: "application/json", - "User-Agent": "grok-pager/0.2.93 grok-shell/0.2.93 (linux; x86_64)", + "User-Agent": GROK_CLI_PAGER_USER_AGENT, }, body, }); @@ -36,7 +37,7 @@ const grokCli = { headers: { "Content-Type": "application/x-www-form-urlencoded", Accept: "application/json", - "User-Agent": "grok-pager/0.2.93 grok-shell/0.2.93 (linux; x86_64)", + "User-Agent": GROK_CLI_PAGER_USER_AGENT, }, body: new URLSearchParams({ grant_type: "urn:ietf:params:oauth:grant-type:device_code", @@ -69,9 +70,9 @@ const grokCli = { headers: { Authorization: `Bearer ${tokens.access_token}`, Accept: "application/json", - "User-Agent": "grok-pager/0.2.93 grok-shell/0.2.93 (linux; x86_64)", + "User-Agent": GROK_CLI_PAGER_USER_AGENT, "x-xai-token-auth": "xai-grok-cli", - "x-grok-client-version": "0.2.93", + "x-grok-client-version": GROK_CLI_VERSION, }, }); if (res.ok) return { user: await res.json() }; diff --git a/tests/__baseline__/providers-baseline.json b/tests/__baseline__/providers-baseline.json index d8fb0e92..06a65846 100644 --- a/tests/__baseline__/providers-baseline.json +++ b/tests/__baseline__/providers-baseline.json @@ -417,13 +417,13 @@ "modelsUrl": "https://cli-chat-proxy.grok.com/v1/models", "userUrl": "https://cli-chat-proxy.grok.com/v1/user", "billingUrl": "https://cli-chat-proxy.grok.com/v1/billing", - "clientVersion": "0.2.99", + "clientVersion": "1.0.44", "clientIdentifier": "grok-shell", "tokenAuth": "xai-grok-cli", "headers": { - "User-Agent": "grok-shell/0.2.99 (linux; x86_64)", + "User-Agent": "grok-shell/1.0.44 (linux; x86_64)", "x-grok-client-identifier": "grok-shell", - "x-grok-client-version": "0.2.99" + "x-grok-client-version": "1.0.44" }, "usage": { "url": "https://cli-chat-proxy.grok.com/v1/billing?format=credits", diff --git a/tests/unit/grok-cli-executor.test.js b/tests/unit/grok-cli-executor.test.js index 519bf038..a21d819d 100644 --- a/tests/unit/grok-cli-executor.test.js +++ b/tests/unit/grok-cli-executor.test.js @@ -98,7 +98,7 @@ describe("GrokCliExecutor", () => { expect(headers.Accept).toBe("text/event-stream"); expect(headers["x-xai-token-auth"]).toBeUndefined(); expect(headers["x-grok-client-identifier"]).toBe("grok-shell"); - expect(headers["x-grok-client-version"]).toBe("0.2.99"); + expect(headers["x-grok-client-version"]).toBe("1.0.44"); expect(headers["x-grok-session-id"]).toBe("sess-abc"); expect(headers["x-grok-conv-id"]).toBe("sess-abc"); expect(headers["x-grok-req-id"]).toBe("req-xyz"); diff --git a/tests/unit/grok-cli-models.test.js b/tests/unit/grok-cli-models.test.js index 3abd3159..a1673e30 100644 --- a/tests/unit/grok-cli-models.test.js +++ b/tests/unit/grok-cli-models.test.js @@ -75,6 +75,6 @@ describe("Grok CLI live models", () => { expect(fetchFn).toHaveBeenCalledTimes(2); expect(fetchFn.mock.calls[0][2]).toBe(proxyOptions); expect(fetchFn.mock.calls[1][1].headers.Authorization).toBe("Bearer new-token"); - expect(fetchFn.mock.calls[1][1].headers["x-grok-client-version"]).toBe("0.2.99"); + expect(fetchFn.mock.calls[1][1].headers["x-grok-client-version"]).toBe("1.0.44"); }); }); diff --git a/tests/unit/grok-cli-usage.test.js b/tests/unit/grok-cli-usage.test.js index 4017ea03..d4aca719 100644 --- a/tests/unit/grok-cli-usage.test.js +++ b/tests/unit/grok-cli-usage.test.js @@ -272,7 +272,7 @@ describe("getUsageForProvider(grok-cli)", () => { expect(billingCall[0]).toContain("/v1/billing"); expect(billingCall[1].headers.Authorization).toBe("Bearer test-token"); expect(billingCall[1].headers["x-xai-token-auth"]).toBe("xai-grok-cli"); - expect(billingCall[1].headers["x-grok-client-version"]).toBe("0.2.99"); + expect(billingCall[1].headers["x-grok-client-version"]).toBe("1.0.44"); expect(billingCall[1].headers["x-grok-client-identifier"]).toBe("grok-shell"); expect(billingCall[1].headers["x-userid"]).toBe( "d84768dd-224d-4052-ba49-0d336fa9160c",