fix(onboard): align xAI default model to grok-4

This commit is contained in:
George Pickett
2026-02-05 15:04:20 -08:00
parent db31c0ccca
commit 155dfa93e5
7 changed files with 71 additions and 9 deletions

View File

@@ -36,7 +36,7 @@ export async function applyAuthChoiceXAI(
let hasCredential = false; let hasCredential = false;
const optsKey = params.opts?.xaiApiKey?.trim(); const optsKey = params.opts?.xaiApiKey?.trim();
if (optsKey) { if (optsKey) {
await setXaiApiKey(normalizeApiKeyInput(optsKey), params.agentDir); setXaiApiKey(normalizeApiKeyInput(optsKey), params.agentDir);
hasCredential = true; hasCredential = true;
} }
@@ -48,7 +48,7 @@ export async function applyAuthChoiceXAI(
initialValue: true, initialValue: true,
}); });
if (useExisting) { if (useExisting) {
await setXaiApiKey(envKey.apiKey, params.agentDir); setXaiApiKey(envKey.apiKey, params.agentDir);
hasCredential = true; hasCredential = true;
} }
} }
@@ -59,7 +59,7 @@ export async function applyAuthChoiceXAI(
message: "Enter xAI API key", message: "Enter xAI API key",
validate: validateApiKeyInput, validate: validateApiKeyInput,
}); });
await setXaiApiKey(normalizeApiKeyInput(String(key)), params.agentDir); setXaiApiKey(normalizeApiKeyInput(String(key)), params.agentDir);
} }
nextConfig = applyAuthProfileConfig(nextConfig, { nextConfig = applyAuthProfileConfig(nextConfig, {

View File

@@ -237,7 +237,7 @@ describe("applyAuthChoice", () => {
mode: "api_key", mode: "api_key",
}); });
expect(result.config.agents?.defaults?.model?.primary).toBe("openai/gpt-4o-mini"); expect(result.config.agents?.defaults?.model?.primary).toBe("openai/gpt-4o-mini");
expect(result.agentModelOverride).toBe("xai/grok-2-latest"); expect(result.agentModelOverride).toBe("xai/grok-4");
const authProfilePath = authProfilePathFor(requireAgentDir()); const authProfilePath = authProfilePathFor(requireAgentDir());
const raw = await fs.readFile(authProfilePath, "utf8"); const raw = await fs.readFile(authProfilePath, "utf8");

View File

@@ -205,7 +205,7 @@ export async function setOpencodeZenApiKey(key: string, agentDir?: string) {
}); });
} }
export async function setXaiApiKey(key: string, agentDir?: string) { export function setXaiApiKey(key: string, agentDir?: string) {
upsertAuthProfile({ upsertAuthProfile({
profileId: "xai:default", profileId: "xai:default",
credential: { credential: {

View File

@@ -94,7 +94,7 @@ export function buildMoonshotModelDefinition(): ModelDefinitionConfig {
} }
export const XAI_BASE_URL = "https://api.x.ai/v1"; export const XAI_BASE_URL = "https://api.x.ai/v1";
export const XAI_DEFAULT_MODEL_ID = "grok-2-latest"; export const XAI_DEFAULT_MODEL_ID = "grok-4";
export const XAI_DEFAULT_MODEL_REF = `xai/${XAI_DEFAULT_MODEL_ID}`; export const XAI_DEFAULT_MODEL_REF = `xai/${XAI_DEFAULT_MODEL_ID}`;
export const XAI_DEFAULT_CONTEXT_WINDOW = 131072; export const XAI_DEFAULT_CONTEXT_WINDOW = 131072;
export const XAI_DEFAULT_MAX_TOKENS = 8192; export const XAI_DEFAULT_MAX_TOKENS = 8192;
@@ -108,7 +108,7 @@ export const XAI_DEFAULT_COST = {
export function buildXaiModelDefinition(): ModelDefinitionConfig { export function buildXaiModelDefinition(): ModelDefinitionConfig {
return { return {
id: XAI_DEFAULT_MODEL_ID, id: XAI_DEFAULT_MODEL_ID,
name: "Grok 2", name: "Grok 4",
reasoning: false, reasoning: false,
input: ["text"], input: ["text"],
cost: XAI_DEFAULT_COST, cost: XAI_DEFAULT_COST,

View File

@@ -13,11 +13,14 @@ import {
applyOpenrouterProviderConfig, applyOpenrouterProviderConfig,
applySyntheticConfig, applySyntheticConfig,
applySyntheticProviderConfig, applySyntheticProviderConfig,
applyXaiConfig,
applyXaiProviderConfig,
applyXiaomiConfig, applyXiaomiConfig,
applyXiaomiProviderConfig, applyXiaomiProviderConfig,
OPENROUTER_DEFAULT_MODEL_REF, OPENROUTER_DEFAULT_MODEL_REF,
SYNTHETIC_DEFAULT_MODEL_ID, SYNTHETIC_DEFAULT_MODEL_ID,
SYNTHETIC_DEFAULT_MODEL_REF, SYNTHETIC_DEFAULT_MODEL_REF,
XAI_DEFAULT_MODEL_REF,
setMinimaxApiKey, setMinimaxApiKey,
writeOAuthCredentials, writeOAuthCredentials,
} from "./onboard-auth.js"; } from "./onboard-auth.js";
@@ -389,6 +392,65 @@ describe("applyXiaomiConfig", () => {
}); });
}); });
describe("applyXaiConfig", () => {
it("adds xAI provider with correct settings", () => {
const cfg = applyXaiConfig({});
expect(cfg.models?.providers?.xai).toMatchObject({
baseUrl: "https://api.x.ai/v1",
api: "openai-completions",
});
expect(cfg.agents?.defaults?.model?.primary).toBe(XAI_DEFAULT_MODEL_REF);
});
it("preserves existing model fallbacks", () => {
const cfg = applyXaiConfig({
agents: {
defaults: {
model: { fallbacks: ["anthropic/claude-opus-4-5"] },
},
},
});
expect(cfg.agents?.defaults?.model?.fallbacks).toEqual(["anthropic/claude-opus-4-5"]);
});
});
describe("applyXaiProviderConfig", () => {
it("adds model alias", () => {
const cfg = applyXaiProviderConfig({});
expect(cfg.agents?.defaults?.models?.[XAI_DEFAULT_MODEL_REF]?.alias).toBe("Grok");
});
it("merges xAI models and keeps existing provider overrides", () => {
const cfg = applyXaiProviderConfig({
models: {
providers: {
xai: {
baseUrl: "https://old.example.com",
apiKey: "old-key",
api: "anthropic-messages",
models: [
{
id: "custom-model",
name: "Custom",
reasoning: false,
input: ["text"],
cost: { input: 1, output: 2, cacheRead: 0, cacheWrite: 0 },
contextWindow: 1000,
maxTokens: 100,
},
],
},
},
},
});
expect(cfg.models?.providers?.xai?.baseUrl).toBe("https://api.x.ai/v1");
expect(cfg.models?.providers?.xai?.api).toBe("openai-completions");
expect(cfg.models?.providers?.xai?.apiKey).toBe("old-key");
expect(cfg.models?.providers?.xai?.models.map((m) => m.id)).toEqual(["custom-model", "grok-4"]);
});
});
describe("applyOpencodeZenProviderConfig", () => { describe("applyOpencodeZenProviderConfig", () => {
it("adds allowlist entry for the default model", () => { it("adds allowlist entry for the default model", () => {
const cfg = applyOpencodeZenProviderConfig({}); const cfg = applyOpencodeZenProviderConfig({});

View File

@@ -65,7 +65,7 @@ describe("onboard (non-interactive): xAI", () => {
expect(cfg.auth?.profiles?.["xai:default"]?.provider).toBe("xai"); expect(cfg.auth?.profiles?.["xai:default"]?.provider).toBe("xai");
expect(cfg.auth?.profiles?.["xai:default"]?.mode).toBe("api_key"); expect(cfg.auth?.profiles?.["xai:default"]?.mode).toBe("api_key");
expect(cfg.agents?.defaults?.model?.primary).toBe("xai/grok-2-latest"); expect(cfg.agents?.defaults?.model?.primary).toBe("xai/grok-4");
const { ensureAuthProfileStore } = await import("../agents/auth-profiles.js"); const { ensureAuthProfileStore } = await import("../agents/auth-profiles.js");
const store = ensureAuthProfileStore(); const store = ensureAuthProfileStore();

View File

@@ -233,7 +233,7 @@ export async function applyNonInteractiveAuthChoice(params: {
return null; return null;
} }
if (resolved.source !== "profile") { if (resolved.source !== "profile") {
await setXaiApiKey(resolved.key); setXaiApiKey(resolved.key);
} }
nextConfig = applyAuthProfileConfig(nextConfig, { nextConfig = applyAuthProfileConfig(nextConfig, {
profileId: "xai:default", profileId: "xai:default",