mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-30 00:21:34 +00:00
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:
@@ -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'
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user