Create editOperations.ts with EditOperation type union covering all 5 operation types (addNode, removeNode, updateNode, addEdge, removeEdge). Implement applyEditOperations function with batched immutable updates, proper ID generation, and validation with skip tracking. Add narrateOperations function for human-readable summaries.
Create contextBuilder.ts with WorkflowContext interface and buildWorkflowContext function that strips base64 data, history arrays, and internal state. Add formatContextForPrompt function for system prompt injection.
Both modules are pure TypeScript with no UI or API dependencies.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use neutral-300 text, neutral-700/50 bg, and neutral-600 border
to make the button noticeable without clashing with the app style.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
loadWorkflow was unconditionally calling clearSnapshot(), wiping the
snapshot that captureSnapshot() just saved. Add preserveSnapshot
option to loadWorkflow and pass it from the AI build workflow path
so the Revert AI Changes button actually appears.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Updated last activity date and details in STATE.md to reflect completion of quick-001.
- Added recent decisions regarding dynamicInputs type and behavior.
- Enhanced tests in QuickstartTemplatesView to handle new download URL structure for community workflows, ensuring proper response handling for both API and direct download scenarios.
- Test: multiple images to same schema-mapped handle aggregate into array
- Test: single image to schema-mapped handle stays as plain string
- Test: multiple images with distinct schema handles remain separate strings
- Test: three images to same handle produce array of length 3
- Fix react-dom version mismatch (19.2.0 -> 19.2.3) to match react
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update dynamicInputs type from Record<string, string> to Record<string, string | string[]> in 4 locations
- Fix getConnectedInputs to aggregate same-key values into arrays instead of overwriting
- Fix dynamicInputs.prompt access to handle array case
- Fix hasPrompt check in POST handler to handle array-typed prompt
- Update processedDynamicInputs type in both Replicate and fal blocks
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The proxy was downloading 80-275MB workflow files through a serverless
function, causing timeouts and failures. Now the proxy just returns the
presigned R2 URL and the client downloads directly from R2.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add react-markdown to parse assistant responses so bold, italic,
lists, blockquotes, and code render properly instead of showing
raw asterisks and markdown syntax.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add trash icon button in chat header that clears all messages.
Only visible when messages exist. Uses setMessages([]) from
the AI SDK useChat hook.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Rewrite chat system prompt to be concise — bullet points over
paragraphs, 2-4 sentences per response. Make chat panel stretch
from top-16 to bottom-[220px] for near-full canvas height.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add defensive check before Object.keys(groups) in saveToFile and
exportWorkflow to prevent "Cannot read properties of undefined
(reading 'length')" when groups is undefined after AI workflow
generation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tasks 1 & 2: Complete AI workflow revert feature
Changes:
- WorkflowCanvas: Call captureSnapshot() before AI loadWorkflow
- Header: Add "Revert AI Changes" button with confirmation dialog
- Button visible only when previousWorkflowSnapshot exists
- Amber styling to distinguish safety feature from destructive actions
Snapshot capture ONLY in AI generation path (not file loads/templates).
Button auto-hides after revert or 3 manual changes (store handles this).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create 33-01-SUMMARY.md documenting snapshot infrastructure
implementation. Update STATE.md with current position and
decisions about snapshot behavior.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add snapshot state and actions to capture, revert, and clear workflow
state before AI-initiated changes. Includes manual change tracking
that auto-clears snapshot after 3 user edits.
- Add previousWorkflowSnapshot state (nodes, edges, groups, edgeStyle)
- Add manualChangeCount state
- Implement captureSnapshot() to save current workflow state
- Implement revertToSnapshot() to restore snapshot
- Implement clearSnapshot() to remove snapshot
- Implement incrementManualChangeCount() with auto-clear at 3 changes
- Wire manual change tracking into addNode, removeNode, onConnect,
removeEdge, onNodesChange (remove only), onEdgesChange (remove only)
- Call clearSnapshot() in clearWorkflow and loadWorkflow
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
All tasks completed:
- Task 1: Build Workflow button in ChatPanel with conversation extraction
- Task 2: Workflow generation integration in WorkflowCanvas
- Task 3: External loading state (completed in Task 1)
Created SUMMARY.md and updated STATE.md (.planning/ in .gitignore).
Phase 32 complete. Chat-to-workflow flow fully functional.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Task 3 requirements were already implemented in Task 1 commit. The ChatPanel
correctly uses the isBuildingWorkflow prop from parent, disables button during
both chat streaming and workflow building, and shows proper loading state.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add handleBuildWorkflow function that calls /api/quickstart with conversation
description and loads the generated workflow. Includes error handling with toast
notifications and automatically closes chat panel on success.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add "Build Workflow" button that appears after conversation starts. Button
extracts user messages to form a description and passes to parent via callback.
Includes loading state support via isBuildingWorkflow prop.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add nowheel class to prevent React Flow from intercepting scroll
- Add touchAction: pan-y for proper touch gesture support
- Add onWheelCapture to stop event propagation to canvas
- Add isChatOpen state for chat visibility
- Add chat toggle button positioned above MiniMap
- Render ChatPanel conditionally when open
- Style toggle button with active/inactive states
- Add @ai-sdk/react package for useChat hook
- Create floating chat panel with streaming messages
- Display messages with role-based styling (user/assistant)
- Auto-scroll to bottom on new messages
- Show loading indicator during AI responses
- Dark theme matching app (neutral-800 bg)
- Import convertToModelMessages and UIMessage from ai
- Convert incoming messages for useChat hook compatibility
- Return toUIMessageStreamResponse() instead of toTextStreamResponse()
- POST /api/chat with Vercel AI SDK streamText
- Node Banana domain expertise in system prompt
- Conversational workflow planning assistant
- Uses createGoogleGenerativeAI with GEMINI_API_KEY
Add POST endpoint that generates WorkflowProposal JSON from a description:
- Validates description (min 3 chars)
- Calls Gemini with buildProposalPrompt
- Parses JSON with repair logic from validation.ts
- Validates response matches WorkflowProposal structure
- Returns { success: true, proposal } or { success: false, error }
Uses same patterns as /api/quickstart:
- maxDuration = 60
- Temperature 0.3 for consistent output
- Request ID logging
- Rate limit (429) handling
- gemini-3-flash-preview model
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add function that generates a prompt asking the LLM to output a
WorkflowProposal JSON structure instead of a full workflow.
Key differences from buildQuickstartPrompt:
- Outputs reviewable proposal, not internal workflow state
- Focus on explaining purpose of each node
- Human-readable connection descriptions
- Simpler schema without positions or runtime data
- Includes complexity estimate and warnings
The prompt guides the LLM to create proposals that users can
review and modify before building the actual workflow.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add types for the workflow proposal system:
- ProposedNode: node with purpose, title, and suggested settings
- ProposedConnection: connection with human-readable description
- ProposedGroup: optional grouping with purpose description
- WorkflowProposal: complete reviewable workflow structure
These types enable the LLM to propose workflow structure before
generating full workflow JSON, allowing user review and editing.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
LLMGenerateNode improvements:
- Add collapsible parameters section with temperature and max tokens sliders
- Add copy to clipboard button for output text
- Clean up UI organization
PromptNode improvements:
- Add text input handle to receive incoming text connections
- Auto-populate prompt when connected to a text source (e.g., another LLM)
ConnectionDropMenu:
- Add Prompt as a target option for text connections
ProjectSetupModal:
- Add max tokens slider for LLM default settings
Test updates:
- Update mocks to include edges and getConnectedInputs
- Fix tests for collapsible parameters section
- Update wrap-around test for new menu options
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
React Flow's internal bounds for nodes were undefined, causing certain nodes
to be incorrectly included in drag selections regardless of their position.
Added statistical outlier detection using IQR to identify and automatically
deselect nodes that are clearly outside the actual selection area.
Also includes:
- Clear selected state and validate position coordinates on workflow load
- Strip selected property when saving workflows (transient UI state)
- Enable prompt nodes to receive text input connections
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The PromptNode now uses local state and only updates on blur to prevent
cursor jumping. Update test to trigger blur after change.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove configurable COMMUNITY_WORKFLOWS_API_URL env var that caused
errors when users copied the placeholder from .env.example.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update getHandleType() to recognize indexed handles (text-0, image-0)
used by external providers like Replicate and fal.ai
- Fix validateWorkflow() to accept indexed text handles for nanoBanana nodes
- Add validation for generateVideo nodes requiring text input
- Use local state pattern in PromptNode to prevent cursor jumping during typing
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Validate presigned URLs before fetching by checking:
- Protocol is https
- Hostname ends with .r2.cloudflarestorage.com
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update the community workflow API to fetch presigned URLs from
node-banana-pro, then download workflows directly from R2. This
avoids timeouts when fetching large workflow files (275MB+).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update API routes to fetch from nodebananapro.com
- Remove local workflow JSON files (now hosted on R2)
- Remove LFS tracking (.gitattributes)
- Remove local communityWorkflows.ts metadata (now on server)
- Add COMMUNITY_WORKFLOWS_API_URL env variable option
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>