feat(desktop): add v1 import intro page + fix preset import#4151
Conversation
Splits the v1 import welcome screen into two pages: the existing
"Welcome to Superset v2" hero (now copy-free) and a new intro page that
sets expectations — workspaces and projects port over, terminal sessions
don't, and v1 stays accessible.
Also fixes the preset import flow, which threw "Invalid input - path: id"
for builtin agent presets ("claude", "codex"). v1 stores those with the
agent name as the preset id, but v2's schema requires id to be a UUID.
The import now generates a fresh UUID for the v2 row, sets agentId for
the link, and dedups on agentId (builtins) or name (custom presets)
instead of v1's id.
Greptile SummaryThis PR splits the v1→v2 import welcome screen into two pages (
Confidence Score: 3/5Safe to merge with the display-name mismatch resolved — the preset import logic is otherwise correct, but builtin preset rows currently show the raw v1 key in the picker while the imported record lands in v2 with the human-readable display label. The preset import fix is solid — fresh UUIDs, agentId linking, and split dedup all look correct. The remaining gap is that ImportRow renders preset.name rather than v2Name, so users see the raw v1 agent key in the UI instead of the human-readable label they'll find in v2 after import. The custom-preset dedup also has a latent false-positive if any custom preset name collides with a builtin display label. ImportPresetsPage.tsx — the ImportRow primary label and the importedNames set construction both warrant a second look.
|
| Filename | Overview |
|---|---|
| apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportPresetsPage/ImportPresetsPage.tsx | Core preset import logic refactored: dedup now uses agentId for builtins and name for custom presets; id is now a fresh UUID. The ImportRow still displays the v1 preset name (e.g. "claude") while the imported v2 row gets the display label (e.g. "Claude Code"), creating a visual mismatch. |
| apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/V1ImportModal.tsx | Added IntroPage between welcome and projects; DialogTitle and navigation logic updated correctly. DialogDescription is now static (always shows intro copy), which is minor since it's sr-only. |
| apps/desktop/src/renderer/stores/v1-import-modal.ts | Added "intro" to V1ImportPage type and V1_IMPORT_PAGE_ORDER; straightforward and correct. |
| apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/components/IntroPage/IntroPage.tsx | New static intro page component; simple, no issues. |
| apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/components/IntroPage/index.ts | Barrel export for IntroPage; correct. |
| apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/components/WelcomePage/WelcomePage.tsx | Removed the descriptive subtitle from WelcomePage, leaving just the title; straightforward removal. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A([Open Modal]) --> B[WelcomePage]
B -->|Get started| C[IntroPage - NEW]
C -->|Next| D{activeHostUrl ready?}
D -->|Yes| E[ImportProjectsPage]
D -->|No| F[Waiting screen]
F --> E
E -->|Next| G{activeHostUrl ready?}
G -->|Yes| H[ImportWorkspacesPage]
G -->|No| I[Waiting screen]
I --> H
H -->|Next| J[ImportPresetsPage]
J -->|Done| K([Close Modal])
subgraph Preset import logic
L[v1 preset] --> M{Is builtin agent name?}
M -->|Yes| N[linkedAgentId = preset.name\nv2Name = AGENT_LABELS lookup]
M -->|No| O[linkedAgentId = undefined\nv2Name = preset.name]
N --> P{importedAgentIds has linkedAgentId?}
O --> Q{importedNames has v2Name?}
P -->|Yes| R[Show Imported]
Q -->|Yes| R
P -->|No| S[Show Import button]
Q -->|No| S
S -->|clicked| T[Insert row with randomUUID id\nagentId set for builtins]
end
Comments Outside Diff (1)
-
apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportPresetsPage/ImportPresetsPage.tsx, line 152-156 (link)The
ImportRowstill passespreset.name(the raw v1 key, e.g."claude") as theprimarylabel. After this PR, builtin presets are imported with the display label fromAGENT_LABELS(e.g."Claude Code"), so the list shows"claude"but the imported row lands in v2 as"Claude Code". Passingv2Namehere keeps the two in sync.Prompt To Fix With AI
This is a comment left during a code review. Path: apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportPresetsPage/ImportPresetsPage.tsx Line: 152-156 Comment: The `ImportRow` still passes `preset.name` (the raw v1 key, e.g. `"claude"`) as the `primary` label. After this PR, builtin presets are imported with the display label from `AGENT_LABELS` (e.g. `"Claude Code"`), so the list shows `"claude"` but the imported row lands in v2 as `"Claude Code"`. Passing `v2Name` here keeps the two in sync. How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportPresetsPage/ImportPresetsPage.tsx:152-156
The `ImportRow` still passes `preset.name` (the raw v1 key, e.g. `"claude"`) as the `primary` label. After this PR, builtin presets are imported with the display label from `AGENT_LABELS` (e.g. `"Claude Code"`), so the list shows `"claude"` but the imported row lands in v2 as `"Claude Code"`. Passing `v2Name` here keeps the two in sync.
```suggestion
return (
<ImportRow
icon={<LuTerminal className="size-3.5" strokeWidth={2} />}
primary={v2Name}
secondary={preset.description ?? preset.commands[0]}
```
### Issue 2 of 2
apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportPresetsPage/ImportPresetsPage.tsx:36-38
**Name-based dedup collides with builtin display labels**
`importedNames` is built from all v2 preset names, including builtins imported under their display labels (e.g. `"Claude Code"`). If a user has a custom v1 preset whose name happens to match a builtin's display label, `importedNames.has(v2Name)` returns `true` and the row is permanently stuck as "Imported" — even though no custom preset with that name was ever actually imported. Narrowing `importedNames` to only presets where `agentId` is absent would avoid the collision.
Reviews (1): Last reviewed commit: "feat(desktop): add v1 import intro page ..." | Re-trigger Greptile
| const importedNames = useMemo( | ||
| () => new Set(v2Presets.map((p) => p.name)), | ||
| [v2Presets], |
There was a problem hiding this comment.
Name-based dedup collides with builtin display labels
importedNames is built from all v2 preset names, including builtins imported under their display labels (e.g. "Claude Code"). If a user has a custom v1 preset whose name happens to match a builtin's display label, importedNames.has(v2Name) returns true and the row is permanently stuck as "Imported" — even though no custom preset with that name was ever actually imported. Narrowing importedNames to only presets where agentId is absent would avoid the collision.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/components/V1ImportModal/ImportPresetsPage/ImportPresetsPage.tsx
Line: 36-38
Comment:
**Name-based dedup collides with builtin display labels**
`importedNames` is built from all v2 preset names, including builtins imported under their display labels (e.g. `"Claude Code"`). If a user has a custom v1 preset whose name happens to match a builtin's display label, `importedNames.has(v2Name)` returns `true` and the row is permanently stuck as "Imported" — even though no custom preset with that name was ever actually imported. Narrowing `importedNames` to only presets where `agentId` is absent would avoid the collision.
How can I resolve this? If you propose a fix, please make it concise.|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
💤 Files with no reviewable changes (1)
📝 WalkthroughWalkthroughThis PR enhances the V1 import modal by introducing an introductory onboarding step between the welcome and import pages, refactoring preset import status tracking with memoized sets, and updating the preset row rendering to compute and display agent-linked names alongside import status derivation. ChangesV1 Import Modal Flow Enhancement
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ImportRow showed the raw v1 key ("claude") while the imported v2 row
landed under the display label ("Claude Code"). Pass v2Name so the picker
matches the post-import name.
importedNames also now excludes builtin-linked v2 rows so a custom v1
preset whose name happens to match a builtin display label isn't falsely
flagged as already imported.
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
…-sh#4151) * feat(desktop): add v1 import intro page + fix preset import Splits the v1 import welcome screen into two pages: the existing "Welcome to Superset v2" hero (now copy-free) and a new intro page that sets expectations — workspaces and projects port over, terminal sessions don't, and v1 stays accessible. Also fixes the preset import flow, which threw "Invalid input - path: id" for builtin agent presets ("claude", "codex"). v1 stores those with the agent name as the preset id, but v2's schema requires id to be a UUID. The import now generates a fresh UUID for the v2 row, sets agentId for the link, and dedups on agentId (builtins) or name (custom presets) instead of v1's id. * fix(desktop): align import row label with imported name + tighten dedup ImportRow showed the raw v1 key ("claude") while the imported v2 row landed under the display label ("Claude Code"). Pass v2Name so the picker matches the post-import name. importedNames also now excludes builtin-linked v2 rows so a custom v1 preset whose name happens to match a builtin display label isn't falsely flagged as already imported.
Summary
IntroPagethat sets expectations — "let's get your workspaces and projects ported over. Terminal sessions won't be carried over, but you can still access v1 at any time."Invalid input - path: idfor builtin agent presets (claude,codex). v1 keys those presets by agent name; v2 requiresidto be a UUID. The import now generates a fresh UUID, setsagentIdfor the link, and dedups onagentId(builtins) orname(custom) instead of v1's id.Test plan
agentIdand dedups by name.Summary by cubic
Split the v1→v2 import flow into a welcome hero and a short intro to set expectations. Also fixed builtin preset import errors, label mismatch, and tightened deduping.
New Features
Bug Fixes
claude,codex): generate a UUID forid, setagentIdfor linking, dedup byagentId(builtins) or name (custom), show the v2 display label in the picker, and exclude builtin-linked rows from name-based dedup to avoid false “Imported”.Written for commit e20b4e2. Summary will update on new commits.
Summary by CodeRabbit
New Features