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" && (
+
+
{
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"
+ />
+
+ )}