The ModelSearchDialog only checked client-side localStorage keys to
determine available providers, missing providers configured via .env
server-side vars. Now the /api/models endpoint returns an
availableProviders array and the dialog merges both sources.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create shared getModelPageUrl utility in src/utils/providerUrls.ts
- Add external-link icon to GenerateImageNode header (before Browse button)
- Add external-link icon to GenerateVideoNode header (before Browse button)
- Add external-link icon to Generate3DNode header (before Browse button)
- Icon only appears when model is selected and provider has a page URL
- Gemini models show no link (returns null); Replicate/fal/Kie/WaveSpeed show links
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Gemini and fal.ai always shown (always-available providers)
- Replicate, Kie.ai, WaveSpeed icons only shown when API key is configured
- Reset provider filter to "all" if selected provider becomes unavailable
- Fix WaveSpeed active color from orange to purple (matching its badge color)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove Annotate button assertion from basic rendering test
- Remove Annotate click test case
- Add All Nodes Menu test suite (4 tests: render, open, select, close)
- Update Browse Models tests for "All models" text label
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove Annotate shortcut button from action bar
- Add AllNodesMenu dropdown with all 22 node types in 6 categories
- Replace magnifying glass Browse models icon with "All models" text button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ConnectionDropMenu tests expected stale last items and item counts after
Router, Switch, and Conditional Switch were added. WorkflowCanvas tests
were missing dimmedNodeIds from the mock store state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After disconnecting an image edge, the target node's inputImages data
was not cleared. On regeneration, useStoredFallback would pick up the
stale images and send them to the API, causing results to still resemble
the old reference. Now removeEdge and onEdgesChange call
clearStaleInputImages to reset inputImages when no image-source edges
remain on the target node.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The else-if chain in blockedTypes detection meant that when a switch/
conditionalSwitch node was itself dimmed but had an enabled output,
the finalDimmed.has(source) check was skipped entirely. Changed the
dimmed-source check from else-if to a standalone if so it runs for
all source types, including switch and conditionalSwitch.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of setting inputSchema via useEffect (which runs after render),
set it directly in handleModelChange and handleBrowseModelSelect. This
ensures dynamic handles (including image-0 for I2V models) are rendered
in the same update cycle as model selection, preventing connection issues
where the image handle wouldn't accept connections.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of an inline text field, negative prompt is now a proper text
handle on the node that can receive connections from prompt/LLM nodes.
Updates the API route to merge dynamicInputs.negative_prompt into the
Veo parameters, and aligns the model schema definition accordingly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Veo models (veo-3.1, veo-3.1-fast) showed no user-configurable
parameters in the UI. Follows the established pattern from
GenerateImageNode where Gemini model parameters are hardcoded in the
component rather than fetched via the schema API. Adds aspect ratio,
duration, resolution, negative prompt, and seed controls.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The dimming algorithm processed potentially-dimmed nodes in arbitrary
order, causing nodes downstream of a rescued convergence point to stay
dimmed. Fix by topologically sorting the candidate set (upstream-first)
and checking finalDimmed instead of potentiallyDimmed, so rescued nodes
properly propagate their active status downstream.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add early validation for image-to-video models when no image is provided
- Wrap Veo generation/polling in try/catch with specific error messages
- Add 60s AbortController timeout to video download fetch
- Fix SwitchNode toggle knob not sliding (peer-checked on non-sibling)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds an evaluationPaused flag that lets users reset evaluation state
and un-dim all downstream paths. The flag auto-resets on workflow
execution or manual rule edits.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The useMemo for incomingText depended on edges (from useEdges), which
doesn't change when upstream node data changes. On re-runs, the memo
returned stale text and the useEffect overwrote correct execution
results. Replace with a Zustand store selector using
getConnectedInputsPure that recomputes when upstream node data changes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The customTitle and comment fields are typed as string | undefined in
ConditionalSwitchNodeData. The null values were masked by an 'as' cast
but caused strict type errors. These fields are optional and don't need
explicit defaults.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The customTitle and comment fields are typed as string | undefined, not
string | null. Remove them from the quickstart default data to fix the
TypeScript build error.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The inline defaultDimensions record in the keyboard shortcut handler was
missing the conditionalSwitch entry, causing a TypeScript build error.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The createDefaultNodeData function in validation.ts had cases for router
and switch but was missing conditionalSwitch, despite it being listed in
VALID_NODE_TYPES and DEFAULT_DIMENSIONS.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add guard in handleDelete and hide the delete button when only one
switch remains, matching ConditionalSwitchNode's existing behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The same 20-line block for evaluating rules and updating node data before
executing a ConditionalSwitch appeared in both executeWorkflow and
executeSelectedNodes. Extract to evaluateAndExecuteConditionalSwitch helper.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Identical rule evaluation logic existed in ConditionalSwitchNode.tsx and
workflowStore.ts. Extract to src/store/utils/ruleEvaluation.ts and
import from both locations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The MAX_BASE64_SIZE check was returning the video URL with the API key
appended as a query parameter to the browser client for videos over 20MB.
Always encode to base64 instead since the buffer is already downloaded.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ConditionalSwitch should act as a gate/trigger, not a data router.
Active outputs now trigger downstream execution without forwarding
the upstream text through the connection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace static pixel math with useLayoutEffect + offsetTop measurement to
position output handles at the actual vertical center of their corresponding
rule/default rows. This is robust against header height, padding, and text
preview variations that caused the previous static offset to misalign.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve three issues with the Conditional Switch node:
- Add fromHandleType resolution for conditionalSwitch in handleConnectEnd so
the connection drop menu appears when dragging from rule/default outputs
- Align output handles with visual rule rows by accounting for the text preview
height in baseOffset and using fixed h-8 rows matching handleSpacing=32
- Move "Add Rule" button after the Default row so the default handle aligns
with its visual row instead of being displaced
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add geminiApiKey to useProviderApiKeys hook. Update GenerateVideoNode to
include Gemini as a provider when API key is configured, and pass the
X-Gemini-API-Key header when fetching models.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Import generateWithGeminiVideo and route Veo model requests (modelId
starting with 'veo-') to the video provider before falling through
to the existing image generation path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Veo video generation using @google/genai SDK with:
- Model ID mapping (veo-3.1/veo-3.1-fast to API model IDs)
- Async generation with polling (10s intervals, 5min timeout)
- Image-to-video support with base64 image input
- Video download and base64 encoding (URL fallback for >20MB)
- Configurable aspect ratio, duration, resolution, negative prompt, seed
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add getGeminiVideoSchema() function returning parameter schemas (aspect
ratio, duration, resolution, negative prompt, seed) and input definitions
for all 4 Veo model variants. Wire into GET handler with gemini provider
support.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add GEMINI_VIDEO_MODELS array with 4 native Veo entries (3.1 and 3.1 Fast,
text-to-video and image-to-video variants) and include them in the GET
handler alongside existing Gemini image models.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Anthropic as a third LLM provider with Claude Opus 4.6, Sonnet 4.5,
and Haiku 4.5 models. Extend Google provider with Gemini 3.1 Pro.
Includes full API route support with multimodal content blocks,
provider settings UI, temperature clamping (Anthropic max 1.0),
header builder plumbing, and comprehensive test coverage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Nano Banana Pro supports 1K/2K/4K, while Nano Banana 2 also supports 512.
Split the shared RESOLUTIONS constant into RESOLUTIONS_PRO and RESOLUTIONS_NB2,
and use the correct list based on the selected model in both GenerateImageNode
and SplitGridSettingsModal. Also normalize aspect ratio and resolution to valid
defaults when switching models in the SplitGrid modal.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Nano Banana 2 (gemini-3.1-flash-image) supports a new searchTypes API
that allows enabling web search and image search independently. This adds
a useImageSearch toggle visible only for Nano Banana 2, while keeping the
existing Google Search toggle using the legacy format for Nano Banana Pro.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Make aspect ratio dropdowns model-aware: nano-banana-2 shows 14 ratios
while other models keep showing the base 10. Also add nano-banana-2 to
the SplitGrid settings model list.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update expected model counts and sort order to account for the new
Nano Banana 2 Gemini model (3 Gemini models instead of 2).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove router/switch/conditionalSwitch entries from WorkflowCanvas
defaultDimensions and validation.ts (these types only exist on develop)
- Add ModelType import and cast in nodeDefaults.ts for type safety
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pre-existing type error — conditionalSwitch was missing from the
createDefaultNodeData switch in validation.ts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pre-existing type error — conditionalSwitch was added to NodeType but the
local defaultDimensions map in keyboard shortcut handler was not updated.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Nano Banana 2 entry to GEMINI_IMAGE_MODELS in model registry
- Add model to GenerateImageNode dropdown with 512px resolution option
- Extend resolution/Google Search gates to support nano-banana-2
- Replace hardcoded model name ternaries with MODEL_DISPLAY_NAMES lookup
in workflowStore, nodeDefaults, and GenerateImageNode migration code
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add per-resolution pricing for nano-banana-2 (512/1K/2K/4K).
Add 512px tier to all model pricing tables.
Use MODEL_DISPLAY_NAMES lookup instead of ternaries.
Add getPricing fallback for nano-banana-2 / gemini-3.1-flash-image-preview.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Map nano-banana-2 to gemini-3.1-flash-image-preview API model.
Enable resolution control and Google Search grounding for nano-banana-2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add "nano-banana-2" to ModelType union for Gemini 3.1 Flash Image Preview.
Add "512" resolution tier. Add MODEL_DISPLAY_NAMES lookup to replace ternaries.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>