feat(catalog): default paid xAI and SuperGrok to grok-4.6

Point xai and xai-oauth at grok-4.6, already in the bundled catalog.
Tests pin the default id in models.json and load picker fixtures from
the catalog so the next bump does not rot hardcoded name or cost.
This commit is contained in:
Yang Yang
2026-08-16 16:29:14 -07:00
parent 37eee71978
commit 848f7fb0fd
8 changed files with 34 additions and 37 deletions
+1 -1
View File
@@ -1566,7 +1566,7 @@ xAI Grok OAuth provides subscription-backed access (SuperGrok / X Premium+) to x
- **Usage Tracking**: `xaiOauthUsageProvider` (`packages/ai/src/usage/xai-oauth.ts`) queries `https://cli-chat-proxy.grok.com/v1/billing` (`validateXAIBillingEndpoint` pins to HTTPS `*.grok.com`) with header `X-XAI-Token-Auth: xai-grok-cli` (`getXAICliBillingHeaders`). Only accepts valid OAuth bearer credentials. Probes legacy weekly credits (`?format=credits`, `parseWeeklyBillingConfig` for `creditUsagePercent` and `productUsage`) and unified monthly quota (`parseMonthlyBillingConfig` for `monthlyLimit` and `used`), plus positive `onDemandCap` / `onDemandUsed` limits.
### Catalog model handling
- **Curated Models & Static Seed**: `XAI_OAUTH_CURATED_MODELS` (`packages/catalog/src/provider-models/openai-compat.ts`) defines static models (`grok-build`, `grok-build-0.1`, `grok-4.3`, `grok-4.5`, `grok-4.20-multi-agent-0309`, `grok-4.20-0309-reasoning`, `grok-4.20-0309-non-reasoning`, `grok-composer-2.5-fast`) with zero cost (`cost: 0`). Default model is `grok-4.3` (`descriptors.ts`). `buildXaiOAuthStaticSeed` seeds `ModelRegistry` synchronously at boot so `modelRoles.default = "xai-oauth/<id>"` works before dynamic refresh.
- **Curated Models & Static Seed**: `XAI_OAUTH_CURATED_MODELS` (`packages/catalog/src/provider-models/openai-compat.ts`) defines static models (`grok-build`, `grok-build-0.1`, `grok-4.3`, `grok-4.5`, `grok-4.6`, `grok-4.20-multi-agent-0309`, `grok-4.20-0309-reasoning`, `grok-4.20-0309-non-reasoning`, `grok-composer-2.5-fast`) with zero cost (`cost: 0`). Default model is `grok-4.6` (`descriptors.ts`). `buildXaiOAuthStaticSeed` seeds `ModelRegistry` synchronously at boot so `modelRoles.default = "xai-oauth/<id>"` works before dynamic refresh.
- **Dynamic Curation Overlay**: `applyXAIOAuthCuration` (`openai-compat.ts`, `xaiOAuthModelManagerOptions`) filters non-chat prefixes (`grok-imagine-`, `grok-stt-`, `grok-voice-`), overlays curated context windows (up to 2M), sets `maxTokens` equal to `contextWindow`, preserves image capabilities and reasoning flags, and injects missing curated models.
- **Reference Resolution Exclusion**: `isZeroCostXaiOAuthCandidate` (`packages/catalog/src/identity/reference.ts`) excludes zero-cost subscription entries from reference index matching so subscription pricing and limits do not override public/paid Grok references.
+3 -3
View File
@@ -2698,7 +2698,7 @@ export class AuthStorage {
/**
* Whether a request could resolve a key for this provider, including
* cross-provider env aliases (`xai-oauth` borrowing `XAI_API_KEY`).
* Use this for explicit model preflight (`xai-oauth/grok-4.5`); use
* Use this for explicit model preflight (`xai-oauth/grok-4.6`); use
* {@link hasAuth} for auto-availability so the default picker stays on
* paid `xai` when only `XAI_API_KEY` is set.
*/
@@ -2732,8 +2732,8 @@ export class AuthStorage {
* `getEnvApiKey("xai-oauth")` also accepts `XAI_API_KEY` so an explicit
* `xai-oauth/…` stream can still borrow the paid key. Availability and
* origin must not: otherwise an API-key-only setup marks SuperGrok as
* signed in and `pickDefaultAvailableModel` prefers `xai-oauth/grok-4.5`
* over paid `xai/grok-4.5`.
* signed in and `pickDefaultAvailableModel` prefers `xai-oauth/grok-4.6`
* over paid `xai/grok-4.6`.
*/
#hasDedicatedEnvAuth(provider: string): boolean {
if (provider === "xai-oauth") {
+5
View File
@@ -2,6 +2,11 @@
## [Unreleased]
### Changed
- Changed the paid xAI (XAI_API_KEY) and SuperGrok (xai-oauth) default models to grok-4.6.
## [17.3.5] - 2026-08-16
### Added
@@ -478,13 +478,13 @@ export const CATALOG_PROVIDERS = [
},
{
id: "xai",
defaultModel: "grok-4.5",
defaultModel: "grok-4.6",
envVars: ["XAI_API_KEY"],
createModelManagerOptions: (config: ModelManagerConfig) => xaiModelManagerOptions(config),
},
{
id: "xai-oauth",
defaultModel: "grok-4.5",
defaultModel: "grok-4.6",
envVars: ["XAI_OAUTH_TOKEN", "XAI_API_KEY"],
createModelManagerOptions: (config: ModelManagerConfig) => xaiOAuthModelManagerOptions(config),
catalogDiscovery: {
@@ -4,7 +4,7 @@ import * as os from "node:os";
import * as path from "node:path";
import { resolveProviderModels } from "@oh-my-pi/pi-catalog/model-manager";
import { getBundledModels } from "@oh-my-pi/pi-catalog/models";
import { CATALOG_PROVIDERS } from "@oh-my-pi/pi-catalog/provider-models/descriptors";
import { CATALOG_PROVIDERS, DEFAULT_MODEL_PER_PROVIDER } from "@oh-my-pi/pi-catalog/provider-models/descriptors";
import { xaiModelManagerOptions } from "@oh-my-pi/pi-catalog/provider-models/openai-compat";
import type { ModelSpec } from "@oh-my-pi/pi-catalog/types";
@@ -37,13 +37,18 @@ describe("paid xai (XAI_API_KEY) Responses contract", () => {
it("registers xai on the catalog Responses discovery path", () => {
const entry = CATALOG_PROVIDERS.find(provider => provider.id === "xai");
expect(entry, "xai catalog descriptor").toBeDefined();
expect(entry!.defaultModel).toBe("grok-4.5");
expect(entry!.defaultModel).toBe("grok-4.6");
expect(DEFAULT_MODEL_PER_PROVIDER.xai).toBe("grok-4.6");
expect(
getBundledModels("xai").find(model => model.id === "grok-4.6"),
"xai/grok-4.6 must be bundled for the default",
).toBeDefined();
expect(entry!.envVars).toContain("XAI_API_KEY");
const options = xaiModelManagerOptions({ apiKey: "test-key" });
expect(options.providerId).toBe("xai");
expect(options.fetchDynamicModels, "live /v1/models overlay").toBeTypeOf("function");
expect(options.dropCachedModelIdsOnStaticMismatch).toEqual(getBundledModels("xai").map(model => model.id));
expect(options.dropCachedModelIdsOnStaticMismatch).toContain("grok-4.5");
expect(options.dropCachedModelIdsOnStaticMismatch).toContain("grok-4.6");
});
it("bundles every paid xai chat model on openai-responses", () => {
@@ -18,11 +18,11 @@ describe("xai-oauth bundled catalog (regression)", () => {
(MODELS_JSON as unknown as Record<string, Record<string, ModelSpec<"openai-responses">>>)["xai-oauth"] ?? {};
const seed = buildXaiOAuthStaticSeed();
it("defaults SuperGrok selection to grok-4.5", () => {
it("defaults SuperGrok selection to grok-4.6", () => {
const entry = CATALOG_PROVIDERS.find(provider => provider.id === "xai-oauth");
expect(entry?.defaultModel).toBe("grok-4.5");
expect(DEFAULT_MODEL_PER_PROVIDER["xai-oauth"]).toBe("grok-4.5");
expect(bundled["grok-4.5"], "xai-oauth/grok-4.5 must be bundled for the default").toBeDefined();
expect(entry?.defaultModel).toBe("grok-4.6");
expect(DEFAULT_MODEL_PER_PROVIDER["xai-oauth"]).toBe("grok-4.6");
expect(bundled["grok-4.6"], "xai-oauth/grok-4.6 must be bundled for the default").toBeDefined();
});
it("bundles every curated id", () => {
+5
View File
@@ -2,6 +2,11 @@
## [Unreleased]
### Changed
- Updated the default model for XAI_API_KEY (xai) and SuperGrok OAuth (xai-oauth) to grok-4.6. Automatic model selection continues to prefer paid xai/grok-4.6 when only XAI_API_KEY is set, with xai-oauth/grok-4.6 still available explicitly.
## [17.3.5] - 2026-08-16
### Added
@@ -1,6 +1,7 @@
import { describe, expect, test } from "bun:test";
import { type Api, Effort, type Model } from "@oh-my-pi/pi-ai";
import { buildModel } from "@oh-my-pi/pi-catalog/build";
import { getBundledModel } from "@oh-my-pi/pi-catalog/models";
import { DEFAULT_MODEL_PER_PROVIDER } from "@oh-my-pi/pi-catalog/provider-models";
import {
expandRoleAlias,
@@ -439,30 +440,11 @@ describe("pickDefaultAvailableModel", () => {
});
test("prefers SuperGrok over paid xAI when both defaults are present", () => {
const paid = buildModel({
id: "grok-4.5",
name: "Grok 4.5",
api: "openai-responses",
provider: "xai",
baseUrl: "https://api.x.ai/v1",
reasoning: true,
input: ["text", "image"],
cost: { input: 2, output: 6, cacheRead: 0.3, cacheWrite: 0 },
contextWindow: 500000,
maxTokens: 500000,
});
const oauth = buildModel({
id: "grok-4.5",
name: "Grok 4.5",
api: "openai-responses",
provider: "xai-oauth",
baseUrl: "https://api.x.ai/v1",
reasoning: true,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 500000,
maxTokens: 500000,
});
const paid = getBundledModel("xai", DEFAULT_MODEL_PER_PROVIDER.xai);
const oauth = getBundledModel("xai-oauth", DEFAULT_MODEL_PER_PROVIDER["xai-oauth"]);
if (!paid || !oauth) {
throw new Error("Expected bundled xAI provider defaults");
}
expect(pickDefaultAvailableModel([paid, oauth])?.provider).toBe("xai-oauth");
expect(pickDefaultAvailableModel([paid])?.provider).toBe("xai");