diff --git a/frontend/src/components/account/EditAccountModal.vue b/frontend/src/components/account/EditAccountModal.vue index eed9920bb2..0bbe2fd937 100644 --- a/frontend/src/components/account/EditAccountModal.vue +++ b/frontend/src/components/account/EditAccountModal.vue @@ -1455,7 +1455,7 @@ - +
{ const wrapper = mountModal(account) + expect(wrapper.text()).toContain('admin.accounts.openai.codexImageTool') + expect(wrapper.text()).toContain('admin.accounts.openai.codexImageToolDesc') + expect(wrapper.text()).toContain('admin.accounts.openai.codexImageToolEnabledDesc') + await wrapper.get('button[data-testid="codex-image-tool-enabled"]').trigger('click') await wrapper.get('form#edit-account-form').trigger('submit.prevent') @@ -809,6 +813,9 @@ describe('EditAccountModal', () => { const wrapper = mountModal(account) + expect(wrapper.text()).toContain('admin.accounts.openai.codexImageToolBlock') + expect(wrapper.text()).toContain('admin.accounts.openai.codexImageToolBlockDesc') + await wrapper.get('button[data-testid="codex-image-tool-block"]').trigger('click') await wrapper.get('form#edit-account-form').trigger('submit.prevent') diff --git a/frontend/src/components/keys/UseKeyModal.vue b/frontend/src/components/keys/UseKeyModal.vue index 4663b2b7d8..9d99f703b4 100644 --- a/frontend/src/components/keys/UseKeyModal.vue +++ b/frontend/src/components/keys/UseKeyModal.vue @@ -100,6 +100,14 @@ {{ t('keys.useKeyModal.openai.authModeApiKey') }}
+
+ +

{{ t('keys.useKeyModal.openai.authModeApiKeyRestartNotice') }}

+
diff --git a/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts b/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts index 6db8505489..99c09f1acd 100644 --- a/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts +++ b/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts @@ -267,6 +267,7 @@ describe('UseKeyModal', () => { expect(configToml).toContain('[features]\ngoals = true') expect(codeBlocks).toContain('{\n "OPENAI_API_KEY": "sk-test"\n}') expect(wrapper.text()).toContain('auth.json') + expect(wrapper.find('[data-testid="codex-api-key-restart-notice"]').exists()).toBe(false) }) it('renders API Key Mode authorization in OpenAI Codex config', async () => { @@ -304,6 +305,19 @@ describe('UseKeyModal', () => { expect(configToml).not.toContain('image_generation') expect(codeBlocks).toContain('{\n "OPENAI_API_KEY": "sk-test"\n}') expect(wrapper.text()).toContain('auth.json') + + const restartNotice = wrapper.get('[data-testid="codex-api-key-restart-notice"]') + expect(restartNotice.text()).toContain( + 'keys.useKeyModal.openai.authModeApiKeyRestartNotice' + ) + + await wrapper.get('[data-testid="codex-auth-mode-legacy"]').trigger('click') + await nextTick() + + expect(wrapper.find('[data-testid="codex-api-key-restart-notice"]').exists()).toBe(false) + expect(wrapper.findAll('pre code').map((code) => code.text()).join('\n')).not.toContain( + 'x-openai-actor-authorization' + ) }) it('keeps legacy OpenAI Codex WebSocket config as the default', async () => { diff --git a/frontend/src/i18n/locales/en/admin/accounts.ts b/frontend/src/i18n/locales/en/admin/accounts.ts index b7ea0244d8..ee7acfe247 100644 --- a/frontend/src/i18n/locales/en/admin/accounts.ts +++ b/frontend/src/i18n/locales/en/admin/accounts.ts @@ -489,21 +489,21 @@ export default { codexCLIOnlyAppServer: 'Allow Codex app-server clients', codexCLIOnlyAppServerDesc: "Effective only when the switch above is on. When enabled, this account also allows third-party clients that embed the Codex engine over the app-server protocol (e.g. Claude Code's codex plugin); they still pass the global engine-fingerprint gate. OR-combined with the global app-server toggle.", - codexImageTool: 'Codex image tool', + codexImageTool: 'Codex image bridge policy', codexImageToolDesc: - 'One policy for the image_generation tool on Codex /responses text requests: whether it is auto-injected, and whether client-provided tools pass through. Account policy takes precedence over channel and global settings; standalone image-generation endpoints are unaffected.', + 'Controls the hosted image_generation bridge and client-declared image tools on Codex /responses text requests. Hosted auto-injection applies only to non-Responses Lite requests. Account policy takes precedence over channel and global settings; standalone image-generation endpoints are unaffected.', codexImageToolInherit: 'Follow channel', - codexImageToolInheritDesc: 'No account override; injection follows the channel or global policy, and client-provided image tools pass through.', - codexImageToolEnabled: 'Force inject', - codexImageToolEnabledDesc: 'Always inject the image tool for Codex /responses requests.', - codexImageToolDisabled: 'No injection', - codexImageToolDisabledDesc: 'Never auto-inject; client-provided image tools still pass through.', - codexImageToolBlock: 'Block all', - codexImageToolBlockDesc: 'No injection, and client-provided image tools plus matching tool_choice are removed.', + codexImageToolInheritDesc: 'No account override; hosted injection for non-Lite requests follows the channel or global policy, while client-provided hosted tools and local image_gen declarations pass through.', + codexImageToolEnabled: 'Enable hosted bridge', + codexImageToolEnabledDesc: 'Inject the hosted image_generation tool only for non-Responses Lite requests; client-provided image tools still pass through.', + codexImageToolDisabled: 'No hosted injection', + codexImageToolDisabledDesc: 'Do not inject the hosted tool; client-provided hosted tools and local image_gen declarations still pass through.', + codexImageToolBlock: 'Strip client image tools', + codexImageToolBlockDesc: 'Do not auto-inject through the bridge, and remove client-provided hosted image_generation tools, local image_gen declarations, and matching tool_choice. Image-only model routing remains unaffected.', codexImageToolBadgeInherit: 'Channel policy', - codexImageToolBadgeEnabled: 'Force inject', - codexImageToolBadgeDisabled: 'No injection', - codexImageToolBadgeBlock: 'Blocked', + codexImageToolBadgeEnabled: 'Hosted bridge on', + codexImageToolBadgeDisabled: 'No hosted injection', + codexImageToolBadgeBlock: 'Client image tools stripped', compactMode: 'Compact mode', compactModeDesc: 'Controls how this account participates in /responses/compact routing. Auto follows probe results, Force On always allows, Force Off always excludes.', diff --git a/frontend/src/i18n/locales/en/admin/channels.ts b/frontend/src/i18n/locales/en/admin/channels.ts index ce6327770f..96c0a6cbdf 100644 --- a/frontend/src/i18n/locales/en/admin/channels.ts +++ b/frontend/src/i18n/locales/en/admin/channels.ts @@ -156,7 +156,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: '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.', + codexImageGenerationBridgeHint: 'When enabled, only non-Responses Lite Codex /responses text requests in OpenAI groups receive the hosted image_generation tool. The bridge does not inject tools for Responses Lite; local image_gen handling follows the client and account policy. Leave this off unless 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', diff --git a/frontend/src/i18n/locales/en/dashboard.ts b/frontend/src/i18n/locales/en/dashboard.ts index 77c1d29ca8..06d15b9215 100644 --- a/frontend/src/i18n/locales/en/dashboard.ts +++ b/frontend/src/i18n/locales/en/dashboard.ts @@ -140,9 +140,10 @@ export default { openai: { description: 'Add the following configuration files to your Codex CLI config directory.', authModeTitle: 'Codex authentication mode', - authModeDescription: 'Compatibility mode keeps the existing setup for older Codex clients. API Key Mode enables the client-side image executor.', + authModeDescription: 'Compatibility mode keeps the existing setup for older Codex clients. API Key Mode authorizes the client-side image executor.', authModeLegacy: 'Compatibility mode', authModeApiKey: 'API Key Mode', + authModeApiKeyRestartNotice: 'After saving this configuration, completely quit and restart Codex Desktop or CLI, then create a new task so the client can rebuild its tool registry.', configTomlHint: 'Make sure the following content is at the beginning of the config.toml file', 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.', diff --git a/frontend/src/i18n/locales/zh/admin/accounts.ts b/frontend/src/i18n/locales/zh/admin/accounts.ts index e4e38e0709..e0c94bc8ae 100644 --- a/frontend/src/i18n/locales/zh/admin/accounts.ts +++ b/frontend/src/i18n/locales/zh/admin/accounts.ts @@ -587,21 +587,21 @@ export default { codexCLIOnlyDesc: '仅对 OpenAI OAuth 生效。开启后仅允许 Codex 官方客户端家族访问;关闭后完全绕过并保持原逻辑。', codexCLIOnlyAppServer: '允许 Codex app-server 客户端', codexCLIOnlyAppServerDesc: '仅在上方开关开启时生效。开启后本账号额外放行内嵌 Codex 引擎、经 app-server 协议接入的第三方客户端(如 Claude Code 的 codex 插件),仍需通过全局引擎指纹门;与全局 app-server 开关取 OR(任一开即放行)。', - codexImageTool: 'Codex 图片工具', + codexImageTool: 'Codex 图片桥接策略', codexImageToolDesc: - '统一控制 Codex /responses 文本请求的 image_generation 图片工具:是否自动注入,以及客户端自带该工具时是否放行。账号级策略优先于渠道和全局配置,不影响独立图片生成接口。', + '统一控制 Codex /responses 文本请求的 hosted image_generation 桥接和客户端图片工具声明。hosted 工具自动注入仅适用于非 Responses Lite 请求;账号级策略优先于渠道和全局配置,不影响独立图片生成接口。', codexImageToolInherit: '跟随渠道', - codexImageToolInheritDesc: '不写入账号覆盖,是否注入由渠道或全局策略决定;客户端自带的图片工具照常放行。', - codexImageToolEnabled: '强制注入', - codexImageToolEnabledDesc: '始终为 Codex /responses 请求注入图片工具。', - codexImageToolDisabled: '关闭注入', - codexImageToolDisabledDesc: '不自动注入;客户端自带的图片工具仍会放行。', - codexImageToolBlock: '完全阻断', - codexImageToolBlockDesc: '不注入,并移除客户端自带的图片工具及指向它的 tool_choice。', + codexImageToolInheritDesc: '不写入账号覆盖;非 Lite 请求是否注入 hosted 工具由渠道或全局策略决定,客户端显式携带的 hosted 工具和本地 image_gen 声明照常放行。', + codexImageToolEnabled: '启用 Hosted 桥接', + codexImageToolEnabledDesc: '仅为非 Responses Lite 请求注入 hosted image_generation 工具;客户端显式携带的图片工具仍会放行。', + codexImageToolDisabled: '不注入 Hosted 工具', + codexImageToolDisabledDesc: '不注入 hosted 工具;客户端显式携带的 hosted 工具和本地 image_gen 声明仍会放行。', + codexImageToolBlock: '移除客户端图片工具', + codexImageToolBlockDesc: '不通过桥接自动注入 hosted 工具,并移除客户端显式携带的 hosted image_generation 工具、本地 image_gen 声明及相关 tool_choice;image-only 模型路由不受影响。', codexImageToolBadgeInherit: '渠道策略', - codexImageToolBadgeEnabled: '强制注入', - codexImageToolBadgeDisabled: '关闭注入', - codexImageToolBadgeBlock: '完全阻断', + codexImageToolBadgeEnabled: 'Hosted 桥接已开启', + codexImageToolBadgeDisabled: '不注入 Hosted 工具', + codexImageToolBadgeBlock: '客户端图片工具已移除', compactMode: 'Compact 模式', compactModeDesc: '控制本账号在 /responses/compact 调度中的参与方式。Auto 跟随探测结果,Force On 强制允许,Force Off 强制排除。', diff --git a/frontend/src/i18n/locales/zh/admin/channels.ts b/frontend/src/i18n/locales/zh/admin/channels.ts index 56ffbb60c8..cdfb185c8a 100644 --- a/frontend/src/i18n/locales/zh/admin/channels.ts +++ b/frontend/src/i18n/locales/zh/admin/channels.ts @@ -156,7 +156,7 @@ export default { webSearchEmulationHint: '⚠️ 开启后该渠道下所有 Anthropic 分组的账号将自动拦截 web_search 请求,请谨慎操作', webSearchEmulationGlobalDisabled: '请先在系统设置 → 网关 → Web Search 模拟中启用全局开关', codexImageGenerationBridge: 'Codex 图片生成桥接', - codexImageGenerationBridgeHint: '开启后,OpenAI 分组的 Codex /responses 文本请求可能会被自动注入 image_generation 工具。仅在路由账号支持图片生成时开启。', + codexImageGenerationBridgeHint: '开启后,OpenAI 分组仅会为非 Responses Lite 的 Codex /responses 文本请求自动注入 hosted image_generation 工具。桥接不会为 Responses Lite 注入工具;本地 image_gen 的处理由客户端和账号策略决定。仅在路由账号支持图片生成时开启。', bedrockCCCompat: 'Bedrock CC 兼容', bedrockCCCompatHint: '⚠️ 开启后,该渠道下 Bedrock 账号的请求将进行 Claude Code 兼容处理(thinking 类型转换、tool_use ID 清理)', basicSettings: '基础设置', diff --git a/frontend/src/i18n/locales/zh/dashboard.ts b/frontend/src/i18n/locales/zh/dashboard.ts index 500bec422a..eaf0004086 100644 --- a/frontend/src/i18n/locales/zh/dashboard.ts +++ b/frontend/src/i18n/locales/zh/dashboard.ts @@ -140,9 +140,10 @@ export default { openai: { description: '将以下配置文件添加到 Codex CLI 配置目录中。', authModeTitle: 'Codex 认证模式', - authModeDescription: '兼容模式保留旧版 Codex 配置;API Key Mode 用于启用客户端图片执行器。', + authModeDescription: '兼容模式保留旧版 Codex 配置;API Key Mode 用于授权客户端图片执行器。', authModeLegacy: '兼容模式', authModeApiKey: 'API Key Mode', + authModeApiKeyRestartNotice: '保存此配置后,必须完全退出并重启 Codex Desktop 或 CLI,然后新建 task,让客户端重新构建工具注册表。', configTomlHint: '请确保以下内容位于 config.toml 文件的开头部分', note: '请确保配置目录存在。macOS/Linux 用户可运行 mkdir -p ~/.codex 创建目录。', noteWindows: