import * as React from "react"; import type { QueryClient } from "@tanstack/react-query"; import { getGlobalAgentConfig, setGlobalAgentConfig, } from "@/shared/api/tauriGlobalAgentConfig"; import { getIdentity, importIdentity, persistCurrentIdentity, } from "@/shared/api/tauriIdentity"; import { Button } from "@/shared/ui/button"; import { StartupWindowDragRegion } from "@/shared/ui/StartupWindowDragRegion"; import { BackupStep } from "./BackupStep"; import { DefaultConfigStep } from "./DefaultConfigStep"; import { LandingBees } from "./LandingBees"; import { NostrKeyImportForm } from "./NostrKeyImportForm"; import { ONBOARDING_LANDING_CTA_CLASS, OnboardingChrome, } from "./OnboardingChrome"; import { OnboardingFooterProvider } from "./OnboardingFooter"; import { OnboardingSlideTransition } from "./OnboardingSlideTransition"; import { SetupStep } from "./SetupStep"; type MachinePage = "identity" | "key-import" | "backup" | "setup" | "config"; export function MachineOnboardingFlow({ complete, identityLost, queryClient, }: { complete: (pubkey?: string) => void; identityLost: boolean; queryClient: QueryClient; }) { const [page, setPage] = React.useState( identityLost ? "key-import" : "identity", ); const [error, setError] = React.useState(null); const [isPending, setIsPending] = React.useState(false); const [identityWasImported, setIdentityWasImported] = React.useState(false); const [selectedPubkey, setSelectedPubkey] = React.useState( null, ); const [selectedRuntimeId, setSelectedRuntimeId] = React.useState< string | null >(null); const [pendingRuntimeId, setPendingRuntimeId] = React.useState( null, ); const [isRuntimeSelectionSaving, setIsRuntimeSelectionSaving] = React.useState(false); const [runtimeSelectionError, setRuntimeSelectionError] = React.useState< string | null >(null); const runtimeSaveSequence = React.useRef(0); const persistPreferredRuntime = React.useCallback( async (runtimeId: string) => { const sequence = runtimeSaveSequence.current + 1; runtimeSaveSequence.current = sequence; setPendingRuntimeId(runtimeId); setRuntimeSelectionError(null); setIsRuntimeSelectionSaving(true); try { const current = await getGlobalAgentConfig(); const result = await setGlobalAgentConfig({ ...current, preferred_runtime: runtimeId, }); if (runtimeSaveSequence.current === sequence) { setSelectedRuntimeId(result.config.preferred_runtime); setPendingRuntimeId(null); } } catch (cause) { if (runtimeSaveSequence.current === sequence) { setPendingRuntimeId(null); setRuntimeSelectionError( cause instanceof Error ? cause.message : "Couldn’t save your preferred runtime.", ); } } finally { if (runtimeSaveSequence.current === sequence) { setIsRuntimeSelectionSaving(false); } } }, [], ); const loadFreshIdentity = React.useCallback(async () => { setIsPending(true); setError(null); try { const identity = await getIdentity(); queryClient.setQueryData(["identity"], identity); setSelectedPubkey(identity.pubkey); setPage("backup"); } catch (cause) { setError( cause instanceof Error ? cause.message : "Failed to load identity", ); } finally { setIsPending(false); } }, [queryClient]); const replaceLostIdentity = React.useCallback(async () => { const confirmed = window.confirm( "This will create a new identity and abandon your previous key. This cannot be undone. Continue?", ); if (!confirmed) return; setIsPending(true); setError(null); try { const identity = await persistCurrentIdentity(); queryClient.setQueryData(["identity"], identity); setSelectedPubkey(identity.pubkey); setPage("backup"); } catch (cause) { setError( cause instanceof Error ? cause.message : "Failed to save identity", ); } finally { setIsPending(false); } }, [queryClient]); const importExistingIdentity = React.useCallback( async (nsec: string) => { const identity = await importIdentity(nsec); queryClient.setQueryData(["identity"], identity); setIdentityWasImported(true); setSelectedPubkey(identity.pubkey); setPage("setup"); }, [queryClient], ); return (
{page === "identity" ? : null} {page !== "identity" ? ( ) : null}
{page === "identity" ? ( Buzz

Your people, your agents, your projects —
all in one place.

{error ? (

{error}

) : null}
) : page === "key-import" ? (

{identityLost ? "Re-import your key" : "Enter your private key"}

{identityLost ? "Your identity is no longer in the system keyring. Re-import your nsec to restore it." : "If you already have a Nostr account, enter your private key below to get started."}

void replaceLostIdentity() : () => setPage("identity") } onImport={importExistingIdentity} variant="spotlight" />
) : page === "backup" ? ( setPage("identity")} onNext={() => setPage("setup")} /> ) : page === "setup" ? ( setPage(identityWasImported ? "key-import" : "backup"), next: () => { if (!selectedRuntimeId) return; if ( selectedRuntimeId === "claude" || selectedRuntimeId === "codex" ) { complete(selectedPubkey ?? undefined); return; } setPage("config"); }, }} direction="forward" isSelectionSaving={isRuntimeSelectionSaving} onSelectedRuntimeChange={(runtimeId) => { void persistPreferredRuntime(runtimeId); }} selectionError={runtimeSelectionError} selectedRuntimeId={pendingRuntimeId ?? selectedRuntimeId} /> ) : ( setPage("setup"), complete: () => complete(selectedPubkey ?? undefined), }} direction="forward" /> )}
); }