From b717ed9d0d1fc28eddc0a1327856de36f24efcb9 Mon Sep 17 00:00:00 2001 From: IanShaw027 Date: Sat, 8 Aug 2026 10:33:45 +0800 Subject: [PATCH] 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. --- frontend/src/components/keys/UseKeyModal.vue | 49 ++++++++++++++----- .../keys/__tests__/UseKeyModal.spec.ts | 25 +++++++--- frontend/src/i18n/locales/en/dashboard.ts | 8 +-- frontend/src/i18n/locales/zh/dashboard.ts | 8 +-- 4 files changed, 63 insertions(+), 27 deletions(-) diff --git a/frontend/src/components/keys/UseKeyModal.vue b/frontend/src/components/keys/UseKeyModal.vue index d90b13b7c8..35c30a72cb 100644 --- a/frontend/src/components/keys/UseKeyModal.vue +++ b/frontend/src/components/keys/UseKeyModal.vue @@ -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 }, diff --git a/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts b/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts index 197ecbcfd0..a933585104 100644 --- a/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts +++ b/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts @@ -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' diff --git a/frontend/src/i18n/locales/en/dashboard.ts b/frontend/src/i18n/locales/en/dashboard.ts index df2610110a..a63fdbdc8b 100644 --- a/frontend/src/i18n/locales/en/dashboard.ts +++ b/frontend/src/i18n/locales/en/dashboard.ts @@ -174,13 +174,13 @@ export default { claudeDescription: 'Configure Claude Code to send Messages API traffic through your Sub2API Grok group.', codexDescription: 'Configure Codex to send Responses API traffic through your Sub2API Grok group.', configTomlHint: - 'Official path: ~/.grok/config.toml (or $GROK_HOME). Prefer env_key = "XAI_API_KEY" over api_key. Every model must set api_backend = "responses" for Sub2API. Back up before merge, then run grok inspect.', + 'Official path: ~/.grok/config.toml (or $GROK_HOME). Fill [endpoints] (models_base_url / models_list_url / xai_api_base_url / cli_chat_proxy_base_url), [auth] preferred_method=api_key, [models], [session], and [features] image/video overrides. Prefer env_key over api_key; every text model needs api_backend=responses. Back up before merge, then run grok inspect.', codexConfigTomlHint: - 'Official Codex: wire_api = "responses" only; prefer env_key over experimental_bearer_token; supports_websockets = false for non-OpenAI gateways. Back up ~/.codex/config.toml before merge.', + 'Official Codex: wire_api = "responses" only; prefer env_key over experimental_bearer_token; supports_websockets = false for non-OpenAI gateways (Sub2API can still accept client WS and bridge to HTTP/SSE). Back up ~/.codex/config.toml before merge.', note: - 'Export GROK_MODELS_BASE_URL and XAI_API_KEY, save config.toml as ~/.grok/config.toml, run grok inspect, then /model grok-4.5 (or grok-build-0.1 for coding).', + 'Export GROK_MODELS_BASE_URL and XAI_API_KEY, save the full config.toml (endpoints/auth/models/session/features) as ~/.grok/config.toml, run grok inspect, then /model grok-4.5 (or grok-build-0.1 for coding).', noteWindows: - 'Set GROK_MODELS_BASE_URL and XAI_API_KEY, save config.toml as %USERPROFILE%\\.grok\\config.toml, run grok inspect, then /model grok-4.5 (or grok-build-0.1 for coding).', + 'Set GROK_MODELS_BASE_URL and XAI_API_KEY, save the full config.toml as %USERPROFILE%\\.grok\\config.toml, run grok inspect, then /model grok-4.5 (or grok-build-0.1 for coding).', claudeNote: 'Choose one method: terminal env for this session, or ~/.claude/settings.json for persistence. Do not commit files that contain your API key.', codexNote: diff --git a/frontend/src/i18n/locales/zh/dashboard.ts b/frontend/src/i18n/locales/zh/dashboard.ts index 540c878889..7be49c3257 100644 --- a/frontend/src/i18n/locales/zh/dashboard.ts +++ b/frontend/src/i18n/locales/zh/dashboard.ts @@ -178,13 +178,13 @@ export default { claudeDescription: '配置 Claude Code,让 Messages API 请求通过当前 Sub2API Grok 分组发送。', codexDescription: '配置 Codex,让 Responses API 请求通过当前 Sub2API Grok 分组发送。', configTomlHint: - '官方路径:~/.grok/config.toml(或 $GROK_HOME)。优先 env_key = "XAI_API_KEY",勿硬编码 api_key。Sub2API 上每个模型必须 api_backend = "responses"。合并前请备份,保存后运行 grok inspect。', + '官方路径:~/.grok/config.toml(或 $GROK_HOME)。请填写 [endpoints](models_base_url / models_list_url / xai_api_base_url / cli_chat_proxy_base_url)、[auth] preferred_method=api_key、[models]、[session]、[features] 图片/视频覆盖。优先 env_key,勿硬编码 api_key;文本模型必须 api_backend=responses。合并前备份,保存后运行 grok inspect。', codexConfigTomlHint: - 'Codex 官方:wire_api 仅支持 "responses";优先 env_key,勿与 experimental_bearer_token 混用;非 OpenAI 网关请 supports_websockets = false。合并前备份 ~/.codex/config.toml。', + 'Codex 官方:wire_api 仅支持 "responses";优先 env_key,勿与 experimental_bearer_token 混用;非 OpenAI 网关默认 supports_websockets = false(Sub2API 仍可接客户端 WS 并桥接到 HTTP/SSE)。合并前备份 ~/.codex/config.toml。', note: - '导出 GROK_MODELS_BASE_URL 与 XAI_API_KEY,将 config.toml 保存为 ~/.grok/config.toml,运行 grok inspect,再用 /model 选择 grok-4.5(编程场景可用 grok-build-0.1)。', + '导出 GROK_MODELS_BASE_URL 与 XAI_API_KEY,将完整 config.toml(endpoints/auth/models/session/features)保存为 ~/.grok/config.toml,运行 grok inspect,再用 /model 选择 grok-4.5(编程场景可用 grok-build-0.1)。', noteWindows: - '设置 GROK_MODELS_BASE_URL 与 XAI_API_KEY,将 config.toml 保存为 %USERPROFILE%\\.grok\\config.toml,运行 grok inspect,再用 /model 选择 grok-4.5(编程场景可用 grok-build-0.1)。', + '设置 GROK_MODELS_BASE_URL 与 XAI_API_KEY,将完整 config.toml 保存为 %USERPROFILE%\\.grok\\config.toml,运行 grok inspect,再用 /model 选择 grok-4.5(编程场景可用 grok-build-0.1)。', claudeNote: '二选一:终端环境变量仅当前会话;~/.claude/settings.json 可持久化。请勿把含 API Key 的文件提交到仓库。', codexNote: