Browse Source

docs(14-01): complete fix drag-connect node creation bugs plan

Phase 14 complete - Milestone v1.1 finished

Tasks completed:
- Normalize dynamic handle IDs to standard values
- Update connection validation for normalized handles
- Map normalized handles to schema names in execution
- Add placeholder handles for unused input types

SUMMARY: .planning/phases/14-fix-drag-connect-bugs/14-01-SUMMARY.md

Co-Authored-By: Claude <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 6 months ago
parent
commit
be2387e1e8
  1. 12
      .planning/ROADMAP.md
  2. 26
      .planning/STATE.md
  3. 204
      .planning/phases/14-fix-drag-connect-bugs/14-01-PLAN.md
  4. 109
      .planning/phases/14-fix-drag-connect-bugs/14-01-SUMMARY.md

12
.planning/ROADMAP.md

@ -11,7 +11,7 @@ None
## Milestones
- ✅ **v1.0 Multi-Provider Support** - Phases 1-6 (shipped 2026-01-11)
- 🚧 **v1.1 Improvements** - Phases 7-12 (in progress)
- **v1.1 Improvements** - Phases 7-14 (shipped 2026-01-12)
## Phases
@ -92,7 +92,7 @@ Plans:
</details>
### 🚧 v1.1 Improvements (In Progress)
### ✅ v1.1 Improvements (Shipped 2026-01-12)
**Milestone Goal:** Fix connection issues, improve error visibility, add video history, auto-size nodes, and polish UI
@ -168,16 +168,16 @@ Plans:
Plans:
- [x] 13-01: Add MD5 content hashing and deduplication to save-generation API
#### Phase 14: Fix Drag-Connect Node Creation Bugs
#### Phase 14: Fix Drag-Connect Node Creation Bugs
**Goal**: Fix bugs with nodes created via drag-connect: (1) connection vanishes after selecting model from browser, (2) defaults to Gemini with missing model selector in header
**Depends on**: Phase 13
**Research**: Unlikely (React Flow connection state, node creation flow)
**Research topics**: Connection state during node creation, model selection callbacks, createDefaultNodeData initialization
**Plans**: TBD
**Plans**: 1 plan
Plans:
- [ ] 14-01: TBD (run /gsd:plan-phase 14 to break down)
- [x] 14-01: Normalize dynamic handle IDs and fix connection persistence
## Progress
@ -199,4 +199,4 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 →
| 11. UI Polish | v1.1 | 1/1 | Complete | 2026-01-12 |
| 12. Model Improvements | v1.1 | 1/1 | Complete | 2026-01-12 |
| 13. Fix Duplicate Generations | v1.1 | 1/1 | Complete | 2026-01-12 |
| 14. Fix Drag-Connect Node Creation Bugs | v1.1 | 0/? | Not started | - |
| 14. Fix Drag-Connect Node Creation Bugs | v1.1 | 1/1 | Complete | 2026-01-12 |

26
.planning/STATE.md

@ -5,23 +5,23 @@
See: .planning/PROJECT.md (updated 2026-01-09)
**Core value:** Provider infrastructure that dynamically discovers models from external APIs, enabling users to access hundreds of image/video generation models without hardcoding schemas.
**Current focus:** Phase 14 - Fix Drag-Connect Node Creation Bugs
**Current focus:** Milestone v1.1 Complete
## Current Position
Phase: 13 of 14 (Fix Duplicate Generations)
Phase: 14 of 14 (Fix Drag-Connect Node Creation Bugs)
Plan: 1 of 1 complete
Status: Phase complete
Last activity: 2026-01-12 - Completed 13-01-PLAN.md
Status: Milestone complete
Last activity: 2026-01-12 - Completed 14-01-PLAN.md
Progress: ███████░░░ 55%
Progress: ██████████ 100%
## Performance Metrics
**Velocity:**
- Total plans completed: 21
- Average duration: 6.8 min
- Total execution time: 2.4 hours
- Total plans completed: 22
- Average duration: 6.6 min
- Total execution time: 2.5 hours
**By Phase:**
@ -40,9 +40,10 @@ Progress: ███████░░░ 55%
| 11. UI Polish | 1/1 | 8 min | 8 min |
| 12. Model Improvements | 1/1 | - | - |
| 13. Fix Duplicate Generations | 1/1 | 1 min | 1 min |
| 14. Fix Drag-Connect Bugs | 1/1 | 7 min | 7 min |
**Recent Trend:**
- Last 5 plans: 14 min, 12 min, 2 min, 8 min, 1 min
- Last 5 plans: 12 min, 2 min, 8 min, 1 min, 7 min
- Trend: Fast execution with established patterns
## Accumulated Context
@ -93,6 +94,9 @@ Recent decisions affecting current work:
- regenerateNode includes parameters in request body
- MD5 content hashing for generation deduplication (fast, collision resistance not critical)
- Hash prefix in filename for O(1) duplicate lookup
- Normalized handle IDs (image, text, image-0) for connection stability across model changes
- Handle-to-schema mapping built at execution time from inputSchema
- Placeholder handles (dimmed 30%) for input types not used by model, preserving connections
### Deferred Issues
@ -113,6 +117,6 @@ Recent decisions affecting current work:
## Session Continuity
Last session: 2026-01-12
Stopped at: Phase 13 Fix Duplicate Generations completed
Stopped at: Milestone v1.1 complete
Resume file: None
Next action: Plan Phase 14 (Fix Drag-Connect Node Creation Bugs)
Next action: Complete milestone (run /gsd:complete-milestone)

204
.planning/phases/14-fix-drag-connect-bugs/14-01-PLAN.md

@ -0,0 +1,204 @@
---
phase: 14-fix-drag-connect-bugs
plan: 01
type: execute
---
<objective>
Fix two bugs with nodes created via drag-connect:
1. Connection vanishes after selecting model from browser
2. Node defaults to Gemini with correct Browse button but connection to default handles breaks when model schema loads
**Root Cause Analysis:**
Bug 1 (Connection Vanishes):
- Node created via drag-connect gets default Gemini model (no `inputSchema`)
- Connection made to default handle IDs: `"image"` and `"text"`
- User clicks Browse → selects external model (Replicate/fal.ai)
- `handleBrowseModelSelect` updates `selectedModel`
- `ModelParameters` component loads schema → calls `handleInputsLoaded` → sets `inputSchema`
- Node re-renders with dynamic handles that have **different IDs** from schema (e.g., `"image_url"` instead of `"image"`)
- React Flow invalidates edges connected to non-existent handles → **connection vanishes**
Bug 2 is a symptom of Bug 1 - the node works fine with Gemini defaults, but switching to an external provider with dynamic schema causes the connection loss.
**Solution:**
When a user selects an external model on a node created via drag-connect, we need to either:
A) Remap existing connections to the new dynamic handle IDs, OR
B) Keep standard `"image"` and `"text"` handles for external models too (normalize schema handle IDs)
Option B is simpler and more robust - normalize all dynamic schema handles to use standard IDs. The schema already provides semantic type info ("image" vs "text"), so we don't need the provider-specific names as handle IDs.
Output: Connections persist when switching from default Gemini to external provider on drag-connect-created nodes.
</objective>
<execution_context>
@~/.claude/get-shit-done/workflows/execute-phase.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
**Key source files:**
@src/components/nodes/GenerateImageNode.tsx - Dynamic handle rendering (lines 464-550)
@src/components/WorkflowCanvas.tsx - Connection handling, handleMenuSelect (lines 529-646)
@src/components/nodes/ModelParameters.tsx - Schema fetching and input loading
**Current behavior:**
1. `handleMenuSelect` creates node with `addNode(nodeType, flowPosition)` - no initial data
2. Node gets default Gemini with handles `id="image"` and `id="text"`
3. Connection made to default handle IDs
4. User selects external model → `handleInputsLoaded` sets `inputSchema`
5. Node renders dynamic handles with schema-specific IDs (e.g., `"image_url"`, `"prompt"`)
6. Connection to `"image"` or `"text"` becomes invalid → edge removed
**Target behavior:**
- Dynamic handles use standard IDs (`"image"`, `"text"`) regardless of schema
- Schema still provides semantic info but doesn't change handle IDs
- Connections persist through model changes
</context>
<tasks>
<task type="auto">
<name>Task 1: Normalize dynamic handle IDs to standard values</name>
<files>src/components/nodes/GenerateImageNode.tsx</files>
<action>
Modify the dynamic handle rendering logic (lines 464-510) to use standard handle IDs instead of schema-specific names:
1. In the dynamic handle rendering section, change `id={input.name}` to use standard IDs:
- For image inputs: use `"image"` (or `"image-{index}"` if multiple)
- For text inputs: use `"text"` (or `"text-{index}"` if multiple)
2. Update the handle key to use a combination of type and index for uniqueness
3. The schema `input.name` is still used for:
- `title` attribute (tooltip)
- Label display
- Parameter mapping during execution (stored in nodeData, not handle ID)
This ensures connections made to `"image"` or `"text"` remain valid when schema loads.
Example change:
```typescript
// Before:
<Handle
type="target"
position={Position.Left}
id={input.name} // e.g., "image_url"
...
/>
// After:
<Handle
type="target"
position={Position.Left}
id={imageInputs.length > 1 ? `image-${imageIndex}` : "image"} // Standard ID
...
/>
```
</action>
<verify>
1. Create node via drag-connect from image output
2. Connection appears with default Gemini handles
3. Click Browse → select Replicate model
4. Connection persists after schema loads
</verify>
<done>
- Dynamic handles use standard IDs: "image", "text" (or indexed if multiple)
- Schema input names preserved for labels and tooltips
- Connections persist through model changes
</done>
</task>
<task type="auto">
<name>Task 2: Update connection validation for normalized handles</name>
<files>src/components/WorkflowCanvas.tsx</files>
<action>
Verify and update `getHandleType` and `findCompatibleHandle` functions to work with normalized handle IDs:
1. `getHandleType` (lines 63-73): May need updates if we use indexed handles like `"image-0"`
- Add pattern matching for indexed handles: `if (handleId.startsWith("image")) return "image"`
2. `findCompatibleHandle` (lines 327-341): Update to return standard handle IDs
- When finding compatible input handle, return `"image"` or `"text"` instead of schema name
3. `handleMenuSelect` (lines 544-646): Already uses `"image"` and `"text"` for targetHandleId, so should work as-is
The key insight: by normalizing handle IDs in the node, all existing connection logic that expects `"image"` and `"text"` will continue to work.
</action>
<verify>
1. Drag connection from prompt node's text output
2. Drop on empty space → select "Generate Image"
3. Connection creates to text handle
4. Browse → select fal.ai model with text input
5. Connection persists (text handle still valid)
</verify>
<done>
- getHandleType handles indexed handle IDs
- findCompatibleHandle returns normalized IDs
- Multi-input models (multiple images) work correctly
</done>
</task>
<task type="auto">
<name>Task 3: Update execution to map normalized handles to schema names</name>
<files>src/store/workflowStore.ts, src/app/api/generate/route.ts</files>
<action>
Ensure the execution pipeline correctly maps normalized handle IDs back to schema parameter names:
1. In `getConnectedInputs` (workflowStore.ts): Check if it needs to map handle IDs to schema names
- Currently uses handle IDs directly for dynamicInputs
- May need to look up schema to get the actual parameter name
2. In `/api/generate/route.ts`: Verify parameter mapping
- Check how dynamicInputs are passed to provider APIs
- Ensure the provider receives the correct parameter names (e.g., "image_url" not "image")
3. Store the schema input name mapping in nodeData for execution:
- `inputSchema` already has `{ name, type, label }`
- Execution can look up: "image" handle → first image input from schema → use schema name for API
If execution already uses nodeData.inputSchema for parameter names (not handle IDs), this task may be minimal.
</action>
<verify>
1. Create node via drag-connect
2. Connect image and text inputs
3. Select external model (Replicate/fal.ai)
4. Run workflow
5. Verify API call uses correct parameter names from schema
</verify>
<done>
- Execution maps normalized handle IDs to schema parameter names
- Provider APIs receive correct parameter names
- No regression in existing workflows
</done>
</task>
</tasks>
<verification>
Before declaring phase complete:
- [ ] `npm run build` succeeds without errors
- [ ] Drag-connect from image output → Generate Image → connection persists
- [ ] Browse → select external model → connection still persists
- [ ] Drag-connect from text output → Generate Image → connection persists after model change
- [ ] Execute workflow with drag-connect-created node → works correctly
- [ ] Existing workflows (created via action bar) still work
- [ ] Multiple input models (if any) handle correctly
</verification>
<success_criteria>
- All tasks completed
- All verification checks pass
- Connections persist when switching models on drag-connect nodes
- No regression in existing functionality
- External providers work correctly with normalized handles
</success_criteria>
<output>
After completion, create `.planning/phases/14-fix-drag-connect-bugs/14-01-SUMMARY.md`
</output>

109
.planning/phases/14-fix-drag-connect-bugs/14-01-SUMMARY.md

@ -0,0 +1,109 @@
---
phase: 14-fix-drag-connect-bugs
plan: 01
subsystem: ui
tags: [react-flow, handles, connections, node-editor]
requires:
- phase: 03-generate-node-refactor
provides: Dynamic handle rendering from model schema
- phase: 04-model-search-dialog
provides: Model selection and schema loading
provides:
- Stable drag-connect node creation that persists through model selection
- Normalized handle ID system for multi-provider compatibility
- Handle-to-schema mapping for API parameter passing
affects: [future-node-types, connection-system-improvements]
tech-stack:
added: []
patterns:
- "Normalized handle IDs (image, text, image-0, text-0) for connection stability"
- "data-schema-name attribute for preserving API parameter names"
- "handleToSchemaName mapping in execution for API compatibility"
key-files:
created: []
modified:
- src/components/nodes/GenerateImageNode.tsx
- src/components/nodes/GenerateVideoNode.tsx
- src/components/WorkflowCanvas.tsx
- src/store/workflowStore.ts
key-decisions:
- "Use normalized handle IDs instead of schema names for React Flow handles"
- "Store schema name in data-schema-name attribute for reference"
- "Build handleToSchemaName mapping at execution time from inputSchema"
patterns-established:
- "Handle normalization: single input uses type name (image), multiple use indexed (image-0)"
- "Schema mapping: inputSchema drives normalized ID to schema name conversion"
issues-created: []
duration: 7min
completed: 2026-01-12
---
# Phase 14 Plan 01: Fix Drag-Connect Node Creation Bugs Summary
**Placeholder handles ensure connections persist when selecting models that don't use all input types**
## Performance
- **Duration:** 12 min
- **Started:** 2026-01-12T10:11:43Z
- **Completed:** 2026-01-12T10:23:00Z
- **Tasks:** 3
- **Files modified:** 4
## Accomplishments
- Always render "image" and "text" handles even when model schema doesn't include them
- Placeholder handles (dimmed at 30% opacity) preserve connections for models that don't use that input type
- Normalized dynamic handle IDs to use standard values ("image", "text") instead of schema-specific names
- Updated connection validation to return normalized handle IDs when finding compatible targets
- Added handle-to-schema mapping in execution to preserve API parameter compatibility
## Task Commits
Each task was committed atomically:
1. **Task 1: Normalize handle IDs + placeholder handles** - `7548e5a` (fix)
2. **Task 2: Update connection validation** - `714b60b` (fix)
3. **Task 3: Map handles to schema names in execution** - `5643cb8` (feat)
## Files Created/Modified
- `src/components/nodes/GenerateImageNode.tsx` - Placeholder handles for missing inputs, normalized IDs
- `src/components/nodes/GenerateVideoNode.tsx` - Same fix for video nodes
- `src/components/WorkflowCanvas.tsx` - findCompatibleHandle returns normalized IDs
- `src/store/workflowStore.ts` - getConnectedInputs builds handleToSchemaName mapping
## Decisions Made
- **Placeholder handles**: Always render "image" and "text" handles, dimmed when model doesn't use them
- **Normalized handle naming**: Single input of type uses base name ("image"), multiple use indexed ("image-0", "image-1")
- **Schema name preservation**: Stored in data-schema-name attribute for debugging/reference
- **Execution mapping**: Build mapping at runtime from inputSchema rather than storing in edge data
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 1 - Bug] Handle disappearance with text-to-image models**
- **Found during:** Testing after initial fix
- **Issue:** Text-to-image models (FLUX, etc.) have no image input in schema, causing image handle to disappear
- **Fix:** Always render placeholder handles for missing input types (dimmed at 30% opacity)
- **Files modified:** GenerateImageNode.tsx, GenerateVideoNode.tsx
- **Verification:** Build passes, handles persist through model selection
## Issues Encountered
None
## Next Phase Readiness
- Phase 14 complete (single plan phase)
- Milestone v1.1 complete - all 8 phases finished
- Ready for `/gsd:complete-milestone`
---
*Phase: 14-fix-drag-connect-bugs*
*Completed: 2026-01-12*
Loading…
Cancel
Save