Skip to content

Commit 49e9382

Browse files
authored
fix(configure): unify OpenAI auth provider picker (#82324)
1 parent 8d3b5c2 commit 49e9382

20 files changed

Lines changed: 187 additions & 60 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Docs: https://docs.openclaw.ai
2424
- Providers: reject malformed successful Runway, BytePlus, and Ollama embedding responses with provider-owned errors instead of raw parser/type failures, silent bad vectors, or long bogus polling.
2525
- Trajectory export: skip and report malformed session/runtime JSONL rows in `manifest.json` instead of letting wrong-shaped session rows crash support bundle export.
2626
- Config/doctor: copy fallback-enabled channel `allowFrom` entries into explicit `groupAllowFrom` allowlists during `openclaw doctor --fix`, preserving current group access without adding runtime fallback-transition flags.
27+
- Configure: show one OpenAI provider entry with ChatGPT/Codex sign-in and API key choices, and keep browsed Codex models in the saved `/model` picker allowlist.
2728
- Hooks: raise bounded gateway lifecycle hook wait budgets to 5 seconds for shutdown and 10 seconds for pre-restart, giving short restart notification handlers time to finish before shutdown continues. (#82273) Thanks @bryanbaer.
2829
- Plugin releases: require external package compatibility metadata in the npm plugin publish plan, matching the ClawHub package contract before packages ship.
2930
- Agents/OpenAI-compatible: honor per-model `max_completion_tokens`/`max_tokens` params in embedded OpenAI-completions runs so high-token Kimi-style routes keep their configured completion cap. Fixes #82230. Thanks @albert-zen.

extensions/openai/auth-choice-copy.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ export const OPENAI_CHATGPT_DEVICE_PAIRING_HINT =
77
export const OPENAI_CODEX_API_KEY_BACKUP_LABEL = "OpenAI API Key Backup";
88
export const OPENAI_CODEX_API_KEY_BACKUP_HINT =
99
"Use an OpenAI API key when your Codex subscription is unavailable";
10-
export const OPENAI_CODEX_LOGIN_LABEL = "OpenAI Codex Browser Login";
10+
export const OPENAI_CODEX_LOGIN_LABEL = "ChatGPT/Codex Browser Login";
1111
export const OPENAI_CODEX_LOGIN_HINT = "Sign in with OpenAI in your browser";
12-
export const OPENAI_CODEX_DEVICE_PAIRING_LABEL = "OpenAI Codex Device Pairing";
12+
export const OPENAI_CODEX_DEVICE_PAIRING_LABEL = "ChatGPT/Codex Device Pairing";
1313
export const OPENAI_CODEX_DEVICE_PAIRING_HINT = "Pair in browser with a device code";
1414

15+
const OPENAI_UNIFIED_GROUP_HINT = "ChatGPT/Codex sign-in or API key";
16+
1517
export const OPENAI_API_KEY_WIZARD_GROUP = {
1618
groupId: "openai",
1719
groupLabel: "OpenAI",
@@ -21,11 +23,11 @@ export const OPENAI_API_KEY_WIZARD_GROUP = {
2123
export const OPENAI_ACCOUNT_WIZARD_GROUP = {
2224
groupId: "openai",
2325
groupLabel: "OpenAI",
24-
groupHint: "ChatGPT subscription or API key",
26+
groupHint: OPENAI_UNIFIED_GROUP_HINT,
2527
} as const;
2628

2729
export const OPENAI_CODEX_WIZARD_GROUP = {
28-
groupId: "openai-codex",
29-
groupLabel: "OpenAI Codex",
30-
groupHint: "ChatGPT/Codex sign-in",
30+
groupId: "openai",
31+
groupLabel: "OpenAI",
32+
groupHint: OPENAI_UNIFIED_GROUP_HINT,
3133
} as const;

extensions/openai/openai-codex-provider.test.ts

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -170,23 +170,23 @@ describe("openai codex provider", () => {
170170
const apiKey = requireAuthMethod(provider, "api-key");
171171

172172
expectRecordFields(oauth.wizard, "oauth wizard", {
173-
choiceLabel: "OpenAI Codex Browser Login",
174-
groupId: "openai-codex",
175-
groupLabel: "OpenAI Codex",
176-
groupHint: "ChatGPT/Codex sign-in",
173+
choiceLabel: "ChatGPT/Codex Browser Login",
174+
groupId: "openai",
175+
groupLabel: "OpenAI",
176+
groupHint: "ChatGPT/Codex sign-in or API key",
177177
});
178178
expectRecordFields(deviceCode.wizard, "device-code wizard", {
179-
choiceLabel: "OpenAI Codex Device Pairing",
180-
groupId: "openai-codex",
181-
groupLabel: "OpenAI Codex",
182-
groupHint: "ChatGPT/Codex sign-in",
179+
choiceLabel: "ChatGPT/Codex Device Pairing",
180+
groupId: "openai",
181+
groupLabel: "OpenAI",
182+
groupHint: "ChatGPT/Codex sign-in or API key",
183183
});
184184
expectRecordFields(apiKey.wizard, "api-key wizard", {
185185
choiceLabel: "OpenAI API Key Backup",
186186
choiceHint: "Use an OpenAI API key when your Codex subscription is unavailable",
187-
groupId: "openai-codex",
188-
groupLabel: "OpenAI Codex",
189-
groupHint: "ChatGPT/Codex sign-in",
187+
groupId: "openai",
188+
groupLabel: "OpenAI",
189+
groupHint: "ChatGPT/Codex sign-in or API key",
190190
});
191191
});
192192

@@ -222,19 +222,20 @@ describe("openai codex provider", () => {
222222
const deviceCode = requireAuthMethod(provider, "device-code");
223223

224224
expect(provider.auth?.map((method) => method.id)).toEqual(["oauth", "device-code", "api-key"]);
225-
expect(oauth.label).toBe("OpenAI Codex Browser Login");
225+
expect(oauth.label).toBe("ChatGPT/Codex Browser Login");
226226
expect(oauth.hint).toBe("Sign in with OpenAI in your browser");
227227
expectRecordFields(oauth.wizard, "oauth wizard", {
228228
choiceId: "openai-codex",
229-
choiceLabel: "OpenAI Codex Browser Login",
229+
choiceLabel: "ChatGPT/Codex Browser Login",
230230
assistantPriority: -30,
231+
onboardingFeatured: true,
231232
});
232-
expect(deviceCode.label).toBe("OpenAI Codex Device Pairing");
233+
expect(deviceCode.label).toBe("ChatGPT/Codex Device Pairing");
233234
expect(deviceCode.hint).toBe("Pair in browser with a device code");
234235
expect(deviceCode.kind).toBe("device_code");
235236
expectRecordFields(deviceCode.wizard, "device-code wizard", {
236237
choiceId: "openai-codex-device-code",
237-
choiceLabel: "OpenAI Codex Device Pairing",
238+
choiceLabel: "ChatGPT/Codex Device Pairing",
238239
assistantPriority: -10,
239240
});
240241
});

extensions/openai/openai-codex-provider.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ export function buildOpenAICodexProviderPlugin(): ProviderPlugin {
489489
choiceLabel: OPENAI_CODEX_LOGIN_LABEL,
490490
choiceHint: OPENAI_CODEX_LOGIN_HINT,
491491
assistantPriority: OPENAI_CODEX_LOGIN_ASSISTANT_PRIORITY,
492+
onboardingFeatured: true,
492493
...OPENAI_CODEX_WIZARD_GROUP,
493494
},
494495
run: async (ctx) => await runOpenAICodexOAuth(ctx),
@@ -525,6 +526,7 @@ export function buildOpenAICodexProviderPlugin(): ProviderPlugin {
525526
choiceLabel: OPENAI_CODEX_API_KEY_BACKUP_LABEL,
526527
choiceHint: OPENAI_CODEX_API_KEY_BACKUP_HINT,
527528
assistantPriority: 5,
529+
assistantVisibility: "manual-only",
528530
...OPENAI_CODEX_WIZARD_GROUP,
529531
},
530532
}),

extensions/openai/openai-provider.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ describe("buildOpenAIProvider", () => {
132132
choiceHint: "Use your OpenAI API key directly",
133133
groupId: "openai",
134134
groupLabel: "OpenAI",
135-
groupHint: "ChatGPT subscription or API key",
135+
groupHint: "ChatGPT/Codex sign-in or API key",
136136
});
137137
});
138138

extensions/openai/openclaw.plugin.json

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -767,9 +767,10 @@
767767
"choiceLabel": "ChatGPT Login",
768768
"choiceHint": "Sign in with your ChatGPT or Codex subscription",
769769
"assistantPriority": -40,
770+
"assistantVisibility": "manual-only",
770771
"groupId": "openai",
771772
"groupLabel": "OpenAI",
772-
"groupHint": "ChatGPT subscription or API key"
773+
"groupHint": "ChatGPT/Codex sign-in or API key"
773774
},
774775
{
775776
"provider": "openai",
@@ -778,32 +779,34 @@
778779
"choiceLabel": "ChatGPT Device Pairing",
779780
"choiceHint": "Pair your ChatGPT account in browser with a device code",
780781
"assistantPriority": -10,
782+
"assistantVisibility": "manual-only",
781783
"groupId": "openai",
782784
"groupLabel": "OpenAI",
783-
"groupHint": "ChatGPT subscription or API key"
785+
"groupHint": "ChatGPT/Codex sign-in or API key"
784786
},
785787
{
786788
"provider": "openai-codex",
787789
"method": "oauth",
788790
"choiceId": "openai-codex",
789791
"deprecatedChoiceIds": ["codex-cli", "openai-codex-import"],
790-
"choiceLabel": "OpenAI Codex Browser Login",
792+
"choiceLabel": "ChatGPT/Codex Browser Login",
791793
"choiceHint": "Sign in with OpenAI in your browser",
792794
"assistantPriority": -30,
793-
"groupId": "openai-codex",
794-
"groupLabel": "OpenAI Codex",
795-
"groupHint": "ChatGPT/Codex sign-in"
795+
"groupId": "openai",
796+
"groupLabel": "OpenAI",
797+
"groupHint": "ChatGPT/Codex sign-in or API key",
798+
"onboardingFeatured": true
796799
},
797800
{
798801
"provider": "openai-codex",
799802
"method": "device-code",
800803
"choiceId": "openai-codex-device-code",
801-
"choiceLabel": "OpenAI Codex Device Pairing",
804+
"choiceLabel": "ChatGPT/Codex Device Pairing",
802805
"choiceHint": "Pair in browser with a device code",
803806
"assistantPriority": -10,
804-
"groupId": "openai-codex",
805-
"groupLabel": "OpenAI Codex",
806-
"groupHint": "ChatGPT/Codex sign-in"
807+
"groupId": "openai",
808+
"groupLabel": "OpenAI",
809+
"groupHint": "ChatGPT/Codex sign-in or API key"
807810
},
808811
{
809812
"provider": "openai-codex",
@@ -813,9 +816,9 @@
813816
"choiceHint": "Use an OpenAI API key when your Codex subscription is unavailable",
814817
"assistantPriority": 5,
815818
"assistantVisibility": "manual-only",
816-
"groupId": "openai-codex",
817-
"groupLabel": "OpenAI Codex",
818-
"groupHint": "ChatGPT/Codex sign-in",
819+
"groupId": "openai",
820+
"groupLabel": "OpenAI",
821+
"groupHint": "ChatGPT/Codex sign-in or API key",
819822
"optionKey": "openaiApiKey",
820823
"cliFlag": "--openai-api-key",
821824
"cliOption": "--openai-api-key <key>",
@@ -830,7 +833,7 @@
830833
"assistantPriority": 5,
831834
"groupId": "openai",
832835
"groupLabel": "OpenAI",
833-
"groupHint": "ChatGPT subscription or API key",
836+
"groupHint": "ChatGPT/Codex sign-in or API key",
834837
"onboardingFeatured": true,
835838
"optionKey": "openaiApiKey",
836839
"cliFlag": "--openai-api-key",

extensions/openai/openclaw.plugin.test.ts

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const manifest = JSON.parse(
2222
choiceHint?: string;
2323
choiceId?: string;
2424
deprecatedChoiceIds?: string[];
25+
assistantVisibility?: string;
2526
groupId?: string;
2627
groupLabel?: string;
2728
groupHint?: string;
@@ -38,6 +39,7 @@ function manifestComparableWizardFields(choice: {
3839
choiceId?: string;
3940
choiceLabel?: string;
4041
choiceHint?: string;
42+
assistantVisibility?: string;
4143
groupId?: string;
4244
groupLabel?: string;
4345
groupHint?: string;
@@ -47,6 +49,7 @@ function manifestComparableWizardFields(choice: {
4749
choiceId: choice.choiceId,
4850
choiceLabel: choice.choiceLabel,
4951
choiceHint: choice.choiceHint,
52+
assistantVisibility: choice.assistantVisibility,
5053
groupId: choice.groupId,
5154
groupLabel: choice.groupLabel,
5255
groupHint: choice.groupHint,
@@ -125,38 +128,40 @@ describe("OpenAI plugin manifest", () => {
125128

126129
expect(openAiLogin?.choiceLabel).toBe("ChatGPT Login");
127130
expect(openAiLogin?.choiceHint).toBe("Sign in with your ChatGPT or Codex subscription");
131+
expect(openAiLogin?.assistantVisibility).toBe("manual-only");
128132
expect(openAiLogin?.groupId).toBe("openai");
129133
expect(openAiLogin?.groupLabel).toBe("OpenAI");
130-
expect(openAiLogin?.groupHint).toBe("ChatGPT subscription or API key");
134+
expect(openAiLogin?.groupHint).toBe("ChatGPT/Codex sign-in or API key");
131135
expect(openAiDeviceCode?.choiceLabel).toBe("ChatGPT Device Pairing");
132136
expect(openAiDeviceCode?.choiceHint).toBe(
133137
"Pair your ChatGPT account in browser with a device code",
134138
);
139+
expect(openAiDeviceCode?.assistantVisibility).toBe("manual-only");
135140
expect(openAiDeviceCode?.groupId).toBe("openai");
136141
expect(openAiDeviceCode?.groupLabel).toBe("OpenAI");
137-
expect(openAiDeviceCode?.groupHint).toBe("ChatGPT subscription or API key");
138-
expect(codexBrowserLogin?.choiceLabel).toBe("OpenAI Codex Browser Login");
142+
expect(openAiDeviceCode?.groupHint).toBe("ChatGPT/Codex sign-in or API key");
143+
expect(codexBrowserLogin?.choiceLabel).toBe("ChatGPT/Codex Browser Login");
139144
expect(codexBrowserLogin?.choiceHint).toBe("Sign in with OpenAI in your browser");
140-
expect(codexBrowserLogin?.groupId).toBe("openai-codex");
141-
expect(codexBrowserLogin?.groupLabel).toBe("OpenAI Codex");
142-
expect(codexBrowserLogin?.groupHint).toBe("ChatGPT/Codex sign-in");
143-
expect(codexDeviceCode?.choiceLabel).toBe("OpenAI Codex Device Pairing");
145+
expect(codexBrowserLogin?.groupId).toBe("openai");
146+
expect(codexBrowserLogin?.groupLabel).toBe("OpenAI");
147+
expect(codexBrowserLogin?.groupHint).toBe("ChatGPT/Codex sign-in or API key");
148+
expect(codexDeviceCode?.choiceLabel).toBe("ChatGPT/Codex Device Pairing");
144149
expect(codexDeviceCode?.choiceHint).toBe("Pair in browser with a device code");
145-
expect(codexDeviceCode?.groupId).toBe("openai-codex");
146-
expect(codexDeviceCode?.groupLabel).toBe("OpenAI Codex");
147-
expect(codexDeviceCode?.groupHint).toBe("ChatGPT/Codex sign-in");
150+
expect(codexDeviceCode?.groupId).toBe("openai");
151+
expect(codexDeviceCode?.groupLabel).toBe("OpenAI");
152+
expect(codexDeviceCode?.groupHint).toBe("ChatGPT/Codex sign-in or API key");
148153
expect(apiKey?.choiceLabel).toBe("OpenAI API Key");
149154
expect(apiKey?.choiceHint).toBe("Use your OpenAI API key directly");
150155
expect(apiKey?.groupId).toBe("openai");
151156
expect(apiKey?.groupLabel).toBe("OpenAI");
152-
expect(apiKey?.groupHint).toBe("ChatGPT subscription or API key");
157+
expect(apiKey?.groupHint).toBe("ChatGPT/Codex sign-in or API key");
153158
expect(codexApiKey?.choiceLabel).toBe("OpenAI API Key Backup");
154159
expect(codexApiKey?.choiceHint).toBe(
155160
"Use an OpenAI API key when your Codex subscription is unavailable",
156161
);
157-
expect(codexApiKey?.groupId).toBe("openai-codex");
158-
expect(codexApiKey?.groupLabel).toBe("OpenAI Codex");
159-
expect(codexApiKey?.groupHint).toBe("ChatGPT/Codex sign-in");
162+
expect(codexApiKey?.groupId).toBe("openai");
163+
expect(codexApiKey?.groupLabel).toBe("OpenAI");
164+
expect(codexApiKey?.groupHint).toBe("ChatGPT/Codex sign-in or API key");
160165
expect(choices.map((choice) => choice.choiceLabel)).not.toContain(
161166
"OpenAI Codex (ChatGPT OAuth)",
162167
);

extensions/openai/provider-contract-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export function createOpenAICodexProvider(): ProviderPlugin {
3434
choiceLabel: OPENAI_CODEX_LOGIN_LABEL,
3535
choiceHint: OPENAI_CODEX_LOGIN_HINT,
3636
assistantPriority: -30,
37+
onboardingFeatured: true,
3738
...OPENAI_CODEX_WIZARD_GROUP,
3839
},
3940
},

extensions/openai/setup-api.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ describe("OpenAI setup auth provider", () => {
1515
expect(authMethodIds(provider)).toEqual(["oauth", "device-code", "api-key"]);
1616
expect(oauth?.label).toBe("ChatGPT Login");
1717
expect(oauth?.wizard?.choiceId).toBe("openai");
18+
expect(oauth?.wizard?.assistantVisibility).toBe("manual-only");
1819
expect(apiKey?.label).toBe("OpenAI API Key");
1920
expect(apiKey?.wizard?.choiceId).toBe("openai-api-key");
2021
});

extensions/openai/setup-api.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export function buildOpenAISetupProvider(): ProviderPlugin {
5353
choiceLabel: OPENAI_CHATGPT_LOGIN_LABEL,
5454
choiceHint: OPENAI_CHATGPT_LOGIN_HINT,
5555
assistantPriority: -40,
56+
assistantVisibility: "manual-only",
5657
...OPENAI_ACCOUNT_WIZARD_GROUP,
5758
},
5859
run: async (ctx) => runOpenAICodexProviderAuthMethod("oauth", ctx),
@@ -68,6 +69,7 @@ export function buildOpenAISetupProvider(): ProviderPlugin {
6869
choiceLabel: OPENAI_CHATGPT_DEVICE_PAIRING_LABEL,
6970
choiceHint: OPENAI_CHATGPT_DEVICE_PAIRING_HINT,
7071
assistantPriority: -10,
72+
assistantVisibility: "manual-only",
7173
...OPENAI_ACCOUNT_WIZARD_GROUP,
7274
},
7375
run: async (ctx) => runOpenAICodexProviderAuthMethod("device-code", ctx),
@@ -108,6 +110,7 @@ export function buildOpenAICodexSetupProvider(): ProviderPlugin {
108110
choiceLabel: OPENAI_CODEX_LOGIN_LABEL,
109111
choiceHint: OPENAI_CODEX_LOGIN_HINT,
110112
assistantPriority: -30,
113+
onboardingFeatured: true,
111114
...OPENAI_CODEX_WIZARD_GROUP,
112115
},
113116
run: async (ctx) => runOpenAICodexProviderAuthMethod("oauth", ctx),
@@ -138,6 +141,7 @@ export function buildOpenAICodexSetupProvider(): ProviderPlugin {
138141
choiceLabel: OPENAI_CODEX_API_KEY_BACKUP_LABEL,
139142
choiceHint: OPENAI_CODEX_API_KEY_BACKUP_HINT,
140143
assistantPriority: 5,
144+
assistantVisibility: "manual-only",
141145
...OPENAI_CODEX_WIZARD_GROUP,
142146
},
143147
run: async (ctx) => runOpenAICodexProviderAuthMethod("api-key", ctx),

0 commit comments

Comments
 (0)