From 05de1c4e8afb220c72a6af80086498f4b480c515 Mon Sep 17 00:00:00 2001 From: Steven Enamakel <31011319+senamakel@users.noreply.github.com> Date: Fri, 15 May 2026 19:28:51 -0700 Subject: [PATCH] feat: redesign onboarding, boot, and LLM settings end-to-end (#1885) --- app/src/App.tsx | 6 +- app/src/components/AppBackground.tsx | 20 + .../BootCheckGate/BootCheckGate.tsx | 127 +- .../__tests__/BootCheckGate.test.tsx | 107 +- app/src/components/BottomTabBar.tsx | 18 +- app/src/components/LanguageSelect.tsx | 47 + app/src/components/settings/SettingsHome.tsx | 191 +-- .../settings/__tests__/SettingsHome.test.tsx | 172 +- .../components/settings/panels/AIPanel.tsx | 1483 +++++++++-------- .../settings/panels/ComposioPanel.tsx | 60 +- .../settings/panels/DeveloperOptionsPanel.tsx | 145 +- .../settings/panels/MemoryDataPanel.tsx | 24 +- .../components/settings/panels/ToolsPanel.tsx | 24 +- .../components/settings/panels/VoicePanel.tsx | 24 +- .../panels/__tests__/AIPanel.test.tsx | 27 +- .../panels/__tests__/ComposioPanel.test.tsx | 8 +- .../__tests__/DeveloperOptionsPanel.test.tsx | 8 + .../__tests__/RecoveryPhrasePanel.test.tsx | 2 - .../panels/__tests__/VoicePanel.test.tsx | 2 +- app/src/index.css | 12 +- app/src/lib/i18n/I18nContext.tsx | 2 +- app/src/lib/i18n/en.ts | 205 ++- app/src/lib/i18n/zh-CN.ts | 3 +- app/src/pages/Intelligence.tsx | 2 +- app/src/pages/Welcome.tsx | 165 +- app/src/pages/__tests__/Home.test.tsx | 1 - app/src/pages/__tests__/Welcome.test.tsx | 433 +---- app/src/pages/onboarding/Onboarding.tsx | 40 +- .../pages/onboarding/OnboardingContext.tsx | 9 + app/src/pages/onboarding/OnboardingLayout.tsx | 2 +- .../onboarding/components/BetaBanner.tsx | 6 +- .../components/ConfigureLaterCallout.tsx | 29 + .../onboarding/components/WizardStepper.tsx | 91 + app/src/pages/onboarding/customWizardSteps.ts | 30 + .../pages/onboarding/pages/ApiKeysPage.tsx | 20 + .../onboarding/pages/CustomInferencePage.tsx | 63 + .../onboarding/pages/CustomMemoryPage.tsx | 59 + .../onboarding/pages/CustomOAuthPage.tsx | 63 + .../onboarding/pages/CustomSearchPage.tsx | 52 + .../onboarding/pages/CustomVoicePage.tsx | 63 + .../onboarding/pages/RuntimeChoicePage.tsx | 32 + .../pages/onboarding/pages/WelcomePage.tsx | 2 +- .../pages/onboarding/steps/ApiKeysStep.tsx | 122 ++ .../onboarding/steps/CustomWizardStep.tsx | 156 ++ .../onboarding/steps/RuntimeChoiceStep.tsx | 167 ++ app/src/services/api/aiSettingsApi.ts | 156 ++ app/src/test/test-utils.tsx | 2 + app/src/types/accounts.ts | 16 +- 48 files changed, 2625 insertions(+), 1873 deletions(-) create mode 100644 app/src/components/AppBackground.tsx create mode 100644 app/src/components/LanguageSelect.tsx create mode 100644 app/src/pages/onboarding/components/ConfigureLaterCallout.tsx create mode 100644 app/src/pages/onboarding/components/WizardStepper.tsx create mode 100644 app/src/pages/onboarding/customWizardSteps.ts create mode 100644 app/src/pages/onboarding/pages/ApiKeysPage.tsx create mode 100644 app/src/pages/onboarding/pages/CustomInferencePage.tsx create mode 100644 app/src/pages/onboarding/pages/CustomMemoryPage.tsx create mode 100644 app/src/pages/onboarding/pages/CustomOAuthPage.tsx create mode 100644 app/src/pages/onboarding/pages/CustomSearchPage.tsx create mode 100644 app/src/pages/onboarding/pages/CustomVoicePage.tsx create mode 100644 app/src/pages/onboarding/pages/RuntimeChoicePage.tsx create mode 100644 app/src/pages/onboarding/steps/ApiKeysStep.tsx create mode 100644 app/src/pages/onboarding/steps/CustomWizardStep.tsx create mode 100644 app/src/pages/onboarding/steps/RuntimeChoiceStep.tsx diff --git a/app/src/App.tsx b/app/src/App.tsx index 9387b847e..53f7f6694 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -5,6 +5,7 @@ import { HashRouter as Router, useLocation, useNavigate } from 'react-router-dom import { PersistGate } from 'redux-persist/integration/react'; import AppRoutes from './AppRoutes'; +import AppBackground from './components/AppBackground'; import AppUpdatePrompt from './components/AppUpdatePrompt'; import BootCheckGate from './components/BootCheckGate/BootCheckGate'; import BottomTabBar from './components/BottomTabBar'; @@ -13,7 +14,6 @@ import ServiceBlockingGate from './components/daemon/ServiceBlockingGate'; import DictationHotkeyManager from './components/DictationHotkeyManager'; import ErrorFallbackScreen from './components/ErrorFallbackScreen'; import LocalAIDownloadSnackbar from './components/LocalAIDownloadSnackbar'; -import MeshGradient from './components/MeshGradient'; import OpenhumanLinkModal from './components/OpenhumanLinkModal'; import PersistRehydrationScreen from './components/PersistRehydrationScreen'; import GlobalUpsellBanner from './components/upsell/GlobalUpsellBanner'; @@ -181,8 +181,8 @@ function AppShell() { return (
+
{isDesktop ? t('bootCheck.desktopDescription') : t('bootCheck.webDescription')}
{!isDesktop && (OPENHUMAN_CORE_TOKEN)
{tokenError}
} -+ {tokenError &&
{tokenError}
} +
{t('bootCheck.storedLocally')} Authorization: Bearer … on every RPC.
{t('bootCheck.checkingCore')}
+ +{t('bootCheck.checkingCore')}
+
{result.reason || t('bootCheck.cannotReachDesc')}
- {actionError &&{actionError}
} + {actionError &&{actionError}
}{t('bootCheck.legacyDescription')}
- {actionError &&{actionError}
} +{t('bootCheck.legacyDescription')}
+ {actionError &&{actionError}
}{t('bootCheck.localNeedsRestartDesc')}
- {actionError &&{actionError}
} +{t('bootCheck.localNeedsRestartDesc')}
+ {actionError &&{actionError}
}{t('bootCheck.cloudNeedsUpdateDesc')}
- {actionError &&{actionError}
} +{t('bootCheck.cloudNeedsUpdateDesc')}
+ {actionError &&{actionError}
}{t('bootCheck.versionCheckFailedDesc')}
- {actionError &&{actionError}
} +{t('bootCheck.versionCheckFailedDesc')}
+ {actionError &&{actionError}
}+ Paste your API key. It's stored encrypted on this device only. +
+{error}
: null} + {success && !error ? ( +{success}
+ ) : null} +{workload.label}
++ Connect the language-model backends you want OpenHuman to use. Toggle a provider on to + add its key; toggle off to disconnect. +
- {ollama.snapshot?.presets?.recommended_tier - ? `Recommended for this device: ${ollama.snapshot.presets.recommended_tier}.` - : 'Pick a tier preset to install a default model.'} -
-+ Pick how each workload is served. Default uses OpenHuman; Custom lets you point a + workload at a specific provider and model. +
+Loading…
Composio powers integrations with Gmail, Notion, Slack, GitHub, and 1000+ other apps. By - default OpenHuman proxies these calls through the TinyHumans backend so you don't - need to manage an API key. If you prefer to use your own Composio account directly, switch - to Direct mode and paste your key below. + default OpenHuman manages it for you, so you don't need to bring an API key. If you + prefer to use your own Composio account directly, switch to{' '} + Direct mode and paste your key below.
{/* Mode toggle */} @@ -229,16 +239,16 @@ const ComposioPanel = () => { value="backend" checked={mode === 'backend'} onChange={() => setMode('backend')} - aria-label="Backend (proxied through TinyHumans)" + aria-label="Managed (OpenHuman handles it for you)" className="mt-1" />- Default. Calls go through api.tinyhumans.ai. - Trigger webhooks (real-time Gmail / Slack events) work out of the box. + Default. OpenHuman manages the Composio connection for you. Trigger webhooks + (real-time Gmail / Slack events) work out of the box.
Find your key at app.composio.dev/api-keys. The key - is stored encrypted on this device and is never sent to TinyHumans servers. + is stored encrypted on this device and is never sent to OpenHuman.
{Your existing integrations (Gmail, Slack, GitHub, etc. linked through OpenHuman){' '} - won't be visible — they live in - TinyHumans' Composio tenant. + won't be visible — they live in the + OpenHuman-managed Composio tenant.
You'll need:
{t('settings.tools.chooseCapabilities')}
{rpcUrlError}
- ) : saveSuccess ? ( -URL saved successfully.
- ) : null} -+ {t('onboarding.custom.configureLater')} +
+
+ {t('onboarding.custom.openSettings')}:{' '}
+ {settingsHref}
+
{t('onboarding.apiKeys.subtitle')}
+{error}
: null} +{subtitle}
+ ++ {t('onboarding.runtimeChoice.subtitle')} +
+