mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-24 16:05:44 +08:00
fix(frontend): address Codex config review feedback
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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: '基础设置',
|
||||
|
||||
@@ -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'
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user