Security & API route fixes:
- Remove API key query param support in fal/models route to prevent credential leakage
- Fix MIME type fallback in save-generation route (now uses prefix-based fallback: image/* -> png, video/* -> mp4, unknown -> bin)
- Add timeout (60s) and size limits (500MB) for remote fetch in save-generation route using AbortController
CSS fix:
- Consolidate duplicate :root blocks in globals.css
- Change handle selector from data-handletype="prompt" to data-handletype="text"
- Update --handle-color-text CSS variable from #a3a3a3 to #3b82f6
Test file global mock isolation:
- Fix useAnnotationStore mock to support Zustand selector pattern
- Use vi.stubGlobal() instead of direct global assignments to prevent test leakage
- Restore global.Image in afterAll hook in AnnotationModal.test.tsx
- Wrap async Done assertion in waitFor() in AnnotationModal.test.tsx
- Use idiomatic fireEvent.dragOver() in AnnotationNode.test.tsx
- Fix global.confirm stub with proper beforeAll/afterAll lifecycle in CostDialog.test.tsx
- Import ReactNode type properly in EdgeToolbar.test.tsx
- Update save-generation route test to expect AbortController signal in fetch call
- Add Multi-Provider Support (Beta) section for Replicate and fal.ai
- Update Tech Stack and Environment Variables with new providers
- Add docs link to welcome modal (https://node-banana-docs.vercel.app/)
- Remove debug console.log statements from gridSplitter and WorkflowCanvas
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes issues with external provider models (e.g., seedream-4.5) where:
- Boolean/integer params with "image" in name were misclassified as image inputs
- Array params without items.type specification were incorrectly rejected
- Handle ID mismatch between node components (image-0) and store (image)
- dynamicInputs not passed to API in node regeneration code path
Changes:
- Update isImageInput() to check schema types, not just names
- Map both indexed (image-0) and legacy (image) handle IDs to schema names
- Add dynamicInputs to nanoBanana regeneration request body
- Add hidden backward-compat handles for edge routing
- Add comprehensive tests for schema classification and handle mapping
- Fix Toast test to use specific selector for close button
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
These planning phase documents are local development artifacts
that don't need to be shared in the repo. They remain in .gitignore.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create server.js with extended requestTimeout (10 min) for long-running fal.ai video generation
- Update package.json dev script to use custom server
- Add comments explaining why queue API is not used (file size limitations)
- Use WHATWG URL API instead of deprecated url.parse()
- Added support for long-running video generation using a queue system with a 10-minute timeout.
- Updated maxDuration constant to reflect the new timeout for video generation.
- Enhanced API request handling to accommodate video generation, including error handling and polling for completion.
- Updated model retrieval tests to reflect the inclusion of additional models and improved provider filtering.
- Modified component tests to track model usage and reflect changes in the UI for provider selection.
- Image data flow through node chains (imageInput, annotation, nanoBanana)
- Text data flow through node chains (prompt, llmGenerate)
- Dynamic inputs from schema-mapped connections
- State updates during execution (status, outputImage)
- Mixed image and text data flow
The open project button was only visible for unsaved projects. Now it
displays in both states so users can always load a different project.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When providers like fal.ai or Replicate expect array parameters (e.g.,
image_urls), single values from dynamicInputs are now automatically
wrapped in arrays based on the OpenAPI schema's type property.
Changes:
- Add isArray field to ModelInput type for schema detection
- Update getFalInputMapping() to return schemaArrayParams
- Update getInputMappingFromSchema() to return schemaArrayParams
- Apply array wrapping in both fal.ai and Replicate handlers
- Add tests for array wrapping behavior
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 20: Integration Tests
- 2 plans created
- 6 total tasks defined
- Tests cover getConnectedInputs, validateWorkflow, topological sort,
data flow, error handling, and connection validation
- Ready for execution
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add provider icons (Gemini, Replicate, fal.ai) as filter buttons
- Replace dropdown with horizontal icon button group
- Add green badge color for Gemini provider
- Add 'Recently Used' section at top of model list
- Filter recent models by capability (image/video)
- Show max 4 recent models with cover images
- Track model usage via trackModelUsage on selection
- Add getProviderDisplayName helper for consistent naming
Phase 19 complete. All types now organized into 7 domain files:
annotation, nodes, providers, models, workflow, api, quickstart.
index.ts is a pure re-export hub.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add GEMINI_IMAGE_MODELS constant with nano-banana and nano-banana-pro
- Update GET handler to include Gemini models in response
- Support provider=gemini filter (returns only Gemini models)
- Gemini models appear first in 'all providers' results
- No API key needed for Gemini (always available)
Create api.ts with GenerateRequest, GenerateResponse, LLMGenerateRequest,
LLMGenerateResponse. Move RecentModel to providers.ts. Convert index.ts
to pure re-export hub with no type definitions.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create models.ts with AspectRatio, Resolution, ModelType.
Create workflow.ts with WorkflowEdge, WorkflowEdgeData, WorkflowSaveConfig,
WorkflowCostData, NodeGroup, GroupColor. Update nodes.ts to import from
domain files instead of index.ts to avoid circular dependencies.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add RecentModel interface to types/index.ts
- Add localStorage helpers: getRecentModels, saveRecentModels, MAX_RECENT_MODELS
- Add recentModels state to workflowStore (initialized from localStorage)
- Add trackModelUsage action to track model usage with timestamps
Create providers.ts with ProviderType, SelectedModel, ProviderConfig,
ProviderSettings, LLMProvider, and LLMModelType. Update index.ts to
re-export from providers.ts and import types for internal use.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace position-based sampling hash with MD5 in imageStorage.ts
- Add computeContentHash helper function
- Consistent with save-generation API (Phase 13 decision)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove Task 1 (part ordering fix) - no longer needed
- Phase now focused on unifying MD5 hashing for deduplication
- 1 task remaining
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add tests verifying the parameters field (UI settings) is passed to
provider APIs:
- Replicate: parameters passed to prediction input
- Replicate: dynamicInputs take precedence when merging
- fal.ai: parameters passed to request body
- fal.ai: dynamicInputs take precedence when merging
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 21: Fix Image Input & Deduplication Issues
- 1 plan created
- 2 tasks + 1 checkpoint defined
- Ready for execution
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive tests for dynamic input handles:
- Multiple image handles for multi-frame video models
- Placeholder handles with dimmed opacity
- Handle ordering (images before text)
- Gap spacing between handle groups
- Schema integration tests
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive tests for dynamic input handles:
- Multiple image handles with schema-name attributes
- Multiple text handles with schema-name attributes
- Placeholder handle variations with dimmed opacity
- Handle ordering (images before text)
- Gap spacing between handle groups
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add test to verify parameters field is passed to Replicate/fal.ai APIs
- Tests that UI settings (seed, steps, guidance) reach provider APIs
- Tests that dynamicInputs override parameters when both have same key
Add comprehensive tests for /api/models route covering:
- Basic functionality: fal.ai without key, both providers with keys
- Provider filtering by query param
- Capabilities filtering
- Search query param (client-side for Replicate, server-side for fal.ai)
- Caching behavior: cache hits, cache misses, refresh bypass
- Error handling: partial provider failures, all providers failing
- Pagination for both Replicate and fal.ai (max 15 pages)
- Capability inference for Replicate models (video keywords, i2v keywords)
- fal.ai category mapping to ModelCapability
- Model sorting by provider then name
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive tests for /api/generate fal.ai path:
- Image generation success (images array response)
- Video generation success (video object response)
- Works without API key (unauthenticated allowed)
- Rate limit (429) handling with and without key
- Various response formats (image, images, video, output)
- Large video (>20MB) returns URL instead of base64
- Empty dynamicInputs values are filtered
- Dynamic inputs passed to fal.ai request
- Environment variable API key fallback
- Error response formats (error.message, detail array)
- No media URL in response handling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive tests for /api/generate Replicate path:
- Image generation success with API key header
- Video generation success
- 401 when API key missing
- Rate limit (429) handling
- Prediction failure handling
- Prediction timeout (5 min max)
- Polling for prediction completion
- Large video (>20MB) returns URL instead of base64
- Dynamic inputs passed to prediction
- Environment variable API key fallback
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add tests for input validation and edge cases:
- Reject requests with no prompt, images, or dynamic inputs
- Accept image-to-image (images only, no prompt)
- Accept dynamicInputs with prompt, image frames, and image_url
- Handle multiple images in request
Add provider routing tests:
- Route to Gemini when no selectedModel provided
- Route to Gemini when selectedModel.provider is gemini
- Return 401 for Replicate without API key
Add response handling tests:
- Verify proper response structure
- Handle default MIME type fallback
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive tests for /api/generate route covering Gemini path:
- Success with prompt only and with images
- Config options (aspectRatio, resolution, googleSearch)
- Model mapping (nano-banana, nano-banana-pro)
- API key handling (env var vs header)
- Error cases (missing key, rate limits, no candidates, text-only response)
- MIME type extraction from data URLs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>