Browse Source
Phase 23: Model Browser Improvements - 1 plan created - 3 tasks defined - Ready for execution Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>handoff-20260429-1057
1 changed files with 240 additions and 0 deletions
@ -0,0 +1,240 @@ |
|||
--- |
|||
phase: 23-model-browser-improvements |
|||
plan: 01 |
|||
type: execute |
|||
--- |
|||
|
|||
<objective> |
|||
Improve model browser UX with recently used models section, icon-based provider selector, and Gemini models in browse list. |
|||
|
|||
Purpose: Make it faster to access frequently used models and provide a consistent experience across all providers including Gemini. |
|||
Output: Enhanced ModelSearchDialog with recent models, icon-based provider filter, and Gemini models alongside Replicate/fal.ai models. |
|||
</objective> |
|||
|
|||
<execution_context> |
|||
~/.claude/get-shit-done/workflows/execute-phase.md |
|||
~/.claude/get-shit-done/templates/summary.md |
|||
</execution_context> |
|||
|
|||
<context> |
|||
@.planning/PROJECT.md |
|||
@.planning/ROADMAP.md |
|||
@.planning/STATE.md |
|||
|
|||
# Key source files |
|||
@src/components/modals/ModelSearchDialog.tsx |
|||
@src/components/FloatingActionBar.tsx |
|||
@src/store/workflowStore.ts |
|||
@src/app/api/models/route.ts |
|||
@src/types/index.ts |
|||
@src/lib/providers/types.ts |
|||
|
|||
# Related prior work |
|||
@.planning/phases/04-model-search-dialog/04-02-SUMMARY.md |
|||
|
|||
**Tech stack available:** |
|||
- React with Zustand for state |
|||
- ModelSearchDialog with existing filter patterns |
|||
- /api/models route with caching |
|||
- Provider icons already exist (Replicate, fal.ai SVGs in FloatingActionBar) |
|||
|
|||
**Established patterns:** |
|||
- Client-side search filtering |
|||
- Model cards with cover image, name, badges |
|||
- Provider badge colors (blue for Replicate, yellow for fal.ai) |
|||
- localStorage persistence for settings |
|||
|
|||
**Constraining decisions:** |
|||
- Phase 4: Client-side search filtering for Replicate |
|||
- Phase 4: Model card layout with badges and descriptions |
|||
- Gemini models use internal names (nano-banana, nano-banana-pro) |
|||
</context> |
|||
|
|||
<tasks> |
|||
|
|||
<task type="auto"> |
|||
<name>Task 1: Add recently used models tracking and storage</name> |
|||
<files>src/store/workflowStore.ts, src/store/utils/localStorage.ts, src/types/index.ts</files> |
|||
<action> |
|||
Add recently used models tracking: |
|||
|
|||
1. In types/index.ts, add interface: |
|||
```typescript |
|||
export interface RecentModel { |
|||
provider: ProviderType; |
|||
modelId: string; |
|||
displayName: string; |
|||
timestamp: number; |
|||
} |
|||
``` |
|||
|
|||
2. In localStorage.ts, add: |
|||
- RECENT_MODELS_KEY constant: "node-banana-recent-models" |
|||
- getRecentModels(): RecentModel[] function (returns [] if not found) |
|||
- saveRecentModels(models: RecentModel[]): void function |
|||
- MAX_RECENT_MODELS = 8 (keep 8, show 4 in UI) |
|||
|
|||
3. In workflowStore.ts: |
|||
- Add state: recentModels: RecentModel[] (initialized from localStorage) |
|||
- Add action: trackModelUsage(model: { provider: ProviderType, modelId: string, displayName: string }) => void |
|||
- Remove existing entry for same modelId if present |
|||
- Prepend new entry with current timestamp |
|||
- Trim to MAX_RECENT_MODELS |
|||
- Save to localStorage |
|||
|
|||
Do NOT call trackModelUsage from the store itself - it will be called from ModelSearchDialog's handleSelectModel. |
|||
</action> |
|||
<verify> |
|||
- Check workflowStore exports recentModels and trackModelUsage |
|||
- Check localStorage functions work (manually test in browser console) |
|||
</verify> |
|||
<done> |
|||
- RecentModel type exists |
|||
- localStorage helpers for recent models exist |
|||
- Store has recentModels state and trackModelUsage action |
|||
</done> |
|||
</task> |
|||
|
|||
<task type="auto"> |
|||
<name>Task 2: Add Gemini models to /api/models and update provider filter</name> |
|||
<files>src/app/api/models/route.ts</files> |
|||
<action> |
|||
Add Gemini image models to the models API response: |
|||
|
|||
1. Create GEMINI_IMAGE_MODELS constant at top of file: |
|||
```typescript |
|||
const GEMINI_IMAGE_MODELS: ProviderModel[] = [ |
|||
{ |
|||
id: "nano-banana", |
|||
name: "Nano Banana", |
|||
description: "Fast image generation with Gemini 2.5 Flash. Supports text-to-image and image-to-image with aspect ratio control.", |
|||
provider: "gemini", |
|||
capabilities: ["text-to-image", "image-to-image"], |
|||
coverImage: null, |
|||
}, |
|||
{ |
|||
id: "nano-banana-pro", |
|||
name: "Nano Banana Pro", |
|||
description: "High-quality image generation with Gemini 3 Pro. Supports text-to-image, image-to-image, resolution control (1K/2K/4K), and Google Search grounding.", |
|||
provider: "gemini", |
|||
capabilities: ["text-to-image", "image-to-image"], |
|||
coverImage: null, |
|||
}, |
|||
]; |
|||
``` |
|||
|
|||
2. In GET handler, update providersToFetch logic: |
|||
- If providerFilter === "gemini", only include Gemini models (don't fetch from external APIs) |
|||
- If providerFilter is null/all, include Gemini models in addition to external providers |
|||
- Gemini models are always available (no API key needed) |
|||
|
|||
3. Add Gemini models to allModels array at the start (before external provider fetch loop), so they appear first when no filter is applied. |
|||
|
|||
4. Add gemini to providerResults with { success: true, count: 2, cached: true } when Gemini models are included. |
|||
|
|||
Avoid: Fetching Gemini models from any external API - they are hardcoded. |
|||
</action> |
|||
<verify> |
|||
- curl "http://localhost:3000/api/models" returns Gemini models in response |
|||
- curl "http://localhost:3000/api/models?provider=gemini" returns only Gemini models |
|||
- curl "http://localhost:3000/api/models?provider=fal" does NOT return Gemini models |
|||
</verify> |
|||
<done> |
|||
- /api/models returns Gemini models (nano-banana, nano-banana-pro) |
|||
- Provider filter "gemini" works correctly |
|||
- Gemini models appear first in "all providers" results |
|||
</done> |
|||
</task> |
|||
|
|||
<task type="auto"> |
|||
<name>Task 3: Update ModelSearchDialog with recent models and icon-based provider filter</name> |
|||
<files>src/components/modals/ModelSearchDialog.tsx</files> |
|||
<action> |
|||
Update ModelSearchDialog UI: |
|||
|
|||
1. Import and use recentModels and trackModelUsage from store: |
|||
```typescript |
|||
const { recentModels, trackModelUsage, ... } = useWorkflowStore(); |
|||
``` |
|||
|
|||
2. In handleSelectModel, call trackModelUsage before closing: |
|||
```typescript |
|||
trackModelUsage({ |
|||
provider: model.provider, |
|||
modelId: model.id, |
|||
displayName: model.name, |
|||
}); |
|||
``` |
|||
|
|||
3. Replace provider filter `<select>` with icon-based button group: |
|||
- "All" option (no icon, just text "All") |
|||
- Gemini icon (use a sparkle/star icon from existing SVG patterns, add green-500 badge color) |
|||
- Replicate icon (existing SVG from FloatingActionBar) |
|||
- fal.ai icon (existing SVG from FloatingActionBar) |
|||
- Style: horizontal button group with hover states, active state shows filled background |
|||
- Use existing badge colors: green for Gemini, blue for Replicate, yellow for fal.ai |
|||
|
|||
4. Add getProviderBadgeColor case for "gemini": |
|||
```typescript |
|||
case "gemini": |
|||
return "bg-green-500/20 text-green-300"; |
|||
``` |
|||
|
|||
5. Add "Recently Used" section at top of model list (after filter bar, before loading state): |
|||
- Only show if recentModels.length > 0 |
|||
- Show max 4 models (slice(0, 4)) |
|||
- Use same model card UI as main list |
|||
- Add subtle "Recent" label/header |
|||
- Filter recent models by current capability filter (image/video/all) |
|||
- Add divider between recent section and main list |
|||
|
|||
6. Update provider badge display text: |
|||
- "gemini" -> "Gemini" |
|||
- Keep existing: "replicate" -> "Replicate", "fal" -> "fal.ai" |
|||
|
|||
Styling notes: |
|||
- Icon buttons: p-2, rounded, hover:bg-neutral-700, active state bg-neutral-600 |
|||
- Recent section: slightly different background (bg-neutral-700/30), smaller gap, "Recently Used" label text-xs text-neutral-500 |
|||
- Gemini icon: Use a simple sparkle/AI icon (4-pointed star or similar) |
|||
</action> |
|||
<verify> |
|||
- Open ModelSearchDialog from fal.ai icon |
|||
- Verify Gemini, Replicate, fal.ai icons appear in provider filter |
|||
- Select a model, reopen dialog - model appears in "Recently Used" |
|||
- Filter by provider - recent models also filter |
|||
- Filter by capability - recent models also filter |
|||
</verify> |
|||
<done> |
|||
- Provider filter uses icons instead of dropdown |
|||
- Gemini option available in provider filter |
|||
- Recently used section shows at top of model list |
|||
- Recent models persist across dialog opens |
|||
- Model selection tracks usage |
|||
</done> |
|||
</task> |
|||
|
|||
</tasks> |
|||
|
|||
<verification> |
|||
Before declaring phase complete: |
|||
- [ ] npm run build succeeds without errors |
|||
- [ ] ModelSearchDialog shows Gemini models when "All" or "Gemini" filter selected |
|||
- [ ] Recently used models appear at top after selecting any model |
|||
- [ ] Provider filter uses icons (Gemini, Replicate, fal.ai, All) |
|||
- [ ] Recent models persist after page refresh |
|||
- [ ] Capability filter (image/video) works for both recent and main lists |
|||
</verification> |
|||
|
|||
<success_criteria> |
|||
|
|||
- All tasks completed |
|||
- All verification checks pass |
|||
- No TypeScript errors |
|||
- Gemini models browsable alongside Replicate/fal.ai |
|||
- Recently used models section functional |
|||
- Icon-based provider filter implemented |
|||
</success_criteria> |
|||
|
|||
<output> |
|||
After completion, create `.planning/phases/23-model-browser-improvements/23-01-SUMMARY.md` |
|||
</output> |
|||
Loading…
Reference in new issue