Create SUMMARY.md documenting plan execution and update STATE.md
with current position and accumulated decisions.
Summary includes:
- Task completion: enhanced chat API route with tool calling
- Deviation: changed maxSteps to stopWhen: stepCountIs(3) (AI SDK v6 API)
- Key decisions: tool pattern, context injection, multi-step reasoning
- Verification: TypeScript passes, streaming works correctly
STATE.md updates:
- Current position: Plan 2 of phase 34
- Performance metrics: 2/? plans, 13 min total, 6.5 min avg
- Recent trend: 5-8 min execution
- Accumulated context: 4 new decisions about chat API and tool calling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Broaden the trailing-slash exemption to recognize both C:\ and C:/ as
drive roots. Tighten the client-side absolute path check to require a
separator after the drive letter and accept UNC paths (\\server\share).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Rewrite /api/chat route to accept workflow context from client and use
AI SDK tool calling for multi-modal agent routing.
Changes:
- Accept optional workflowState (nodes/edges) in request body
- Build workflow context using buildWorkflowContext from contextBuilder
- Generate context-aware system prompt using buildEditSystemPrompt
- Create chat tools (answerQuestion, createWorkflow, editWorkflow) with
current node IDs for validation
- Configure streamText with tools, toolChoice: 'auto', and stopWhen for
multi-step reasoning (up to 3 steps)
- Stream results back via toUIMessageStreamResponse for useChat hook
compatibility
LLM now automatically routes to the correct tool based on user intent.
Tool results stream back to client for application in Plan 03.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create tools.ts with buildEditSystemPrompt function that constructs enhanced system prompt with workflow context and tool usage rules. Implement createChatTools function that returns three tool definitions using AI SDK v6 tool() pattern:
- answerQuestion: informational queries without workflow modification
- createWorkflow: build new workflows from scratch via quickstart
- editWorkflow: targeted edits with operation list and explanation
All tools use zod schemas for type-safe input validation. Tools follow "generate" pattern (no execute function) - LLM provides structured output that client/route handles.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
On macOS, osascript's folder picker can return hostname-prefixed paths
(e.g. "HOSTNAME/Users/...") for network-mounted volumes instead of
absolute POSIX paths, causing directory validation to fail.
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.
Update vulnerable react-dom dependency and next.js to patched versions.
Fix QuickstartTemplatesView test to mock two-step R2 download flow.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>
- 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>
Kie API returns HTTP 200 even on errors, with error code in the JSON body.
Now properly checks createResult.code !== 200 and returns the actual error
message from the API instead of generic "No task ID in response".
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Some Kie.ai models (like gpt-image/1.5-text-to-image) require certain
parameters to be present even if not user-specified (e.g., aspect_ratio,
quality). Add getKieModelDefaults() function that provides model-specific
defaults which are merged with user-provided parameters.
Also skip file logging on Vercel since filesystem is read-only.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use multipart/form-data for file upload with 'file' and 'uploadPath' fields
- Extract download URL from data.downloadUrl in upload response
- Wrap parameters in 'input' object for standard models
- Use flat structure with camelCase for Veo models
- Extract results from resultJson.resultUrls in poll response
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Kie.ai section in provider settings with API key input
- Add kie to env-status API for .env detection
Co-Authored-By: Claude <noreply@anthropic.com>
Add Kie.ai as a new provider for image and video generation:
Image models (8):
- z-image, seedream/4.5-text-to-image, seedream/4.5-edit
- nano-banana-pro, gpt-image/1.5-text-to-image, gpt-image/1.5-image-to-image
- google/nano-banana, google/nano-banana-edit
Video models (11):
- sora-2-text-to-video, sora-2-image-to-video
- sora-2-pro-text-to-video, sora-2-pro-image-to-video
- veo3_fast, veo3, bytedance/seedance-1.5-pro
- kling-2.6/text-to-video, kling-2.6/image-to-video
- wan/2-6-text-to-video, wan/2-6-image-to-video
Key changes:
- Add "kie" to ProviderType union
- Add generateWithKie() with image upload and task polling
- Add hardcoded model list and schemas (no discovery API)
- Update workflow store for API key handling
- Update UI components with Kie provider badge
Co-Authored-By: Claude <noreply@anthropic.com>
Documents the production URL, environment variables, and how to sync
updates from upstream while keeping local modifications.
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