fix(frontend): address Codex config review feedback

This commit is contained in:
haruka
2026-07-14 18:31:06 +08:00
parent e2028a814e
commit f09d63f54e
6 changed files with 44 additions and 75 deletions
+20 -19
View File
@@ -563,35 +563,29 @@ name = "OpenAI"
base_url = "${baseUrl}"
wire_api = "responses"
requires_openai_auth = false
env_key = "SUB2API_API_KEY"
http_headers = { "x-openai-actor-authorization" = "local-image-extension" }
[features]
image_generation = true
goals = true`
// auth.json content
const authContent = `{
"OPENAI_API_KEY": "${apiKey}"
}`
return [
{
path: `${configDir}/config.toml`,
content: configContent,
hint: t('keys.useKeyModal.openai.configTomlHint')
},
generateCodexAPIKeyEnvironment(apiKey, isWindows)
{
path: `${configDir}/auth.json`,
content: authContent
}
]
}
function generateCodexAPIKeyEnvironment(apiKey: string, isWindows: boolean): FileConfig {
return isWindows
? {
path: 'PowerShell',
content: `$env:SUB2API_API_KEY="${apiKey}"`
}
: {
path: 'Terminal',
content: `export SUB2API_API_KEY="${apiKey}"`
}
}
function generateGrokFiles(baseUrl: string, apiKey: string): FileConfig[] {
const isWindows = activeTab.value === 'windows'
const configDir = isWindows ? '%userprofile%\\.grok' : '~/.grok'
@@ -620,7 +614,7 @@ function generateOpenAIWsFiles(baseUrl: string, apiKey: string): FileConfig[] {
const isWindows = activeTab.value === 'windows'
const configDir = isWindows ? '%userprofile%\\.codex' : '~/.codex'
// config.toml content with the Responses WebSocket transport enabled
// config.toml content with WebSocket v2
const configContent = `model_provider = "OpenAI"
model = "gpt-5.5"
review_model = "gpt-5.5"
@@ -635,20 +629,27 @@ base_url = "${baseUrl}"
wire_api = "responses"
supports_websockets = true
requires_openai_auth = false
env_key = "SUB2API_API_KEY"
http_headers = { "x-openai-actor-authorization" = "local-image-extension" }
[features]
image_generation = true
responses_websockets_v2 = true
goals = true`
// auth.json content
const authContent = `{
"OPENAI_API_KEY": "${apiKey}"
}`
return [
{
path: `${configDir}/config.toml`,
content: configContent,
hint: t('keys.useKeyModal.openai.configTomlHint')
},
generateCodexAPIKeyEnvironment(apiKey, isWindows)
{
path: `${configDir}/auth.json`,
content: authContent
}
]
}
@@ -78,7 +78,7 @@ describe('UseKeyModal', () => {
expect(parsed.provider.grok.models['gpt-5.6']).toBeUndefined()
})
it('renders API key mode and local image generation in OpenAI Codex config', () => {
it('renders minimal image executor authorization in OpenAI Codex config', () => {
const wrapper = mount(UseKeyModal, {
props: {
show: true,
@@ -108,16 +108,17 @@ describe('UseKeyModal', () => {
expect(configToml).not.toContain('model_context_window')
expect(configToml).not.toContain('model_auto_compact_token_limit')
expect(configToml).toContain('requires_openai_auth = false')
expect(configToml).toContain('env_key = "SUB2API_API_KEY"')
expect(configToml).toContain('http_headers = { "x-openai-actor-authorization" = "local-image-extension" }')
expect(configToml).not.toContain('env_key')
expect(configToml).not.toContain('image_generation')
expect(configToml).not.toContain('supports_websockets')
expect(configToml).not.toContain('responses_websockets_v2')
expect(configToml).toContain('[features]\nimage_generation = true\ngoals = true')
expect(codeBlocks).toContain('export SUB2API_API_KEY="sk-test"')
expect(wrapper.text()).not.toContain('auth.json')
expect(configToml).toContain('[features]\ngoals = true')
expect(codeBlocks).toContain('{\n "OPENAI_API_KEY": "sk-test"\n}')
expect(wrapper.text()).toContain('auth.json')
})
it('renders API key mode and current WebSocket settings in OpenAI Codex config', async () => {
it('renders minimal image executor authorization in OpenAI Codex WebSocket config', async () => {
const wrapper = mount(UseKeyModal, {
props: {
show: true,
@@ -155,46 +156,13 @@ describe('UseKeyModal', () => {
expect(configToml).not.toContain('model_context_window')
expect(configToml).not.toContain('model_auto_compact_token_limit')
expect(configToml).toContain('requires_openai_auth = false')
expect(configToml).toContain('env_key = "SUB2API_API_KEY"')
expect(configToml).toContain('http_headers = { "x-openai-actor-authorization" = "local-image-extension" }')
expect(configToml).not.toContain('env_key')
expect(configToml).not.toContain('image_generation')
expect(configToml).toContain('supports_websockets = true')
expect(configToml).not.toContain('responses_websockets_v2')
expect(configToml).toContain('[features]\nimage_generation = true\ngoals = true')
expect(codeBlocks).toContain('export SUB2API_API_KEY="sk-test"')
expect(wrapper.text()).not.toContain('auth.json')
})
it('renders a PowerShell API key command for Codex on Windows', async () => {
const wrapper = mount(UseKeyModal, {
props: {
show: true,
apiKey: 'sk-test',
baseUrl: 'https://example.com/v1',
platform: 'openai'
},
global: {
stubs: {
BaseDialog: {
template: '<div><slot /><slot name="footer" /></div>'
},
Icon: {
template: '<span />'
}
}
}
})
const windowsTab = wrapper.findAll('button').find(
(button) => button.text().trim() === 'Windows'
)
expect(windowsTab).toBeDefined()
await windowsTab!.trigger('click')
await nextTick()
const codeBlocks = wrapper.findAll('pre code').map((code) => code.text())
expect(codeBlocks).toContain('$env:SUB2API_API_KEY="sk-test"')
expect(wrapper.text()).not.toContain('auth.json')
expect(configToml).toContain('[features]\nresponses_websockets_v2 = true\ngoals = true')
expect(codeBlocks).toContain('{\n "OPENAI_API_KEY": "sk-test"\n}')
expect(wrapper.text()).toContain('auth.json')
})
it('renders GPT-5.4 mini entry in OpenCode config', async () => {
@@ -155,7 +155,7 @@ export default {
webSearchEmulationHint: '⚠️ When enabled, all accounts in this channel\'s Anthropic groups will intercept web_search requests. Use with caution.',
webSearchEmulationGlobalDisabled: 'Please enable the global switch first in Settings → Gateway → Web Search Emulation',
codexImageGenerationBridge: 'Codex Image Generation Bridge',
codexImageGenerationBridgeHint: 'Hosted image bridge for non-Responses Lite requests only. It may inject the image_generation tool into Codex /responses text requests; Responses Lite uses the client-side image executor instead.',
codexImageGenerationBridgeHint: 'When enabled, Codex /responses text requests in OpenAI groups may be automatically given the image_generation tool. Keep off unless the routed accounts support image generation.',
bedrockCCCompat: 'Bedrock CC Compatibility',
bedrockCCCompatHint: '⚠️ When enabled, requests to Bedrock accounts in this channel will be transformed for Claude Code compatibility (thinking type conversion, tool_use ID sanitization).',
basicSettings: 'Basic Settings',
+5 -5
View File
@@ -136,16 +136,16 @@ export default {
noGroupTitle: 'Please assign a group first',
noGroupDescription: 'This API key has not been assigned to a group. Please click the group column in the key list to assign one before viewing the configuration.',
openai: {
description: 'Set SUB2API_API_KEY before starting Codex, then add the config.toml settings below. Responses Lite image generation uses Codex\'s local image executor; hosted force injection applies only to non-Responses Lite requests.',
description: 'Add the following configuration files to your Codex CLI config directory.',
configTomlHint: 'Make sure the following content is at the beginning of the config.toml file',
note: 'Make sure ~/.codex exists, set the environment variable before Codex/Desktop starts, then fully restart the client and create a new thread so the image tool is registered.',
noteWindows: 'Make sure %userprofile%\\.codex exists, set the environment variable before Codex/Desktop starts, then fully restart the client and create a new thread so the image tool is registered.',
note: 'Make sure the config directory exists. macOS/Linux users can run mkdir -p ~/.codex to create it.',
noteWindows: 'Press Win+R and enter %userprofile%\\.codex to open the config directory. Create it manually if it does not exist.',
},
cliTabs: {
claudeCode: 'Claude Code',
geminiCli: 'Gemini CLI',
codexCli: 'Codex (API Key Mode)',
codexCliWs: 'Codex (API Key Mode, WebSocket)',
codexCli: 'Codex CLI',
codexCliWs: 'Codex CLI (WebSocket)',
grokCli: 'Grok CLI',
opencode: 'OpenCode',
},
@@ -155,7 +155,7 @@ export default {
webSearchEmulationHint: '⚠️ 开启后该渠道下所有 Anthropic 分组的账号将自动拦截 web_search 请求,请谨慎操作',
webSearchEmulationGlobalDisabled: '请先在系统设置 → 网关 → Web Search 模拟中启用全局开关',
codexImageGenerationBridge: 'Codex 图片生成桥接',
codexImageGenerationBridgeHint: '仅用于非 Responses Lite 请求的服务端图片桥接,可向 Codex /responses 文本请求注入 image_generation 工具;Responses Lite 改用客户端图片执行器。',
codexImageGenerationBridgeHint: '开启后,OpenAI 分组的 Codex /responses 文本请求可能会被自动注入 image_generation 工具。仅在路由账号支持图片生成时开启。',
bedrockCCCompat: 'Bedrock CC 兼容',
bedrockCCCompatHint: '⚠️ 开启后,该渠道下 Bedrock 账号的请求将进行 Claude Code 兼容处理(thinking 类型转换、tool_use ID 清理)',
basicSettings: '基础设置',
+5 -5
View File
@@ -136,17 +136,17 @@ export default {
noGroupDescription:
'此 API 密钥尚未分配分组,请先在密钥列表中点击分组列进行分配,然后才能查看使用配置。',
openai: {
description: '启动 Codex 前先设置 SUB2API_API_KEY,再添加以下 config.toml 配置。Responses Lite 生图使用 Codex 本地图片执行器;服务端强制注入仅用于非 Responses Lite 请求。',
description: '将以下配置文件添加到 Codex CLI 配置目录中。',
configTomlHint: '请确保以下内容位于 config.toml 文件的开头部分',
note: '请确保 ~/.codex 目录存在,并在 Codex/Desktop 启动前设置环境变量;随后完全重启客户端并新建会话,以重新注册图片工具。',
note: '请确保配置目录存在。macOS/Linux 用户可运行 mkdir -p ~/.codex 创建目录。',
noteWindows:
'请确保 %userprofile%\\.codex 目录存在,并在 Codex/Desktop 启动前设置环境变量;随后完全重启客户端并新建会话,以重新注册图片工具。'
'按 Win+R,输入 %userprofile%\\.codex 打开配置目录。如目录不存在,请先手动创建。'
},
cliTabs: {
claudeCode: 'Claude Code',
geminiCli: 'Gemini CLI',
codexCli: 'Codex(API Key 模式)',
codexCliWs: 'Codex(API Key 模式,WebSocket)',
codexCli: 'Codex CLI',
codexCliWs: 'Codex CLI (WebSocket)',
grokCli: 'Grok CLI',
opencode: 'OpenCode'
},