From ca7f6ecd25187ccdf6c3c20dc8ed6bd0fdb28868 Mon Sep 17 00:00:00 2001 From: xintaofei Date: Sun, 15 Mar 2026 18:17:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81Codex=20CLI=E7=9A=84=E5=AE=98?= =?UTF-8?q?=E7=BD=91=E8=AE=A2=E9=98=85=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../settings/acp-agent-settings.tsx | 289 +++++++++++++----- src/i18n/messages/ar.json | 4 + src/i18n/messages/de.json | 4 + src/i18n/messages/en.json | 4 + src/i18n/messages/es.json | 4 + src/i18n/messages/fr.json | 4 + src/i18n/messages/ja.json | 4 + src/i18n/messages/ko.json | 4 + src/i18n/messages/pt.json | 4 + src/i18n/messages/zh-CN.json | 4 + src/i18n/messages/zh-TW.json | 4 + 11 files changed, 248 insertions(+), 81 deletions(-) diff --git a/src/components/settings/acp-agent-settings.tsx b/src/components/settings/acp-agent-settings.tsx index 8e33fbb..16809c1 100644 --- a/src/components/settings/acp-agent-settings.tsx +++ b/src/components/settings/acp-agent-settings.tsx @@ -92,6 +92,7 @@ interface AgentDraft { googleCloudProject: string googleCloudLocation: string googleApplicationCredentials: string + codexAuthMode: CodexAuthMode codexModelProvider: string codexProviderOptions: string[] codexReasoningEffort: CodexReasoningEffort @@ -970,6 +971,10 @@ interface CodexImportantValues { } const CODEX_DEFAULT_MODEL_PROVIDER = "codeg" + +const CODEX_AUTH_MODES = ["api_key", "chatgpt_subscription"] as const +type CodexAuthMode = (typeof CODEX_AUTH_MODES)[number] + type CodexReasoningEffort = "low" | "medium" | "high" | "xhigh" const CODEX_REASONING_EFFORT_OPTIONS: ReadonlyArray<{ @@ -1283,6 +1288,21 @@ function parseCodexAuthJsonText(authJsonText: string): string | null { return parseCodexAuthJsonObject(authJsonText).error } +function inferCodexAuthMode(authJsonText: string): CodexAuthMode { + const { authObject } = parseCodexAuthJsonObject(authJsonText) + if (authObject) { + // 官网订阅:auth_mode 为 chatgpt,或没有 OPENAI_API_KEY,或值为 null + if ( + authObject.auth_mode === "chatgpt" || + !("OPENAI_API_KEY" in authObject) || + authObject.OPENAI_API_KEY === null + ) { + return "chatgpt_subscription" + } + } + return "api_key" +} + function extractCodexImportantValues( authJsonText: string, configTomlText: string @@ -1982,6 +2002,10 @@ function buildAgentDraft(agent: AcpAgentInfo): AgentDraft { googleCloudProject: geminiImportant.googleCloudProject, googleCloudLocation: geminiImportant.googleCloudLocation, googleApplicationCredentials: geminiImportant.googleApplicationCredentials, + codexAuthMode: + agent.agent_type === "codex" + ? inferCodexAuthMode(codexAuthJsonText) + : "api_key", codexModelProvider: codexImportant.modelProvider, codexProviderOptions: codexImportant.providerOptions, codexReasoningEffort: codexImportant.reasoningEffort, @@ -3956,6 +3980,7 @@ export function AcpAgentSettings() { ) updateSelectedDraft((current) => ({ ...current, + codexAuthMode: inferCodexAuthMode(nextText), codexAuthJsonText: nextText, apiBaseUrl: important.apiBaseUrl, apiKey: important.apiKey ?? current.apiKey, @@ -4027,6 +4052,58 @@ export function AcpAgentSettings() { [selectedAgent, selectedDraft, updateSelectedDraft] ) + const handleCodexAuthModeChange = useCallback( + (nextMode: CodexAuthMode) => { + if ( + !selectedAgent || + !selectedDraft || + selectedAgent.agent_type !== "codex" + ) + return + + const nextAuthJsonText = + nextMode === "chatgpt_subscription" + ? "{}" + : JSON.stringify({ OPENAI_API_KEY: "" }, null, 2) + + const nextConfigTomlText = + nextMode === "chatgpt_subscription" + ? "" + : selectedDraft.codexConfigTomlText + + const nextEnvText = + nextMode === "chatgpt_subscription" + ? patchEnvText(selectedDraft.envText, { + OPENAI_API_KEY: "", + OPENAI_BASE_URL: "", + }) + : selectedDraft.envText + + const synced = extractCodexImportantValues( + nextAuthJsonText, + nextConfigTomlText + ) + + updateSelectedDraft((current) => ({ + ...current, + codexAuthMode: nextMode, + codexAuthJsonText: nextAuthJsonText, + codexConfigTomlText: nextConfigTomlText, + envText: nextEnvText, + apiBaseUrl: + nextMode === "chatgpt_subscription" ? "" : synced.apiBaseUrl, + apiKey: + nextMode === "chatgpt_subscription" ? "" : (synced.apiKey ?? ""), + model: synced.model, + codexModelProvider: synced.modelProvider, + codexProviderOptions: synced.providerOptions, + codexReasoningEffort: synced.reasoningEffort, + codexSupportsWebsockets: synced.supportsWebsockets, + })) + }, + [selectedAgent, selectedDraft, updateSelectedDraft] + ) + const handleCodexImportantConfigChange = useCallback( ( key: "apiBaseUrl" | "apiKey" | "model" | "reasoningEffort", @@ -4484,106 +4561,148 @@ export function AcpAgentSettings() {
+

+ {selectedDraft.codexAuthMode === "chatgpt_subscription" + ? t("codex.chatgptSubscriptionHint") + : t("codex.apiKeyHint")} +

-
- - { - handleCodexImportantConfigChange( - "apiBaseUrl", - event.target.value - ) - }} - placeholder="https://api.openai.com/v1" - /> -
+ {selectedDraft.codexAuthMode !== "chatgpt_subscription" && ( +
+ + +
+ )} -
- -
+ {selectedDraft.codexAuthMode !== "chatgpt_subscription" && ( +
+ { handleCodexImportantConfigChange( - "apiKey", + "apiBaseUrl", event.target.value ) }} - placeholder="sk-..." + placeholder="https://api.openai.com/v1" /> -
-
+ )} -
- - { - handleCodexImportantConfigChange( - "model", - event.target.value - ) - }} - placeholder="gpt-5 / gpt-5-mini" - /> -
+ {selectedDraft.codexAuthMode !== "chatgpt_subscription" && ( +
+ +
+ { + handleCodexImportantConfigChange( + "apiKey", + event.target.value + ) + }} + placeholder="sk-..." + /> + +
+
+ )} + + {selectedDraft.codexAuthMode !== "chatgpt_subscription" && ( +
+ + { + handleCodexImportantConfigChange( + "model", + event.target.value + ) + }} + placeholder="gpt-5 / gpt-5-mini" + /> +
+ )}