Extract shared downloadMedia utility from OutputNode and add download
buttons to ImageInput, VideoInput, Annotation, AudioInput, GenerateImage,
GenerateVideo, GenerateAudio, and GLBViewer nodes. Refactor OutputNode to
use the shared utility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- GroupsOverlay: reset color picker when menu closes, guard locked groups
from drag/resize/rename
- AudioInputNode: add keyboard accessibility to dropzone (role, tabIndex,
onKeyDown)
- list-workflows: fix name regex to handle escaped quotes
- GroupsOverlay.test: add missing NBP Input menu item assertion
- WorkflowBrowserView: make relativePath required to match API contract
- WorkflowBrowserModal: add dialog role, aria-modal, aria-labelledby
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ImageInputNode: dashed border + "Optional" text when empty, badge when loaded
- AudioInputNode: same pattern as ImageInputNode
- PromptNode: updated placeholder text when isOptional is set
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove header props (title, customTitle, comment, etc.) from BaseNode calls
- Apply full-bleed content pattern with contentClassName
- Replace dashed border empty states with subtle fills (bg-neutral-900/40)
- Move floating UI elements to absolute positioning
Part of batch update for all 21 remaining node files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract shared video-probing module (constants, helpers, probeVideoMetadata)
from useTrimVideo and useStitchVideos into src/lib/video-probing.ts
- Fix audio interleaving in useTrimVideo to feed audio before video frames,
matching useStitchVideos fix for Discord playback compatibility
- Fix blob URL leaks in VideoTrimNode and videoProcessingExecutors
- Fix nanoBananaExecutor: null coercion for non-string prompts, redact PII
in console.warn, remove duplicate dynamicInputs.prompt
- Fix generateAudioExecutor double updateNodeData on error paths
- Fix fal.ts media fetch ordering for 3D model detection
- Fix kie.ts and replicate.ts content-type detection for audio models
- Fix WorkflowCanvas connection drop menu wiring for generateAudio nodes
- Fix open-file route Windows path quoting
- Add path traversal protection to workflow-images route
- Add AudioInputNode onerror handler for metadata loading failures
- Fix useAudioPlayback uncaught play() promise rejection
- Add generateAudio case to regenerateNode in workflowStore
- Update placeholder Discord links to real invite URL
- Extract ProviderBadge into shared component in Generate3DNode
- Fix VideoTrimNode duration detection with proper cleanup and cancellation
- Fix GenerateAudioNode test fetch mock cleanup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deduplicate 6 patterns (drawWaveform, ResizeObserver, redraw effect,
animation loop, handlePlayPause, handleSeek) that were 100% identical
between AudioInputNode and GenerateAudioNode into a shared hook.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Both GenerateAudioNode and AudioInputNode relied on nodeData.duration
for the waveform progress calculation, but this was often null (never
set by the audio executor). Using audioRef.current.duration directly
avoids the store roundtrip and works as soon as audio metadata loads.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace bottom "Regenerate" button with header run button (onRun prop)
matching the pattern used by GenerateVideo and GenerateImage nodes
- Add isExecuting and hasError props to BaseNode for visual feedback
- Fix waveform playback progress: bars now change color to show played
vs unplayed portions (violet-300 played, violet-400 unplayed) with a
white position line
- Add requestAnimationFrame loop for smooth playback position updates
- Apply same waveform progress fix to AudioInputNode for consistency
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rename node title from "Audio Input" to "Audio"
- Rename label in ConnectionDropMenu from "Audio Input" to "Audio"
- Add target (input) handle to Audio node so it can receive audio from
GenerateAudio and other upstream nodes
- Add Audio node to AUDIO_TARGET_OPTIONS so it appears in the context
menu when dragging from GenerateAudio's output connector
- Add execution logic: connected audio populates audioFile (connection
wins over uploaded file), enabling pass-through to downstream nodes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- AudioInputNode: use named event handlers with removeEventListener in cleanup
- deduplicatedFetch: track setTimeout IDs and clear them in clearFetchCache()
- waitForPendingImageSyncs: clear timeout in finally block after Promise.race
- decodeWithMediaBunny: wrap in try/finally to close sink, input, blobSource
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Split AudioInputNode waveform effect to avoid ResizeObserver churn on every animation tick
- Add missing kieApiKey/wavespeedApiKey deps to ModelParameters useEffect
- Clean up VideoSampleSource/Output on error in useApplySpeedCurve
- Fix off-by-one in useStitchVideos duplicate-frame skip (<= to <) and add try/finally for resource cleanup
- Replace leftover currentNodeId: null with currentNodeIds: [] in workflowStore
- Store full response metadata (status, headers, body) in deduplicatedFetch cache
- Add in-flight guard to imageStorage to prevent duplicate concurrent saves
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added AudioInputNode export to nodes/index.ts
- Added audioInput to defaultNodeDimensions (300x200) and createDefaultNodeData
- Registered audioInput in WorkflowCanvas nodeTypes map
- Updated getHandleType to recognize audio handles
- Added audioInput to getNodeHandles (no inputs, audio output)
- Updated isValidConnection for audio-to-audio validation
- Added audio to ConnectionDropState handleType union
- Updated findCompatibleHandle to accept audio type
- Added AUDIO_SOURCE_OPTIONS and AUDIO_TARGET_OPTIONS to ConnectionDropMenu
- Added audio array to getConnectedInputs return type
- Updated getSourceOutput to handle audioInput nodes
- Added audioInput execution case (no-op, data source)
- Added AudioInputNodeData import to workflowStore
- Updated DEFAULT_DIMENSIONS in WorkflowCanvas and quickstart/validation.ts
- Updated createDefaultNodeData in quickstart/validation.ts
- Added violet minimap color (#a78bfa) for audioInput nodes
- File upload via drag-and-drop or click
- Waveform visualization using useAudioVisualization hook
- Play/pause controls with scrub bar
- Canvas-based rendering with ResizeObserver for responsive sizing
- Audio handle (purple/violet) on right side
- Min dimensions: 250px width, 150px height
- Remove button to clear audio file