Files
oh-my-pi/packages/catalog/test/xai-oauth-bundle.test.ts
Yang Yang 848f7fb0fd 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.
2026-08-16 16:29:14 -07:00

87 lines
4.7 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import MODELS_JSON from "@oh-my-pi/pi-catalog/models.json" with { type: "json" };
import { CATALOG_PROVIDERS, DEFAULT_MODEL_PER_PROVIDER } from "@oh-my-pi/pi-catalog/provider-models/descriptors";
import { buildXaiOAuthStaticSeed } from "@oh-my-pi/pi-catalog/provider-models/openai-compat";
import type { ModelSpec } from "@oh-my-pi/pi-catalog/types";
// Pins the invariant: bundled `models.json` carries every entry the runtime
// curated catalog (XAI_OAUTH_CURATED_MODELS, surfaced via
// buildXaiOAuthStaticSeed) emits. Without this, editing the curated list
// without regenerating `models.json` silently regresses the boot-time
// default-model resolver — the registry sees the runtime seed only after
// `refresh()`, but interactive boot resolves the persisted default
// synchronously from `#loadModels()`, which reads only `models.json`.
//
// Failure here means: run `bun run gen:models` and commit the diff.
describe("xai-oauth bundled catalog (regression)", () => {
const bundled =
(MODELS_JSON as unknown as Record<string, Record<string, ModelSpec<"openai-responses">>>)["xai-oauth"] ?? {};
const seed = buildXaiOAuthStaticSeed();
it("defaults SuperGrok selection to grok-4.6", () => {
const entry = CATALOG_PROVIDERS.find(provider => provider.id === "xai-oauth");
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", () => {
const seededIds = seed.map(model => model.id).sort();
const bundledIds = Object.keys(bundled).sort();
expect(bundledIds).toEqual(seededIds);
});
for (const seededModel of seed) {
it(`matches contract for ${seededModel.id}`, () => {
const bundledEntry = bundled[seededModel.id];
expect(bundledEntry, `xai-oauth/${seededModel.id} missing from models.json`).toBeDefined();
expect(bundledEntry.id).toBe(seededModel.id);
expect(bundledEntry.name).toBe(seededModel.name);
expect(bundledEntry.provider).toBe("xai-oauth");
expect(bundledEntry.api).toBe("openai-responses");
expect(bundledEntry.contextWindow).toBe(seededModel.contextWindow);
expect(bundledEntry.reasoning).toBe(seededModel.reasoning);
// Input modality must survive both the curated seed and the bundle.
// Without this the static fallback used on offline boot strips
// vision capability silently (Codex PR #1127 review).
expect(bundledEntry.input).toEqual(seededModel.input);
expect(bundledEntry.compat?.supportsReasoningEffort).toBe(seededModel.compat?.supportsReasoningEffort);
});
}
// Absolute contract for the user-specified SuperGrok addition. The parity
// loop above can't catch a value typo (e.g. 2_000_000) or a flipped
// reasoning flag — both sides regenerate from the same seed together — so
// pin the literal attributes here.
it("exposes grok-composer-2.5-fast as a non-reasoning 200K text model", () => {
const composer = seed.find(model => model.id === "grok-composer-2.5-fast");
expect(composer, "grok-composer-2.5-fast must be in the SuperGrok curated seed").toBeDefined();
expect(composer!.reasoning).toBe(false);
expect(composer!.contextWindow).toBe(200_000);
expect(composer!.input).toEqual(["text"]);
// The bundled models.json entry is byte-identical to the generator's
// deterministic xai-oauth output: gen:models pushes
// buildXaiOAuthStaticSeed() (offline — xai-oauth has no upstream catalog
// source) and applyGeneratedModelPolicies(), so a regen reproduces these
// exact bytes; only unrelated other-provider network churn was excluded
// to keep the diff scoped. Pin its zero-cost invariant (overlay-stable
// for the SuperGrok subscription), which the parity loop above never
// compares. (maxTokens is pinned by the maxTokens-equals-contextWindow
// test below.)
expect(bundled["grok-composer-2.5-fast"]?.cost).toEqual({ input: 0, output: 0, cacheRead: 0, cacheWrite: 0 });
});
// The OAuth surface's /v1/models reports no per-request output limit, so the
// curated catalog owns maxTokens — set to mirror each model's contextWindow
// (the openai-responses wire still clamps the actual request to
// OPENAI_MAX_OUTPUT_TOKENS). Pin maxTokens === contextWindow on both the
// static-seed and bundled paths so a null placeholder can
// never silently leak back into the bundle.
it("sets maxTokens equal to contextWindow for every xai-oauth model", () => {
for (const model of seed) {
expect(model.maxTokens, `seed ${model.id} maxTokens`).toBe(model.contextWindow);
expect(bundled[model.id]?.maxTokens, `bundled ${model.id} maxTokens`).toBe(model.contextWindow);
}
});
});