- Add modelSearchOpen/modelSearchProvider state to workflowStore
- Add setModelSearchOpen action to toggle dialog with provider filter
- Add ProviderIconButton component with Replicate (R) and fal.ai (lightning) icons
- Replicate icon only visible when API key is configured
- fal.ai icon always visible (works without key but rate limited)
- Add useEffect to migrate legacy nodes without selectedModel on mount
- Derive selectedModel from model field for legacy workflows
- Ensures UI reflects correct provider/model for migrated nodes
- Add API key headers (X-Replicate-API-Key, X-Fal-API-Key) for external providers
- Include selectedModel in request payload for provider routing
- Update logging to show provider-specific info
- Apply same changes to regenerateNode for consistency
- Migrate nanoBanana nodes without selectedModel on workflow load
- Derive selectedModel from legacy model field (nano-banana, nano-banana-pro)
- Set provider to gemini and appropriate displayName for migrated nodes
Refactor generate API route to support multiple providers:
- Accept both legacy format and new format with selectedModel
- Route requests to Replicate, fal.ai, or Gemini based on provider
- Extract Gemini logic into generateWithGemini() helper function
- Add generateWithReplicate() and generateWithFal() server-side helpers
- Get provider API keys from request headers (X-Replicate-API-Key, X-Fal-API-Key)
- Preserve backward compatibility for existing Gemini-based workflows
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement generation via fal.ai's fal.run API:
- POST to https://fal.run/{modelId} with prompt and parameters
- Use "Key {apiKey}" auth header (works without key but rate limited)
- Extract image URL from response (handles images array, image object, or output string)
- Fetch image and convert to base64 data URL
- Return GenerationOutput with type: "image"
Note: Image inputs skipped for now (Phase 5 adds URL server)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement generation via Replicate's prediction API:
- POST to /predictions with model version and prompt
- Poll /predictions/{id} until succeeded/failed/canceled
- Fetch output image URL and convert to base64 data URL
- Return GenerationOutput with type: "image"
Note: Image inputs skipped for now (Phase 5 adds URL server)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Video models were getting text-to-image capability by default.
Now properly detects video models (by keywords like video, animate,
motion, luma, kling, minimax) and only assigns video capabilities.
Both APIs return paginated results but we were only fetching page 1.
Now fetches up to 5 pages from Replicate (~125 models) and 10 pages
from fal.ai to get more complete model lists.
UAT-005: Video models were showing in image-only dropdown because
the API wasn't filtering by capabilities param. Now filters results
based on ?capabilities=text-to-image,image-to-image query param.
UAT-004: Replicate shows first page only (~25 models) - this is
expected API behavior. Full pagination can be added later.
Tasks completed: 3/3
- Add SelectedModel type and update NanoBananaNodeData
- Create GenerateImageNode with provider/model selector
- Update store and canvas references
SUMMARY: .planning/phases/03-generate-node-refactor/03-01-SUMMARY.md
- Rename loadNanoBananaDefaults to loadGenerateImageDefaults (keep alias)
- Rename saveNanoBananaDefaults to saveGenerateImageDefaults (keep alias)
- Update createDefaultNodeData to set default selectedModel for Gemini
- Update WorkflowCanvas nodeTypes to use GenerateImageNode
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add SelectedModel interface for multi-provider model selection in image
generation nodes. Update NanoBananaNodeData with optional selectedModel
field for backward compatibility with existing workflows.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Rename target from Generate to GenerateImage
- Filter model selector to image capabilities only (text-to-image, image-to-image)
- Note GenerateVideo node deferred to Phase 6
Phase 2: Model Discovery is now complete with all 3 plans executed:
- 02-01: Replicate provider
- 02-02: fal.ai provider
- 02-03: Model caching and unified API
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Export cache utilities from provider index and add listAllModels/
searchAllModels helper functions for multi-provider operations.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add /api/models endpoint that aggregates models from all configured
providers. Supports caching, search, provider filtering, and handles
partial failures gracefully.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add in-memory cache for provider model lists with 10-minute TTL.
Includes get/set/invalidate functions and cache key generation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add defensive null checks before calling .map() on data.results
in both the API route and provider implementation. Returns empty
array with success:true when results is undefined, preventing
"Cannot read properties of undefined (reading 'map')" crash.
Fixes: UAT-001 from 02-01-ISSUES.md
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
fal.ai API only accepts a single category parameter, but we were
sending multiple categories. Now we fetch all active models and
filter client-side using the existing isRelevantModel() function.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Next.js API route for server-side fal.ai model fetching:
- GET /api/providers/fal/models endpoint
- Optional API key auth (fal.ai works without but rate limited)
- Filter to image/video categories only
- Normalize response to ProviderModel interface
- Support search query parameter
- Follow established pattern from replicate API route
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement ProviderInterface for fal.ai model marketplace:
- Model discovery via REST API (listModels, searchModels, getModel)
- Filter to relevant categories (text-to-image, image-to-image, text-to-video, image-to-video)
- Optional API key auth (works without key but with rate limits)
- Self-registration in provider registry on import
- Stub generate() for Phase 3 implementation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- GET /api/providers/replicate/models endpoint
- Accepts X-API-Key header or api_key query param
- Optional search param for model search
- Maps Replicate models to ProviderModel interface
- Infers capabilities from model name/description
- Returns { success, models } or { success, error }
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Implement ProviderInterface for Replicate.com
- listModels() fetches from /v1/models endpoint
- searchModels() uses /v1/search endpoint
- getModel() retrieves single model by owner/name
- inferCapabilities() from model name/description
- Self-registers via registerProvider() on import
- API key read from localStorage provider settings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 02: Model Discovery
- DISCOVERY.md with Replicate and fal.ai API research
- 02-01: Replicate provider implementation (2 tasks)
- 02-02: fal.ai provider implementation (2 tasks)
- 02-03: Model caching and unified endpoint (3 tasks)
- 7 total tasks defined across 3 plans
- Ready for execution
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add provider registry in src/lib/providers/index.ts:
- Export all types from types.ts
- providerRegistry for storing provider implementations
- registerProvider() for providers to self-register
- getProvider() to retrieve provider by type
- getConfiguredProviders() to get providers with API keys
- getAllProviders() to get all registered providers
Registry will be populated when provider modules are imported
in Phase 2 (Replicate and fal.ai implementations).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add provider abstraction layer in src/lib/providers/types.ts:
- ProviderModel interface for normalized model metadata
- ModelCapability union type for model capabilities
- GenerationInput/GenerationOutput interfaces for unified I/O
- ProviderInterface contract for provider implementations
This establishes the interface contract that all providers
(Gemini, Replicate, fal.ai) will implement in Phase 2.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create 01-01-SUMMARY.md with execution details
- Update STATE.md with new position and metrics
- Mark 01-01 complete in ROADMAP.md
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add tabbed interface with Project and Providers tabs. Providers tab
shows Gemini (env var configured), Replicate, and fal.ai with toggle
switches and API key inputs. Settings persist to localStorage on save.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ProviderSettings state with localStorage persistence for managing
Replicate and fal.ai API keys. Includes updateProviderSettings,
updateProviderApiKey, and toggleProvider actions. Gemini enabled by
default with env var, Replicate and fal.ai disabled until configured.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ProviderType union, ProviderConfig interface, and ProviderSettings
interface to support multi-provider API key management for Replicate
and fal.ai alongside existing Gemini support.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 01: Provider Infrastructure
- 2 plans created
- 5 total tasks defined
- Ready for execution
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>