({
onDone,
startingMessage,
mode = 'login',
forceLoginMethod: forceLoginMethodProp
}: Props)
| 52 | }; |
| 53 | const PASTE_HERE_MSG = 'Paste code here if prompted > '; |
| 54 | export function ConsoleOAuthFlow({ |
| 55 | onDone, |
| 56 | startingMessage, |
| 57 | mode = 'login', |
| 58 | forceLoginMethod: forceLoginMethodProp |
| 59 | }: Props): React.ReactNode { |
| 60 | const settings = getSettings_DEPRECATED() || {}; |
| 61 | const forceLoginMethod = forceLoginMethodProp ?? settings.forceLoginMethod; |
| 62 | const orgUUID = settings.forceLoginOrgUUID; |
| 63 | const forcedMethodMessage = forceLoginMethod === 'claudeai' ? 'Login method pre-selected: Subscription Plan (Claude Pro/Max)' : forceLoginMethod === 'console' ? 'Login method pre-selected: API Usage Billing (Anthropic Console)' : null; |
| 64 | const terminal = useTerminalNotification(); |
| 65 | const [oauthStatus, setOAuthStatus] = useState<OAuthStatus>(() => { |
| 66 | if (mode === 'setup-token') { |
| 67 | return { |
| 68 | state: 'ready_to_start' |
| 69 | }; |
| 70 | } |
| 71 | if (forceLoginMethod === 'claudeai' || forceLoginMethod === 'console') { |
| 72 | return { |
| 73 | state: 'ready_to_start' |
| 74 | }; |
| 75 | } |
| 76 | return { |
| 77 | state: 'idle' |
| 78 | }; |
| 79 | }); |
| 80 | const [pastedCode, setPastedCode] = useState(''); |
| 81 | const [cursorOffset, setCursorOffset] = useState(0); |
| 82 | const [oauthService] = useState(() => new OAuthService()); |
| 83 | const [loginWithClaudeAi, setLoginWithClaudeAi] = useState(() => { |
| 84 | // Use Claude AI auth for setup-token mode to support user:inference scope |
| 85 | return mode === 'setup-token' || forceLoginMethod === 'claudeai'; |
| 86 | }); |
| 87 | // After a few seconds we suggest the user to copy/paste url if the |
| 88 | // browser did not open automatically. In this flow we expect the user to |
| 89 | // copy the code from the browser and paste it in the terminal |
| 90 | const [showPastePrompt, setShowPastePrompt] = useState(false); |
| 91 | const [urlCopied, setUrlCopied] = useState(false); |
| 92 | const textInputColumns = useTerminalSize().columns - PASTE_HERE_MSG.length - 1; |
| 93 | |
| 94 | // Log forced login method on mount |
| 95 | useEffect(() => { |
| 96 | if (forceLoginMethod === 'claudeai') { |
| 97 | logEvent('tengu_oauth_claudeai_forced', {}); |
| 98 | } else if (forceLoginMethod === 'console') { |
| 99 | logEvent('tengu_oauth_console_forced', {}); |
| 100 | } |
| 101 | }, [forceLoginMethod]); |
| 102 | |
| 103 | // Retry logic |
| 104 | useEffect(() => { |
| 105 | if (oauthStatus.state === 'about_to_retry') { |
| 106 | const timer = setTimeout(setOAuthStatus, 1000, oauthStatus.nextState); |
| 107 | return () => clearTimeout(timer); |
| 108 | } |
| 109 | }, [oauthStatus]); |
| 110 | |
| 111 | // Handle Enter to continue on success state |
nothing calls this directly
no test coverage detected