fix(settings): improve codex CLI auth mode switching to preserve auth.json keys

- Patch only `OPENAI_API_KEY` and `auth_mode` in auth.json when switching
  auth modes, instead of resetting the entire file
- Clean up `OPENAI_BASE_URL` from env when codex loads in official
  subscription mode
- Hide API URL and API Key inputs when model provider mode is selected

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
xintaofei
2026-04-06 23:05:52 +08:00
parent b64976e4d6
commit 4245df2f4a

View File

@@ -1782,7 +1782,7 @@ function ensureCodexProviderDefaults(
function patchCodexAuthJsonText( function patchCodexAuthJsonText(
authJsonText: string, authJsonText: string,
patch: { apiKey?: string } patch: { apiKey?: string; authMode?: "chatgpt" | null }
): { ): {
authJsonText: string authJsonText: string
recoveredFromInvalid: boolean recoveredFromInvalid: boolean
@@ -1801,6 +1801,14 @@ function patchCodexAuthJsonText(
delete authObject.API_KEY delete authObject.API_KEY
} }
} }
if ("authMode" in patch) {
if (patch.authMode === "chatgpt") {
authObject.auth_mode = "chatgpt"
authObject.OPENAI_API_KEY = null
} else {
delete authObject.auth_mode
}
}
return { return {
authJsonText: authJsonText:
Object.keys(authObject).length === 0 Object.keys(authObject).length === 0
@@ -2082,9 +2090,24 @@ function buildAgentDraft(agent: AcpAgentInfo): AgentDraft {
openCodeAuthJsonText openCodeAuthJsonText
) )
const clineImportant = extractClineImportantValues(configText) const clineImportant = extractClineImportantValues(configText)
const codexAuthMode: CodexAuthMode =
agent.agent_type === "codex" && agent.model_provider_id != null
? "model_provider"
: agent.agent_type === "codex"
? inferCodexAuthMode(codexAuthJsonText)
: "api_key"
const rawEnvText = envMapToText(agent.env)
// When codex is in official subscription mode, clean up API keys/URLs from env
const envText =
agent.agent_type === "codex" && codexAuthMode === "chatgpt_subscription"
? patchEnvText(rawEnvText, {
OPENAI_API_KEY: "",
OPENAI_BASE_URL: "",
})
: rawEnvText
return { return {
enabled: agent.enabled, enabled: agent.enabled,
envText: envMapToText(agent.env), envText,
configText, configText,
apiBaseUrl: apiBaseUrl:
agent.agent_type === "codex" agent.agent_type === "codex"
@@ -2123,12 +2146,7 @@ function buildAgentDraft(agent: AcpAgentInfo): AgentDraft {
googleCloudProject: geminiImportant.googleCloudProject, googleCloudProject: geminiImportant.googleCloudProject,
googleCloudLocation: geminiImportant.googleCloudLocation, googleCloudLocation: geminiImportant.googleCloudLocation,
googleApplicationCredentials: geminiImportant.googleApplicationCredentials, googleApplicationCredentials: geminiImportant.googleApplicationCredentials,
codexAuthMode: codexAuthMode,
agent.agent_type === "codex" && agent.model_provider_id != null
? "model_provider"
: agent.agent_type === "codex"
? inferCodexAuthMode(codexAuthJsonText)
: "api_key",
codexModelProvider: codexImportant.modelProvider, codexModelProvider: codexImportant.modelProvider,
codexProviderOptions: codexImportant.providerOptions, codexProviderOptions: codexImportant.providerOptions,
codexReasoningEffort: codexImportant.reasoningEffort, codexReasoningEffort: codexImportant.reasoningEffort,
@@ -3472,9 +3490,11 @@ export function AcpAgentSettings() {
configText: nextConfigJson.configText, configText: nextConfigJson.configText,
})) }))
} else if (agentType === "codex") { } else if (agentType === "codex") {
const nextAuthJsonText = apiKey const nextAuthPatch = patchCodexAuthJsonText(
? JSON.stringify({ OPENAI_API_KEY: apiKey }, null, 2) selectedDraft.codexAuthJsonText,
: "{}" { apiKey, authMode: null }
)
const nextAuthJsonText = nextAuthPatch.authJsonText
const nextConfigTomlText = patchCodexConfigTomlText( const nextConfigTomlText = patchCodexConfigTomlText(
selectedDraft.codexConfigTomlText, selectedDraft.codexConfigTomlText,
{ {
@@ -4344,8 +4364,12 @@ export function AcpAgentSettings() {
return return
if (nextMode === "chatgpt_subscription") { if (nextMode === "chatgpt_subscription") {
// Official subscription: clear API URL/Key from env, remove model_provider config from toml // Official subscription: set auth_mode to chatgpt, OPENAI_API_KEY to null
const nextAuthJsonText = "{}" const nextAuth = patchCodexAuthJsonText(
selectedDraft.codexAuthJsonText,
{ authMode: "chatgpt" }
)
const nextAuthJsonText = nextAuth.authJsonText
let nextConfigTomlText = updateTomlRootStringKey( let nextConfigTomlText = updateTomlRootStringKey(
selectedDraft.codexConfigTomlText, selectedDraft.codexConfigTomlText,
"model_provider", "model_provider",
@@ -4385,14 +4409,11 @@ export function AcpAgentSettings() {
selectedDraft.codexConfigTomlText, selectedDraft.codexConfigTomlText,
{ modelProvider: CODEX_DEFAULT_MODEL_PROVIDER } { modelProvider: CODEX_DEFAULT_MODEL_PROVIDER }
) )
const nextAuthJsonText = const nextAuthPatch = patchCodexAuthJsonText(
nextMode === "api_key" selectedDraft.codexAuthJsonText,
? JSON.stringify( { authMode: null }
{ OPENAI_API_KEY: selectedDraft.apiKey || "" }, )
null, const nextAuthJsonText = nextAuthPatch.authJsonText
2
)
: selectedDraft.codexAuthJsonText
const synced = extractCodexImportantValues( const synced = extractCodexImportantValues(
nextAuthJsonText, nextAuthJsonText,
nextConfigTomlText nextConfigTomlText
@@ -4940,17 +4961,13 @@ export function AcpAgentSettings() {
</div> </div>
)} )}
{(selectedDraft.codexAuthMode === "api_key" || {selectedDraft.codexAuthMode === "api_key" && (
selectedDraft.codexAuthMode === "model_provider") && (
<div className="space-y-1.5"> <div className="space-y-1.5">
<label className="text-[11px] text-muted-foreground"> <label className="text-[11px] text-muted-foreground">
API URL API URL
</label> </label>
<Input <Input
value={selectedDraft.apiBaseUrl} value={selectedDraft.apiBaseUrl}
readOnly={
selectedDraft.codexAuthMode === "model_provider"
}
onChange={(event) => { onChange={(event) => {
handleCodexImportantConfigChange( handleCodexImportantConfigChange(
"apiBaseUrl", "apiBaseUrl",
@@ -4962,8 +4979,7 @@ export function AcpAgentSettings() {
</div> </div>
)} )}
{(selectedDraft.codexAuthMode === "api_key" || {selectedDraft.codexAuthMode === "api_key" && (
selectedDraft.codexAuthMode === "model_provider") && (
<div className="space-y-1.5"> <div className="space-y-1.5">
<label className="text-[11px] text-muted-foreground"> <label className="text-[11px] text-muted-foreground">
API Key API Key
@@ -4976,9 +4992,6 @@ export function AcpAgentSettings() {
: "password" : "password"
} }
value={selectedDraft.apiKey} value={selectedDraft.apiKey}
readOnly={
selectedDraft.codexAuthMode === "model_provider"
}
onChange={(event) => { onChange={(event) => {
handleCodexImportantConfigChange( handleCodexImportantConfigChange(
"apiKey", "apiKey",