fix(onboarding): clarify Anthropic API vs OAuth provider entries and reorder (#38577)

The setup-flow provider list showed two Anthropic/Claude entries with
ambiguous labels ('Anthropic (Claude API)' and 'Claude Code (subscription)')
in no deliberate order. Relabel and reorder so the distinction and the
subscription caveat are explicit:

- 'Anthropic API Key' (PKCE, API path)
- 'Anthropic OAuth: Required Extra Usage Credits to Use Subscription' (external)
- Both Anthropic entries moved to the bottom of the list.
- 'OpenAI Codex (ChatGPT)' -> 'OpenAI OAuth (ChatGPT)', now first after Nous.

Applied consistently to the backend OAuth catalog (web_server.py) and the
desktop onboarding overlay's PROVIDER_DISPLAY title/order map; test
assertions updated to the new titles.
This commit is contained in:
Teknium 2026-06-03 17:46:04 -07:00 committed by GitHub
parent e7bc6189cf
commit d50741af90
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 31 additions and 26 deletions

View file

@ -52,11 +52,11 @@ describe('onboarding Picker', () => {
expect(screen.getByText('Nous Portal')).toBeTruthy()
expect(screen.getByText('Recommended')).toBeTruthy()
expect(screen.queryByText('Anthropic Claude')).toBeNull()
expect(screen.queryByText('Anthropic API Key')).toBeNull()
fireEvent.click(screen.getByRole('button', { name: 'Other providers' }))
expect(screen.getByText('Anthropic Claude')).toBeTruthy()
expect(screen.getByText('Anthropic API Key')).toBeTruthy()
expect(screen.getByRole('button', { name: 'Collapse' })).toBeTruthy()
})
@ -64,8 +64,8 @@ describe('onboarding Picker', () => {
setProviders([provider('anthropic', 'Anthropic Claude'), provider('openai-codex', 'OpenAI Codex / ChatGPT')])
render(<Picker ctx={ctx} />)
expect(screen.getByText('Anthropic Claude')).toBeTruthy()
expect(screen.getByText('OpenAI Codex / ChatGPT')).toBeTruthy()
expect(screen.getByText('Anthropic API Key')).toBeTruthy()
expect(screen.getByText('OpenAI OAuth (ChatGPT)')).toBeTruthy()
expect(screen.queryByText('Other sign-in options')).toBeNull()
expect(screen.queryByText('Recommended')).toBeNull()
})

View file

@ -102,12 +102,14 @@ const API_KEY_OPTIONS: ApiKeyOption[] = [
const PROVIDER_DISPLAY: Record<string, { order: number; title: string }> = {
nous: { order: 0, title: 'Nous Portal' },
anthropic: { order: 1, title: 'Anthropic Claude' },
'openai-codex': { order: 2, title: 'OpenAI Codex / ChatGPT' },
'minimax-oauth': { order: 3, title: 'MiniMax' },
'openai-codex': { order: 1, title: 'OpenAI OAuth (ChatGPT)' },
'minimax-oauth': { order: 2, title: 'MiniMax' },
'qwen-oauth': { order: 3, title: 'Qwen Code' },
'xai-oauth': { order: 4, title: 'xAI Grok' },
'claude-code': { order: 5, title: 'Claude Code' },
'qwen-oauth': { order: 6, title: 'Qwen Code' }
// Both Anthropic entries sit at the bottom: the API-key path first, then
// the subscription OAuth path (only works with extra usage credits).
anthropic: { order: 5, title: 'Anthropic API Key' },
'claude-code': { order: 6, title: 'Anthropic OAuth: Required Extra Usage Credits to Use Subscription' }
}
const assetPath = (path: string) => `${import.meta.env.BASE_URL}${path.replace(/^\/+/, '')}`

View file

@ -3099,22 +3099,6 @@ def _claude_code_only_status() -> Dict[str, Any]:
# show code + verification URL + poll, ``external`` = read-only (delegated
# to a third-party CLI like Claude Code or Qwen).
_OAUTH_PROVIDER_CATALOG: tuple[Dict[str, Any], ...] = (
{
"id": "anthropic",
"name": "Anthropic (Claude API)",
"flow": "pkce",
"cli_command": "hermes auth add anthropic",
"docs_url": "https://docs.claude.com/en/api/getting-started",
"status_fn": _anthropic_oauth_status,
},
{
"id": "claude-code",
"name": "Claude Code (subscription)",
"flow": "external",
"cli_command": "claude setup-token",
"docs_url": "https://docs.claude.com/en/docs/claude-code",
"status_fn": _claude_code_only_status,
},
{
"id": "nous",
"name": "Nous Portal",
@ -3125,7 +3109,7 @@ _OAUTH_PROVIDER_CATALOG: tuple[Dict[str, Any], ...] = (
},
{
"id": "openai-codex",
"name": "OpenAI Codex (ChatGPT)",
"name": "OpenAI OAuth (ChatGPT)",
"flow": "device_code",
"cli_command": "hermes auth add openai-codex",
"docs_url": "https://platform.openai.com/docs",
@ -3163,6 +3147,25 @@ _OAUTH_PROVIDER_CATALOG: tuple[Dict[str, Any], ...] = (
"docs_url": "https://hermes-agent.nousresearch.com/docs/guides/xai-grok-oauth",
"status_fn": None, # dispatched via auth.get_xai_oauth_auth_status
},
# ── Anthropic / Claude entries sit at the bottom: the API-key path
# first, then the subscription OAuth path (which only works with extra
# usage credits on top of a Claude Max plan — see disclaimer in name).
{
"id": "anthropic",
"name": "Anthropic API Key",
"flow": "pkce",
"cli_command": "hermes auth add anthropic",
"docs_url": "https://docs.claude.com/en/api/getting-started",
"status_fn": _anthropic_oauth_status,
},
{
"id": "claude-code",
"name": "Anthropic OAuth: Required Extra Usage Credits to Use Subscription",
"flow": "external",
"cli_command": "claude setup-token",
"docs_url": "https://docs.claude.com/en/docs/claude-code",
"status_fn": _claude_code_only_status,
},
)