6.7 KiB
| phase | plan | type |
|---|---|---|
| 04-model-search-dialog | 2 | execute |
Purpose: Let users browse and search models from Replicate and fal.ai, then add a GenerateImage node with the selected model. Output: Functional ModelSearchDialog component that searches models, displays results, and creates nodes on selection.
<execution_context> ~/.claude/get-shit-done/workflows/execute-phase.md ./summary.md ~/.claude/get-shit-done/references/checkpoints.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/04-model-search-dialog/04-01-SUMMARY.mdKey source files:
@src/components/FloatingActionBar.tsx @src/store/workflowStore.ts @src/app/api/models/route.ts @src/components/nodes/GenerateImageNode.tsx @src/types/index.ts @src/lib/providers/types.ts
Tech stack available: React, Zustand, /api/models endpoint with search and capabilities filtering Established patterns: Modal rendering via createPortal, model fetching with API key headers, SelectedModel type Constraining decisions:
- [Phase 2]: /api/models endpoint accepts X-Replicate-Key and X-Fal-Key headers
- [Phase 2]: capabilities parameter filters models (text-to-image, image-to-image, text-to-video, image-to-video)
- [Phase 3]: SelectedModel type: { provider, modelId, displayName }
-
Component structure:
- Use createPortal to render outside React Flow stacking context (like other modals)
- Increment/decrement modalCount in store on mount/unmount
- Full-screen overlay with centered dialog (max-w-2xl)
-
Dialog layout:
- Header: "Browse Models" title + close button (X)
- Filter bar:
- Search input (debounced 300ms)
- Provider filter dropdown (All / Replicate / fal.ai)
- Capability filter (All / Image / Video)
- Model grid/list:
- Show cover image thumbnail (if available), model name, provider badge, description (truncated)
- Loading state while fetching
- Empty state for no results
-
Data fetching:
- Fetch from /api/models with query params:
- search: search query (if not empty)
- provider: provider filter (if not "all")
- capabilities: "text-to-image,image-to-image" for Image, "text-to-video,image-to-video" for Video
- Pass API keys via headers:
- Get from providerSettings in store
- X-Replicate-Key: providerSettings.providers.replicate?.apiKey
- X-Fal-Key: providerSettings.providers.fal?.apiKey
- Show loading spinner while fetching
- Handle errors gracefully (show error message, allow retry)
- Fetch from /api/models with query params:
-
Styling (match existing dark theme):
- Background: bg-neutral-800
- Borders: border-neutral-700
- Text: text-neutral-100 for headers, text-neutral-300 for body
- Inputs: bg-neutral-700 border-neutral-600
- Cards: bg-neutral-700/50 hover:bg-neutral-700
-
Update FloatingActionBar.tsx:
- Replace placeholder with actual ModelSearchDialog import and render
- Pass modelSearchProvider as initial provider filter Open dialog via provider icon; search input filters results; provider dropdown changes results; models display with thumbnails ModelSearchDialog renders with search, filtering, and model display working
-
In workflowStore.ts, modify addNode to optionally accept initial data:
- Add optional second parameter:
initialData?: Partial<WorkflowNodeData> - Merge initialData into default node data when creating node
- This allows setting selectedModel when adding from model browser
- Add optional second parameter:
-
Update ModelSearchDialog to call addNode with selectedModel:
const handleSelectModel = (model: ProviderModel) => { const center = getPaneCenter(); // reuse from FloatingActionBar const position = screenToFlowPosition({ x: center.x + Math.random() * 100 - 50, y: center.y + Math.random() * 100 - 50, }); addNode("nanoBanana", position, { selectedModel: { provider: model.provider, modelId: model.id, displayName: model.name, } }); setModelSearchOpen(false); }; -
Add visual feedback:
- Cursor pointer on model cards
- Hover state on cards (slight brightness increase)
- Optional: toast/notification when node created Click model in dialog; GenerateImage node created at canvas center with selectedModel set; dialog closes automatically Model selection creates configured GenerateImage node and closes dialog
<success_criteria>
- All tasks completed
- All verification checks pass
- Human verification approved
- No TypeScript errors
- Users can browse, search, filter, and select models from the dialog
- Phase 4 complete </success_criteria>