♻️ refactor(onboarding): extract language and privacy as shared prefix steps#14538
Conversation
…x steps Move the language-selection and privacy/telemetry consent out of the classic flow into a shared prefix that runs at /onboarding before branching into either the agent or classic experience. Welcome decoration is merged with language selection on a single screen, dropping the total step count by one. Shared-prefix completion is derived from raw stored settings (s.settings.general.responseLanguage and telemetry), so no new schema fields are introduced and existing consumers that rely on the merged-default telemetry value are unaffected. Branch routing remains automatic (feature flag + isDesktop check) and is now encapsulated in deriveOnboardingBranchPath. Both branch routes guard against entering before the shared prefix is complete. MAX_ONBOARDING_STEPS drops from 5 to 3 (FullName, Interests, ProSettings).
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a01e52fa19
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| case 2: { | ||
| return <InterestsStep onBack={goToPreviousStep} onNext={goToNextStep} />; | ||
| } |
There was a problem hiding this comment.
Remap legacy classic step numbers before rendering
This renumbering makes persisted onboarding.currentStep values from the old 5-step classic flow point to the wrong screens: a user previously on old step 2 (FullName) now lands on step 2 (Interests), and old step 3 now lands on ProSettings. Because no migration/remap is applied for in-progress users, they can skip required profile steps after completing the shared prefix. Please translate legacy step values (e.g., old 2->1, 3->2, >=4->3) before this switch is evaluated.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in commit e3df96c. Added a one-time idempotent remap on Common's mount (2→1, 3→2, ≥4→MAX), gated by isUserStateInit && !onboarding.finishedAt so it fires only for in-flight legacy users; finished users and fresh users are untouched. Covered by 6 new test cases in src/features/Onboarding/Common/index.test.tsx.
The remap lives in the shared-prefix mount rather than inside the Classic switch because the Classic-side approach would either (a) flash the wrong step before correcting, or (b) conflict with normal forward navigation in the new flow (e.g., new step 2 = Interests would be remapped to 1).
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## canary #14538 +/- ##
==========================================
- Coverage 68.64% 68.63% -0.01%
==========================================
Files 2623 2624 +1
Lines 230163 230218 +55
Branches 29087 24296 -4791
==========================================
+ Hits 157996 158014 +18
- Misses 72018 72054 +36
- Partials 149 150 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
… shared steps Revert the merged welcome+language design. The shared prefix now reuses the original two classic steps as-is: - Step 1: TelemetryStep (welcome decoration + privacy/telemetry consent) - Step 2: ResponseLanguageStep (language selection) Also suppress the mode-switch + skip footer on the bare /onboarding path so it only appears once the user has entered the agent or classic branch.
…e-triggered remounts Use react-router's useSearchParams to keep the active shared step in the URL (?step=2). Local useState was lost when switching language for the first time because i18next's first-time resource load triggers a remount up the tree; the URL param survives any remount.
…telemetry Derive commonStepsCompleted from responseLanguage alone. setSettings strips fields whose value matches DEFAULT_COMMON_SETTINGS, so accepting the default telemetry: true left s.settings.general.telemetry undefined and the derive selector never flipped to true — the redirect to the branch never fired. Step 2 (language) implies step 1 was completed because the flow is sequential, so checking responseLanguage alone is sufficient and robust against the default-strip behavior.
…responseLanguage only setSettings strips fields that match defaultSettings, so writing telemetry=true (the default) never persists to s.settings.general. That made commonStepsCompleted permanently false even after the user finished both steps, blocking the redirect to the branch flow. Drop telemetry from the derive check. Step 1 completion is already tracked via the URL ?step=2 marker; step 2 completion is the only event that needs to flip commonStepsCompleted, signalled by writing responseLanguage (which always differs from the default since DEFAULT_COMMON_SETTINGS has no responseLanguage entry).
Takes an email, clears users.onboarding, agent_onboarding, full_name, interests and removes responseLanguage + telemetry from user_settings.general so the user re-enters the shared-prefix onboarding from step 1. Usage: pnpm workflow:reset-onboarding <email> bunx tsx scripts/resetOnboarding/index.ts <email>
…s handling Signed-off-by: Innei <tukon479@gmail.com>
…s in progress useInitUserState's onSuccess callback auto-fills general.responseLanguage from navigator.language whenever the field is missing. For new users this fired immediately after signup, which made commonStepsCompleted (which derives from responseLanguage being set) flip to true on first load, and CommonOnboardingPage's early-redirect skipped past the shared prefix straight into /onboarding/agent. Gate the auto-fill on onboarding.finishedAt or agentOnboarding.finishedAt being set, so legacy users who finished onboarding without responseLanguage still get the safety-net detection, but in-progress users keep the field undefined until they explicitly choose it on the language step.
…starts ensureWelcomeMessage previously only created the welcome on first call and skipped on subsequent ones, leaving stale welcomes locked to the locale that was active when the topic was first created. After the shared-prefix refactor users pick their language earlier than they used to, so the welcome that was generated during the auto-detect phase never gets re-translated. Now the welcome content is rewritten in-place to match the current responseLanguage as long as no user reply has been recorded yet (message count <= 1). Once the conversation has started, the welcome is left as part of the chat history.
…ide and avoid persisting during onboarding Signed-off-by: Innei <tukon479@gmail.com>
- Removed responseLanguage from SaveUserQuestionInput and related schemas. - Updated onboarding logic to no longer save or request responseLanguage. - Adjusted related components and services to reflect the removal of responseLanguage. - Enhanced user info handling to include displayName and fullName from OAuth. - Updated tests to align with the new onboarding structure. Signed-off-by: Innei <tukon479@gmail.com>
…anguage Signed-off-by: Innei <tukon479@gmail.com>
…prefix mount Mid-flow legacy users with persisted currentStep authored under the old 5-step classic flow (Telemetry, FullName, Interests, Language, ProSettings) would silently skip required profile steps after the renumbering: old step 2 (FullName) rendered Interests, old step 3 (Interests) rendered ProSettings. Apply a one-time remap (2->1, 3->2, >=4->MAX) when Common mounts, gated by isUserStateInit and onboarding.finishedAt absence so it fires only for in-flight legacy users. Idempotent for new-schema values.
…h for onboarding flow Signed-off-by: Innei <tukon479@gmail.com>
…tests Signed-off-by: Innei <tukon479@gmail.com>
# 🚀 LobeHub Release (20260509) **Release Date:** May 9, 2026 **Since v2.1.56:** 236 merged PRs · 19 contributors > Agent Task System reaches general availability, the Agent Signal pipeline runs nightly self-review with skill-aware policies, the heterogeneous-agent runtime crosses replica boundaries, inline documents become a first-class context source, and bot platforms expand across Messager, Line, and Telegram. --- ## ✨ Highlights - **Agent Task System (GA)** — End-to-end task execution platform: templates, tracking, comment tools, parent reassignment, scheduled cron, and dependency-ordered batch runs. (#14540, #14515, #14517, #14272, #14246, #14418, #14403, #14488) - **Agent Signal nightly self-review** — Wired self-review loop with prompt + DB support, exponential-backoff retry on receipt listing, skill-aware policy, and improved skill-intent detection. (#14543, #14542, #14281, #14409, #14526, #14437) - **Inline documents in KB tool** — BM25 search and `docs_*` read for inline document grounding; agent documents usable as VFS. (#14494, #14222) - **Inline agent cards in chat** — `lobeAgents` markdown tag renders agent profile cards inline; clickable card after `createAgent`. (#14495, #14493) - **Heterogeneous agent runtime** — Cloud hetero exec pipeline steps 3+4 land, persistence recovers across Vercel replicas, server-side ingest/finish handler, and `lh hetero exec` CLI. (#14486, #14539, #14444, #14431) - **Bot platforms expand** — Messager, Line, DM pair policy, and messenger DB tables; Telegram API path restored. (#14442, #14207, #14211, #14496, #14519) - **Visual analysis tool** — New visual understanding tool, with trigger tracking and flattened schema. (#14378, #14399, #14550) - **DeepSeek V4 Pro as OSS default** — OSS deployments ship with DeepSeek V4 Pro by default; DeepSeek Anthropic runtime supported. (#14555, #14312) --- ## 🏗️ Core Agent & Architecture ### Agent Task System - **Task System GA** — End-to-end execution platform now available. (#14540) - **Templates, comments, reparenting** — Template tracking, comment tools, and parent reassignment. (#14515, #14517, #14488) - **Cron + dependency-ordered runs** — Scheduled status with cron editor and dependency-ordered subtask batches. (#14246, #14418, #14272) - **Inspector + chip UI + batch tasks** — Task Inspector/Render registry, batch `createTasks`/`runTasks`, and chip-based agent-documents inspector. (#14403, #14404) - **Recommend templates regardless of brief count** — Recommendations no longer suppressed when briefs are sparse. (#14508) - **Scheduling resilience** — Manual run no longer eats next scheduled tick; recurring tasks survive brief resolution. (#14304, #14348) - **Brief synthesis** — Auto-synthesize topic briefs; brief actions revamp; mute resolved-brief icon on home. (#14324, #14228, #14452) - **Task list & detail polish** — Topic operation ID exposed; task drawer Gateway reconnect. (#14282) ### Agent Signal pipeline - **Nightly self-review wired** — Prompt + DB support for the self-review loop. (#14543) - **Self-review activities push to briefs** — Activities during nightly self-reflection now create briefs. (#14437) - **Skill management policy** — New policy for Skill management running inside Agent Signal. (#14281) - **Skill intent detection & routing** — Improved detection plus direct intent handling when `hintIsSkill`. (#14409, #14526) - **Document tool outcome rendering** — Decision view restores missing document tool outcomes. (#14534) - **Exponential backoff retry** — Listing signal receipts retries with jittered backoff. (#14542) - **Easier-to-use signals** — Structural simplification + recent-activities surface for receipts. (#14290, #14326, #14407) ### Heterogeneous agent runtime - **Cloud hetero exec pipeline (steps 3 + 4)** — Refactor lands the next two stages of the cloud hetero agent execution pipeline. (#14486) - **Persistence recovery on Vercel** — Hetero state recovered across replica boundaries. (#14539) - **Server-side ingest/finish + persistence** — `aiAgent.heteroIngest` / `heteroFinish` handlers. (#14444) - **`lh hetero exec` CLI** — Standalone heterogeneous agent runs from CLI. (#14431) - **Gateway round-trip loading** — `execAgentTask` keeps the input box in loading state through the full round-trip. (#14503) - **Provider SDK type routing** — Provider routing now respects SDK type. (#14520) - **DeepSeek reasoning preserved** — `reasoning_content` preserved in OpenAI-compatible runtime for DeepSeek models. (#14546) ### Knowledge & inline docs - **KB tool BM25 + docs read** — BM25 search and `docs_*` read integrated for inline documents. (#14494) - **Agent documents as VFS** — FS-compatible output for agent documents. (#14222) - **`lobeAgents` markdown tag** — Inline agent cards rendered from a markdown tag. (#14495) - **Clickable agent card after `createAgent`** — Mentions and recommendations become clickable. (#14493) - **ExplorerTree** — Generic tree component built on `@pierre/trees` for reusable explorer surfaces. (#14094) - **Local file mention snapshots** — Mentions can now snapshot local files. (#14278) ### Architecture - **Agent Hono routes** — New agent routes added on Hono. (#14535) - **`/api/agent` migrated to Hono** — Remaining `/api/agent` routes finish their migration. (#14478) - **Agent marketplace merged into web-onboarding** — Reduces package fragmentation. (#14514) - **Producer pipeline extracted** — Shared package for the producer pipeline. (#14425) - **`agentDispatcher.selectRuntimeType`** — New runtime selection abstraction. (#14428) - **pnpm v11 migration** — Workspace consolidated. (#14316) - **Browser-compatible frontmatter parser** — Replaces `gray-matter`. (#14435) --- ## 📱 Platforms & Integrations - **Messager support** — New messager package wired into the chat surface. (#14442) - **Messenger DB tables** — IM bot integration gains its persistence layer. (#14496) - **Line bot** — Initial Line support and downstream optimization. (#14207, #14448) - **DM pair policy** — Group/DM pair-based delivery. (#14211) - **Telegram API restored** — Missing Telegram API path reconnected. (#14519) - **xAI Responses tools stabilized** — Plus unsupported parameter handling. (#14462, #14445) - **Volcengine websearch via ResponseAPI** — Built-in websearch for Volcengine. (#14216) --- ## 🤖 Models & Providers - **DeepSeek V4 Pro default for OSS** — OSS distribution defaults to DeepSeek V4 Pro. (#14555) - **DeepSeek Anthropic runtime** — Anthropic-shape runtime support for DeepSeek. (#14312) - **GPT-5.5 / GPT-5.5 Pro** — New OpenAI tier. (#14142) - **Grok 4.20 / Grok 4.3 / LobeHub-hosted Grok 4.3** — (#14253, #14382, #14446) - **Gemma 4 + provider settings normalization** — (#13313) - **gpt-image-2 + step-image-edit-2** — (#14253, #14329) - **Model bank refresh + original-pricing display** — Batch model updates and pricing surfaces. (#14070, #14391) - **Hunyuan migrated to TokenHub for Hy3 Preview** — (#14108) - **Reject lobehub model ids no longer in the bank** — (#14261) - **Hide runtime-only aliases** — Runtime-only model aliases no longer leak into the model picker. (#14552) --- ## 🖥️ User Experience ### Onboarding - **Shared prefix steps** — Language and privacy extracted as shared prefix steps. (#14538) - **Identity intervention card simplified** — Plus tool result renders cleanup. (#14505, #14506) - **Welcome polish + web-onboarding tool UI** — (#14475) - **Templates fetched from market API** — (#14286) - **Virtual model id for default onboarding model** — (#14311) - **Skip / mode-switch footer behind feature flag** — Footer guarded for desktop and web initialization. (#14560) ### Home & navigation - **Home recents performance** — Recents refresh periodically and inline task status; brief and task-template fetch overhead trimmed. (#14518, #14516) - **Home refactor + skill-connect recommendations** — Restructured home with skill-connect recommendation system. (#14266, #14214) - **Tasks in agent sidebar** — Tasks moved from welcome card into the sidebar list. (#14500) - **Sidebar collapse persists** — Home sidebar collapse state stored. (#14473) - **Agent-specific topic grouping** — Plus improved empty state and agent identity in topic search. (#14225) - **MentionMenu scroll fix** — Mention menu no longer clips inside chat input. (#14533) ### Conversation & chat - **Follow-up chips fill input** — Clicking a follow-up chip now fills the input instead of sending immediately. (#14536) - **Quick-reply chips below assistant messages** — (#14350) - **Inline single-tool assistant group + leading sentence promotion** — (#14244) - **Assistant-group rendering** — Per-segment content overrides flow into MessageContent. (#14504) - **Tool call timer fix** — Timer no longer resets when tool calls collapse or expand. (#14513) - **Streaming re-render reduction** — Reference stabilization and self-subscribing components. (#14470) - **Topic chat drawer feedback input** — (#14392) ### Skills, agents, devtools - **Managed skill folders** — Agent view displays managed skill folders and aligns delete confirmations. (#14553) - **Review tab + bulk git diffs** — New Review tab with bulk diffs; gating uses effective working directory. (#14334, #14512) - **Devtools gallery rebuild** — Plus Review polish, queue-tray images. (#14423) - **Agent mock devtools** — Playback & fixture viewer. (#14436) ### Desktop & CLI - **App tray visibility setting** — (#14463) - **Notification settings in desktop** — (#14491) - **Multimodal input across CLI / shared spawn / desktop** — (#14433) - **CLI bot + userId guide** — (#14258) --- ## 🔧 Tooling - **Visual analysis tool** — New visual understanding tool with flattened schema. (#14378, #14550) - **GitHub marketplace tool UI** — (#14420) - **Drop "Local" prefix and `____builtin` suffix from tool names** — (#14364, #14289) - **Sanitize provider tool names** — Avoids invalid characters from external providers. (#14510) - **Generation moderation context** — Moderation context passed through the generation pipeline. (#14541) - **Visual analysis trigger tracking** — (#14399) - **Claude thinking signature sanitization** — History signatures sanitized when replaying Claude conversations. (#14499) - **Responses input media sanitization** — Assistant media sanitized in Responses input. (#14497) --- ## 🔒 Security & Reliability - **Security:** Removed the `/webapi/proxy` route and dead URL-manifest plugin code to shrink the SSRF surface. (#14549) - **Security:** Sessions revoked after password reset. (#14424) - **Reliability:** Added `prompt_cache_key` to OpenAI chat requests for stable cache hits. (#14349) - **Reliability:** `onFinish` now fires even when the browser tab is backgrounded mid-SSE stream. (#14461) - **Reliability:** Better-auth session refetch preserves user fields rather than overwriting them. (#14531) - **Reliability:** User-memory queries sanitize backticks; user-memory errors now explicitly injected so failures stay visible. (#14524, #14525) - **Reliability:** Auth captcha retries handled; input loading unsticks on `auth_failed` and recoverable `auth_expired`. (#14346, #14419) - **Reliability:** Trace snapshot finalized on error path. (#14440) - **Reliability:** Drop `switchTopic` race under rapid sidebar clicks. (#14115) - **Reliability:** PDF chunking logic fixed to prevent vectorization failure. (#14327) - **Performance:** Marketplace fork uses a batched API for parallel installs. (#14537) - **Performance:** Review tab open latency cut ~9× on large dirty trees. (#14338) --- ## 👥 Contributors Huge thanks to **18 contributors** who shipped **236 merged PRs** this cycle. @hezhijie0327 · @sxjeru · @yueyinqiu · @octo-patch · @hardy-one · @Coooolfan · @CanYuanA · @BillionClaw · @arvinxx · @tjx666 · @Innei · @neko · @AmAzing129 · @rdmclin2 · @lijian · @sudongyuer · @rivertwilight · @cy948 Plus @lobehubbot for i18n and translation maintenance. --- **Full Changelog**: v2.1.56...release/weekly-20260509
💻 Change Type
🔗 Related Issue
N/A
🔀 Description of Change
Extract the language-selection and privacy/telemetry consent out of the classic onboarding flow into a shared prefix that runs at
/onboardingbefore branching into either the agent or classic experience. As follow-up, dropresponseLanguagefrom the agent onboarding profile (single source of truth lives onuser_settings.general.responseLanguage), wire welcome-message rendering to the client, harden several edge cases, and remap legacy mid-flowcurrentStepvalues onto the new schema.Flow
The shared-prefix step is mirrored in the URL (
?step=2) so that locale-triggered remounts during step 2 don't lose the user's place.Persistence (derived, no new schema fields)
Shared-prefix completion is derived from the raw stored settings, bypassing default-merged values:
Telemetry is intentionally not part of the derivation:
setSettingsstrips fields equal toDEFAULT_COMMON_SETTINGS.telemetry === true, so a user accepting the default-on choice never persists telemetry. Existing consumers relying on the merged-defaulttelemetry: trueare unaffected — no type orDEFAULT_COMMON_SETTINGSchanges are required.Routing
Branch selection is encapsulated in
deriveOnboardingBranchPath. Both branch routes (/onboarding/agent,/onboarding/classic) guard against entry before the shared prefix completes and redirect back to/onboardingif not.Step renumbering
MAX_ONBOARDING_STEPSdrops from 5 to 3 — classic flow becomes:Mid-flow legacy users (Codex P1 follow-up)
Users in the middle of the old 5-step classic flow at deploy time would have their persisted
currentSteppoint at the wrong screen under the new numbering — old step 2 (FullName) would render Interests, old step 3 (Interests) would render ProSettings, silently skipping required profile steps. Common's mount now performs a one-time idempotent remap (2→1,3→2,≥4→MAX), gated onisUserStateInit && !onboarding.finishedAtso it fires only for in-flight legacy users; finished users are untouched, fresh users no-op.Agent onboarding profile cleanup
responseLanguageis removed fromagentOnboarding's profile schema — it's now sourced exclusively fromuser_settings.general.responseLanguage.OnboardingContextInjector(new) feeds the resolved language andOnboardingUserInfoto the system role; the agent runtime's web-onboarding pipeline now reads fromi18n.resolvedLanguagefor locale.Welcome message handling
The agent-flow welcome message is now rendered client-side and re-derived as the user switches locale during shared prefix; nothing is persisted until the conversation actually starts, eliminating stale-language artifacts.
Files
src/features/Onboarding/Common/index.tsx(+ tests)packages/context-engine/src/providers/OnboardingContextInjector.ts(+ tests)scripts/resetOnboarding/index.ts,scripts/seedUserInfo/index.tssrc/features/Onboarding/Classic/index.tsx,src/routes/onboarding/agent/index.tsxsrc/routes/onboarding/config.ts(deriveOnboardingBranchPath)src/store/user/slices/onboarding/selectors.ts(commonStepsCompleted)packages/types/src/user/onboarding.ts(MAX_ONBOARDING_STEPS: 5 → 3)packages/types/src/user/agentOnboarding.ts(dropresponseLanguage)src/server/services/onboarding/index.ts+nodeHandlers.ts(drop responseLanguage handling)packages/builtin-tool-web-onboarding/**(drop responseLanguage from saveUserQuestion/manifest/systemRole)🧪 How to Test
Updated / added tests:
src/features/Onboarding/Common/index.test.tsx— 12 cases (rendering, redirects, loading guards, legacy step migration: 2→1, 3→2, ≥4→MAX, idempotent for new schema, skipped when finished, skipped before init)src/routes/onboarding/agent/index.test.tsx— added shared-prefix guard casesrc/store/user/slices/onboarding/selectors.test.ts— addedcommonStepsCompletedcases; updated max-step assertions for the new clamppackages/context-engine/src/providers/__tests__/OnboardingContextInjector.test.ts— new injector testssrc/server/services/onboarding/index.test.ts,nodeSchema.test.ts— drop responseLanguage assertionssrc/store/user/slices/common/action.test.ts— coverage for the welcome-message client flowESLint clean on changed files.
bun run type-checkclean.📸 Screenshots / Videos
📝 Additional Information
No data-shape breaking changes. Server-side
MAX_ONBOARDING_STEPSschema validation now capscurrentStepat 3 — fresh writes are always within range; legacy DB rows withcurrentStep > 3are clamped client-side by thecurrentStepselector and remapped on shared-prefix mount for in-flight users.