feat(keys): complete Grok Build sample with endpoints/auth/session/features

Expand Use Key Grok CLI config.toml to include production-oriented sections
from working gateway setups: full [endpoints], preferred_method=api_key,
image_description, auto_compact threshold, and Imagine image/video feature
overrides with guided comments.
This commit is contained in:
IanShaw027
2026-08-08 10:33:45 +08:00
parent f3bac4619e
commit b717ed9d0d
4 changed files with 63 additions and 27 deletions
+36 -13
View File
@@ -790,27 +790,34 @@ $env:XAI_API_KEY="${apiKey}"`
export XAI_API_KEY="${apiKey}"`
}
// Shape follows official Grok Build docs (docs.x.ai/build/settings + custom-models guide).
// Text models only (Responses). Image/video: grok-imagine-image / grok-imagine-video on media endpoints.
// Shape follows Grok Build user guide (~/.grok/docs + custom-models) and production-ready Sub2API setups.
// Text models only (Responses). Image/video: Imagine model IDs on media endpoints / feature overrides.
// Credential order: api_key field → env_key → signed-in session → XAI_API_KEY global fallback.
const modelsListUrl = `${baseUrl.replace(/\/+$/, '')}/models`
const configContent = `# Grok Build CLI → Sub2API Grok group (API key auth).
# Official docs: https://docs.x.ai/build/settings
# Docs: ~/.grok/docs/user-guide/05-configuration.md + 11-custom-models.md
# Verify after save: grok inspect
#
# Text / agent models only. Image & video use separate Imagine model IDs on media endpoints
# (e.g. grok-imagine-image, grok-imagine-video) — not the catalog below.
#
# IMPORTANT: api_backend must be "responses" for Sub2API Grok (POST /v1/responses).
# If omitted, Grok Build defaults to chat_completions (/v1/chat/completions).
# Global inference base (same role as env GROK_MODELS_BASE_URL).
# Grok also lists models from {models_base_url}/models when this is set.
[endpoints]
models_base_url = "${baseUrl}"
# Keep api_backend = "responses" on every model entry.
#
# Prefer env_key over hardcoding api_key (never commit secrets).
# Also export GROK_MODELS_BASE_URL + XAI_API_KEY in the shell block above.
# Global inference / catalog endpoints (same role as env GROK_MODELS_BASE_URL).
# When models_base_url is set, Grok uses API-key Bearer auth (no grok login required).
[endpoints]
models_base_url = "${baseUrl}" # inference base; model list defaults to {base}/models
models_list_url = "${modelsListUrl}" # optional override (env: GROK_MODELS_LIST_URL)
xai_api_base_url = "${baseUrl}" # public xAI API base override for gateway routing
cli_chat_proxy_base_url = "${baseUrl}" # CLI chat-proxy base (env: GROK_CLI_CHAT_PROXY_BASE_URL)
# Prefer API key when using a custom gateway (matches Sub2API).
# Requires XAI_API_KEY env or per-model env_key / api_key.
[auth]
preferred_method = "api_key"
[model."grok-4.5"]
model = "grok-4.5" # id sent to the API
name = "Grok 4.5" # shown in /model picker
@@ -867,11 +874,27 @@ supports_backend_search = true
# xAI recommends grok-build* for coding/agent sessions; use grok-4.5 for general chat.
default = "grok-4.5"
web_search = "grok-4.5" # client-side web_search tool model (must exist as [model.*])
image_description = "grok-4.5" # vision/describe-image helper model
# Optional environment-wide sampling defaults (per-model values win):
# temperature = 0.7
# top_p = 0.95
# max_completion_tokens = 8192
# max_retries = 8`
# max_retries = 8
[session]
auto_compact_threshold_percent = 80 # auto-compact at this % of context_window (default 85)
# Imagine tools: model IDs go to Sub2API media endpoints (not the text [model.*] catalog).
# Enable only if the Grok group allows image/video generation.
[features]
image_gen = true
video_gen = true
image_gen_model_override = "grok-imagine-image-quality" # or grok-imagine-image
image_edit_model_override = "grok-imagine-edit"
# Optional feature flags (defaults shown in docs):
# telemetry = false
# remote_fetch = true # set false for air-gapped / pure-gateway catalogs
# lsp_tools = false`
return [
{ path: envPath, content: envContent },
@@ -55,11 +55,20 @@ describe('UseKeyModal', () => {
expect(allCode).toContain('[model."grok-4.3"]')
expect(allCode).toContain('default = "grok-4.5"')
expect(allCode).toContain('models_base_url = "https://example.com/v1"')
expect(allCode).toContain('models_list_url = "https://example.com/v1/models"')
expect(allCode).toContain('xai_api_base_url = "https://example.com/v1"')
expect(allCode).toContain('cli_chat_proxy_base_url = "https://example.com/v1"')
expect(allCode).toContain('preferred_method = "api_key"')
expect(allCode).toContain('image_description = "grok-4.5"')
expect(allCode).toContain('auto_compact_threshold_percent = 80')
expect(allCode).toContain('image_gen = true')
expect(allCode).toContain('video_gen = true')
expect(allCode).toContain('image_gen_model_override = "grok-imagine-image-quality"')
expect(allCode).toContain('image_edit_model_override = "grok-imagine-edit"')
expect(allCode).toContain('env_key = "XAI_API_KEY"')
expect(allCode).toContain('Keep api_backend = "responses" on every model entry.')
expect(allCode).toContain('NOT for image/video generation')
expect(allCode).toContain('grok-imagine-image')
expect(allCode).toContain('grok-imagine-video')
expect(allCode).toContain('grok-imagine-edit')
expect(allCode).toMatch(/\[model\."grok-4\.5"\][\s\S]*?context_window = 500000/)
expect(allCode).toMatch(/\[model\."grok-build-0\.1"\][\s\S]*?context_window = 256000/)
// Prefer env_key; hardcode api_key only as commented alternative
@@ -97,7 +106,7 @@ describe('UseKeyModal', () => {
apiKey: 'sk-grok-test'
})
expect(parsed.provider.grok.models['grok-4.5']).toBeDefined()
expect(parsed.provider.grok.models['grok-4.5'].limit.context).toBe(500000)
expect(parsed.provider.grok.models['grok-4.5'].limit.context).toBe(1000000)
expect(parsed.provider.grok.models['grok-build-0.1']).toBeDefined()
expect(parsed.provider.grok.models['grok-4.20-multi-agent-0309']).toBeDefined()
expect(parsed.provider.grok.models['grok-composer-2.5-fast']).toBeDefined()
@@ -227,16 +236,20 @@ describe('UseKeyModal', () => {
expect(configToml).toContain('model_provider = "sub2api"')
expect(configToml).toContain('model = "grok-4.5"')
expect(configToml).toContain('base_url = "https://example.com/v1"')
expect(configToml).toContain('experimental_bearer_token = "sk-grok-codex-test"')
expect(configToml).toContain('env_key = "SUB2API_API_KEY"')
expect(configToml).toContain('wire_api = "responses"')
expect(configToml).toContain('requires_openai_auth = true')
// API-key provider: Codex must not require a ChatGPT OAuth login.
expect(configToml).toContain('requires_openai_auth = false')
expect(configToml).toContain('supports_websockets = false')
expect(configToml).toContain('multi-agent / web_search')
expect(configToml).toContain('grok-4.20-multi-agent-0309 (text / web_search)')
expect(configToml).toContain('grok-imagine-image')
expect(configToml).toContain('grok-imagine-video')
// Hardcoded bearer is only a commented fallback when env cannot be set.
expect(configToml).toMatch(/# experimental_bearer_token = "sk-grok-codex-test"/)
expect(configToml).not.toContain('supports_websockets = true')
expect(configToml).not.toContain('responses_websockets_v2')
expect(wrapper.text()).not.toContain('auth.json')
expect(codeBlocks.join('\n')).toContain('SUB2API_API_KEY')
const windowsTab = wrapper.findAll('button').find(
(button) => button.text().trim() === 'Windows'