From 85f30e07a5441b8b90c1d0291dd26492a34d24cc Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Thu, 7 May 2026 23:37:45 -0400 Subject: [PATCH] fix(desktop): polish onboarding provider list Reorder OAuth providers so Nous Portal is first, give the segmented Sign in / API key control equal column widths, and replace the engineer-flavored backend names like "Anthropic (Claude API)" / "MiniMax (OAuth)" with friendlier in-app titles. External-CLI providers now show a softer subtitle and an external-link icon instead of a chevron. --- .../components/desktop-onboarding-overlay.tsx | 86 ++++++++++++++----- 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/apps/desktop/src/components/desktop-onboarding-overlay.tsx b/apps/desktop/src/components/desktop-onboarding-overlay.tsx index c3d5d3b2e050..1d6eb6820e4f 100644 --- a/apps/desktop/src/components/desktop-onboarding-overlay.tsx +++ b/apps/desktop/src/components/desktop-onboarding-overlay.tsx @@ -98,6 +98,36 @@ interface FlowState { const POLL_INTERVAL_MS = 2000 +// Order/display overrides for the OAuth provider catalog. The backend ships +// engineer-flavored names like "Anthropic (Claude API)" and "MiniMax (OAuth)"; +// the desktop renames them in-place so the overlay reads like a consumer +// product. Anything not in this map keeps the backend's default name. +const PROVIDER_DISPLAY: Record = { + 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' }, + 'claude-code': { order: 4, title: 'Claude Code' }, + 'qwen-oauth': { order: 5, title: 'Qwen Code' } +} + +function displayProviderTitle(provider: OAuthProvider) { + return PROVIDER_DISPLAY[provider.id]?.title ?? provider.name +} + +function sortProviders(providers: OAuthProvider[]) { + return [...providers].sort((a, b) => { + const aOrder = PROVIDER_DISPLAY[a.id]?.order ?? 99 + const bOrder = PROVIDER_DISPLAY[b.id]?.order ?? 99 + + if (aOrder !== bOrder) { + return aOrder - bOrder + } + + return a.name.localeCompare(b.name) + }) +} + export function DesktopOnboardingOverlay({ enabled, onCompleted, @@ -161,8 +191,9 @@ export function DesktopOnboardingOverlay({ return } - setOauthProviders(providers.providers) - setMode(providers.providers.length > 0 ? 'oauth' : 'apikey') + const ordered = sortProviders(providers.providers) + setOauthProviders(ordered) + setMode(ordered.length > 0 ? 'oauth' : 'apikey') } catch { if (!cancelledRef.current) { setOauthProviders([]) @@ -460,26 +491,34 @@ function ProviderPicker({ return ( <> {hasOauth && ( -
+
)} @@ -569,6 +608,7 @@ function ProviderRow({ }) { const isExternal = provider.flow === 'external' const loggedIn = provider.status?.logged_in + const title = displayProviderTitle(provider) return ( ) } -function flowSubtitle(flow: OAuthProvider['flow']) { +function flowSubtitle(flow: OAuthProvider['flow'], _title: string) { if (flow === 'pkce') { - return 'Opens your browser, asks you to paste a one-time code back here.' + return 'Opens your browser to sign in, then continues here.' } if (flow === 'device_code') { return 'Opens a verification page in your browser. Hermes connects automatically.' } - return '' + return 'Sign in once in your terminal, then come back to chat.' } interface FlowPanelProps { @@ -619,11 +661,13 @@ interface FlowPanelProps { } function FlowPanel({ flow, onCancel, onCopyCode, onSubmitCode, onSubmitCodeChange }: FlowPanelProps) { + const providerTitle = flow.provider ? displayProviderTitle(flow.provider) : '' + if (flow.status === 'starting') { return (
- Starting sign-in for {flow.provider?.name}... + Starting sign-in for {providerTitle}...
) } @@ -632,7 +676,7 @@ function FlowPanel({ flow, onCancel, onCopyCode, onSubmitCode, onSubmitCodeChang return (
- Verifying your code with {flow.provider?.name}... + Verifying your code with {providerTitle}...
) } @@ -641,7 +685,7 @@ function FlowPanel({ flow, onCancel, onCopyCode, onSubmitCode, onSubmitCodeChang return (
- {flow.provider?.name} connected. You're ready to chat. + {providerTitle} connected. You're ready to chat.
) } @@ -665,9 +709,9 @@ function FlowPanel({ flow, onCancel, onCopyCode, onSubmitCode, onSubmitCodeChang return (
-

Sign in with {flow.provider.name}

+

Sign in with {providerTitle}

    -
  1. We opened {flow.provider.name} in your browser.
  2. +
  3. We opened {providerTitle} in your browser.
  4. Authorize Hermes there.
  5. Copy the authorization code and paste it below.
@@ -707,9 +751,9 @@ function FlowPanel({ flow, onCancel, onCopyCode, onSubmitCode, onSubmitCodeChang return (
-

Sign in with {flow.provider.name}

+

Sign in with {providerTitle}

- We opened {flow.provider.name} in your browser. Enter this code there: + We opened {providerTitle} in your browser. Enter this code there: