diff --git a/apps/x/apps/renderer/src/components/onboarding-modal.tsx b/apps/x/apps/renderer/src/components/onboarding-modal.tsx index 9060a669..3528d1ee 100644 --- a/apps/x/apps/renderer/src/components/onboarding-modal.tsx +++ b/apps/x/apps/renderer/src/components/onboarding-modal.tsx @@ -38,7 +38,9 @@ interface OnboardingModalProps { onComplete: () => void } -type Step = 0 | 1 | 2 +type Step = 0 | 1 | 2 | 3 + +type OnboardingPath = 'rowboat' | 'byok' | null type LlmProviderFlavor = "openai" | "anthropic" | "google" | "openrouter" | "aigateway" | "ollama" | "openai-compatible" @@ -50,6 +52,7 @@ interface LlmModelOption { export function OnboardingModal({ open, onComplete }: OnboardingModalProps) { const [currentStep, setCurrentStep] = useState(0) + const [onboardingPath, setOnboardingPath] = useState(null) // LLM setup state const [llmProvider, setLlmProvider] = useState("openai") @@ -364,7 +367,7 @@ export function OnboardingModal({ open, onComplete }: OnboardingModalProps) { }, []) const handleNext = () => { - if (currentStep < 2) { + if (currentStep < 3) { setCurrentStep((prev) => (prev + 1) as Step) } } @@ -481,7 +484,20 @@ export function OnboardingModal({ open, onComplete }: OnboardingModalProps) { return cleanup }, []) - // Listen for Composio connection events (Gmail) + // Auto-advance from Rowboat sign-in step when OAuth completes + useEffect(() => { + if (onboardingPath !== 'rowboat' || currentStep !== 1) return + + const cleanup = window.ipc.on('oauth:didConnect', (event) => { + if (event.provider === 'rowboat' && event.success) { + setCurrentStep(2 as Step) + } + }) + + return cleanup + }, [onboardingPath, currentStep]) + + // Listen for Composio connection events useEffect(() => { const cleanup = window.ipc.on('composio:didConnect', (event) => { const { toolkitSlug, success, error } = event @@ -555,7 +571,7 @@ export function OnboardingModal({ open, onComplete }: OnboardingModalProps) { // Step indicator const renderStepIndicator = () => (
- {[0, 1, 2].map((step) => ( + {[0, 1, 2, 3].map((step) => (
) - // Step 0: LLM Setup + // Step 0: Path Choice (Rowboat vs BYOK) + const renderPathChoiceStep = () => ( +
+
+ Your AI coworker, with memory +
+ + Get Started + + Choose how you'd like to set up Rowboat + + + +
+ + + +
+
+ ) + + // Step 1 (Rowboat path): Sign in to Rowboat + const renderRowboatSignInStep = () => { + const rowboatState = providerStates['rowboat'] || { isConnected: false, isLoading: false, isConnecting: false } + + return ( +
+ + Sign in to Rowboat + + Connect your Rowboat account for instant access to all models through our gateway — no API keys needed. + + + + {rowboatState.isConnected ? ( +
+
+ + Connected to Rowboat +
+ +
+ ) : ( +
+ + {rowboatState.isConnecting && ( +

+ Complete sign in in your browser, then return here. +

+ )} +
+ )} +
+ ) + } + + // Step 1 (BYOK path): LLM Setup const renderLlmSetupStep = () => { const primaryProviders: Array<{ id: LlmProviderFlavor; name: string; description: string }> = [ { id: "openai", name: "OpenAI", description: "Use your OpenAI API key" }, @@ -1117,9 +1224,11 @@ export function OnboardingModal({ open, onComplete }: OnboardingModalProps) { onEscapeKeyDown={(e) => e.preventDefault()} > {renderStepIndicator()} - {currentStep === 0 && renderLlmSetupStep()} - {currentStep === 1 && renderAccountConnectionStep()} - {currentStep === 2 && renderCompletionStep()} + {currentStep === 0 && renderPathChoiceStep()} + {currentStep === 1 && onboardingPath === 'rowboat' && renderRowboatSignInStep()} + {currentStep === 1 && onboardingPath === 'byok' && renderLlmSetupStep()} + {currentStep === 2 && renderAccountConnectionStep()} + {currentStep === 3 && renderCompletionStep()}