From 6ecae1bbd19ef7f4a1d5e783266ff0e45c3af99c Mon Sep 17 00:00:00 2001 From: Innei Date: Wed, 1 Apr 2026 19:38:14 +0800 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor:=20gate=20agent?= =?UTF-8?q?=20onboarding=20with=20dedicated=20business=20flag=20(#13472)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ♻️ refactor: gate agent onboarding with dedicated business flag Made-with: Cursor * 🗑️ chore(migrations): remove agent onboarding column from users table Signed-off-by: Innei * ✨ feat(onboarding): enable agent onboarding based on environment and add redirect to classic onboarding - Updated AGENT_ONBOARDING_ENABLED to be true in development mode. - Introduced RedirectToClassicOnboarding component to handle navigation to classic onboarding. - Simplified ClassicOnboardingPage by removing the mode switch button for non-development environments. - Adjusted OnBoardingContainer to conditionally render the skip onboarding button based on the current route. This change enhances the onboarding experience by ensuring that the agent onboarding feature is only available in development, while also improving navigation for users. Signed-off-by: Innei * 🐛 fix(test): inline emoji-mart and @lobehub/* deps in Vitest to fix ESM JSON import error Widen server.deps.inline to include `emoji-mart` and all `@lobehub/*` packages so their transitive `@emoji-mart/data` import (a .json main entry) goes through Vite's transform pipeline instead of Node's native ESM loader, which requires `with { type: "json" }`. --------- Signed-off-by: Innei --- packages/business/const/src/index.ts | 4 +++ .../migrations/0095_add_agent_onboarding.sql | 1 - src/features/Onboarding/Agent/index.tsx | 26 ++++++++++++------- src/features/Onboarding/Classic/index.tsx | 15 ++--------- src/routes/onboarding/_layout/index.test.tsx | 13 ++++++++++ src/routes/onboarding/_layout/index.tsx | 12 ++++++--- src/routes/onboarding/config.ts | 7 ++--- vitest.config.mts | 2 ++ 8 files changed, 48 insertions(+), 32 deletions(-) delete mode 100644 packages/database/migrations/0095_add_agent_onboarding.sql diff --git a/packages/business/const/src/index.ts b/packages/business/const/src/index.ts index bafd6f0879..b8deaee795 100644 --- a/packages/business/const/src/index.ts +++ b/packages/business/const/src/index.ts @@ -3,4 +3,8 @@ export * from './branding'; export * from './llm'; export * from './url'; +const isDev = process.env.NODE_ENV === 'development'; + export const ENABLE_BUSINESS_FEATURES = false; + +export const AGENT_ONBOARDING_ENABLED = isDev; diff --git a/packages/database/migrations/0095_add_agent_onboarding.sql b/packages/database/migrations/0095_add_agent_onboarding.sql deleted file mode 100644 index 399557e7af..0000000000 --- a/packages/database/migrations/0095_add_agent_onboarding.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE "users" ADD COLUMN IF NOT EXISTS "agent_onboarding" jsonb; diff --git a/src/features/Onboarding/Agent/index.tsx b/src/features/Onboarding/Agent/index.tsx index f044e7b088..9e9a1d0e53 100644 --- a/src/features/Onboarding/Agent/index.tsx +++ b/src/features/Onboarding/Agent/index.tsx @@ -2,11 +2,12 @@ import { BUILTIN_AGENT_SLUGS } from '@lobechat/builtin-agents'; import { SESSION_CHAT_URL } from '@lobechat/const'; -import { Button, ErrorBoundary, Flexbox, Text } from '@lobehub/ui'; +import { Button, ErrorBoundary, Flexbox } from '@lobehub/ui'; import { Drawer } from 'antd'; import { History } from 'lucide-react'; -import { memo, useMemo, useState } from 'react'; +import { memo, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { useNavigate } from 'react-router-dom'; import Loading from '@/components/Loading/BrandTextLoading'; import ModeSwitch from '@/features/Onboarding/components/ModeSwitch'; @@ -25,6 +26,19 @@ import AgentOnboardingDebugExportButton from './DebugExportButton'; import HistoryPanel from './HistoryPanel'; import OnboardingConversationProvider from './OnboardingConversationProvider'; +const CLASSIC_ONBOARDING_PATH = '/onboarding/classic'; + +const RedirectToClassicOnboarding = memo(() => { + const navigate = useNavigate(); + + useEffect(() => { + navigate(CLASSIC_ONBOARDING_PATH, { replace: true }); + }, [navigate]); + + return ; +}); +RedirectToClassicOnboarding.displayName = 'RedirectToClassicOnboarding'; + const AgentOnboardingPage = memo(() => { const { t } = useTranslation('onboarding'); const useInitBuiltinAgent = useAgentStore((s) => s.useInitBuiltinAgent); @@ -89,13 +103,7 @@ const AgentOnboardingPage = memo(() => { if (error) { return ( - - - - Failed to initialize onboarding. - - - + ); } diff --git a/src/features/Onboarding/Classic/index.tsx b/src/features/Onboarding/Classic/index.tsx index b30c446c8b..ea29c95e49 100644 --- a/src/features/Onboarding/Classic/index.tsx +++ b/src/features/Onboarding/Classic/index.tsx @@ -1,9 +1,8 @@ 'use client'; import { MAX_ONBOARDING_STEPS } from '@lobechat/types'; -import { Button, Flexbox } from '@lobehub/ui'; +import { Flexbox } from '@lobehub/ui'; import { memo, useState } from 'react'; -import { useTranslation } from 'react-i18next'; import Loading from '@/components/Loading/BrandTextLoading'; import ModeSwitch from '@/features/Onboarding/components/ModeSwitch'; @@ -15,10 +14,8 @@ import ResponseLanguageStep from '@/routes/onboarding/features/ResponseLanguageS import TelemetryStep from '@/routes/onboarding/features/TelemetryStep'; import { useUserStore } from '@/store/user'; import { onboardingSelectors } from '@/store/user/selectors'; -import { isDev } from '@/utils/env'; const ClassicOnboardingPage = memo(() => { - const { t } = useTranslation('onboarding'); const [isUserStateInit, currentStep, goToNextStep, goToPreviousStep, resetOnboarding] = useUserStore((s) => [ s.isUserStateInit, @@ -69,15 +66,7 @@ const ClassicOnboardingPage = memo(() => { return ( - - {t('agent.modeSwitch.reset')} - - ) : undefined - } - /> + {renderStep()} diff --git a/src/routes/onboarding/_layout/index.test.tsx b/src/routes/onboarding/_layout/index.test.tsx index 656cec3975..8907c828ee 100644 --- a/src/routes/onboarding/_layout/index.test.tsx +++ b/src/routes/onboarding/_layout/index.test.tsx @@ -29,6 +29,19 @@ describe('OnBoardingContainer', () => { expect(screen.getByText('Lang Button')).toBeInTheDocument(); expect(screen.getByText('Theme Button')).toBeInTheDocument(); expect(screen.getByText('Onboarding Content')).toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'agent.skipOnboarding' })).not.toBeInTheDocument(); expect(screen.queryByText('© 2026 LobeHub. All rights reserved.')).not.toBeInTheDocument(); }); + + it('shows skip onboarding on agent onboarding route', () => { + render( + + +
Onboarding Content
+
+
, + ); + + expect(screen.getByRole('button', { name: 'agent.skipOnboarding' })).toBeInTheDocument(); + }); }); diff --git a/src/routes/onboarding/_layout/index.tsx b/src/routes/onboarding/_layout/index.tsx index e995800347..93beba56af 100644 --- a/src/routes/onboarding/_layout/index.tsx +++ b/src/routes/onboarding/_layout/index.tsx @@ -5,7 +5,7 @@ import { Divider } from 'antd'; import { cx, useTheme } from 'antd-style'; import { type FC, type PropsWithChildren, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import { ProductLogo } from '@/components/Branding'; import LangButton from '@/features/User/UserPanel/LangButton'; @@ -19,8 +19,10 @@ const OnBoardingContainer: FC = ({ children }) => { const isDarkMode = useIsDark(); const theme = useTheme(); const { t } = useTranslation('onboarding'); + const { pathname } = useLocation(); const navigate = useNavigate(); const finishOnboarding = useUserStore((s) => s.finishOnboarding); + const isAgentOnboarding = pathname.startsWith('/onboarding/agent'); const handleSkip = useCallback(() => { finishOnboarding(); @@ -49,9 +51,11 @@ const OnBoardingContainer: FC = ({ children }) => { - + {isAgentOnboarding ? ( + + ) : null}
diff --git a/src/routes/onboarding/config.ts b/src/routes/onboarding/config.ts index fdfa1a8f14..a08c85f1f4 100644 --- a/src/routes/onboarding/config.ts +++ b/src/routes/onboarding/config.ts @@ -1,5 +1,4 @@ -import { ENABLE_BUSINESS_FEATURES } from '@lobechat/business-const'; -import { isDev } from '@lobechat/utils'; +import { AGENT_ONBOARDING_ENABLED } from '@lobechat/business-const'; import { ChartNetworkIcon, CodeXmlIcon, @@ -13,11 +12,9 @@ import { /** Default target when the user opens `/onboarding`. Flip to `'agent'` when agent onboarding is ready to ship as the primary flow. */ export type DefaultOnboardingEntryVariant = 'agent' | 'classic'; - +export { AGENT_ONBOARDING_ENABLED }; export const DEFAULT_ONBOARDING_ENTRY_VARIANT: DefaultOnboardingEntryVariant = 'classic'; -export const AGENT_ONBOARDING_ENABLED = ENABLE_BUSINESS_FEATURES || isDev; - const resolveDefaultOnboardingPath = (variant: DefaultOnboardingEntryVariant) => variant === 'agent' && AGENT_ONBOARDING_ENABLED ? '/onboarding/agent' : '/onboarding/classic'; diff --git a/vitest.config.mts b/vitest.config.mts index bdf3fbc7f1..fbf9b00c9a 100644 --- a/vitest.config.mts +++ b/vitest.config.mts @@ -113,6 +113,7 @@ export default defineConfig({ inline: [ 'vitest-canvas-mock', /@emoji-mart/, + 'emoji-mart', '@lobehub/ui', '@lobehub/fluent-emoji', '@pierre/diffs', @@ -120,6 +121,7 @@ export default defineConfig({ 'lru_map', 'lexical', /@lexical\//, + /@lobehub\//, ], }, },