Browse Source

feat(44-02): add Switch execution and toggle-aware data flow

- Export executeSwitch from execution/index.ts
- Import executeSwitch in workflowStore.ts
- Add switch case to executeWorkflow (after router)
- Add switch case to regenerateNode (after router)
- Import SwitchNodeData in connectedInputs.ts
- Add Switch passthrough logic with toggle filtering in connectedInputs.ts
  - Disabled outputs block data flow (no downstream input)
  - Enabled outputs recursively traverse upstream (same pattern as Router)
  - Edge type determined by switch inputType field

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 5 months ago
parent
commit
dbfeb22647
  1. 1
      src/store/execution/index.ts
  2. 32
      src/store/utils/connectedInputs.ts
  3. 7
      src/store/workflowStore.ts

1
src/store/execution/index.ts

@ -18,6 +18,7 @@ export {
executeImageCompare,
executeGlbViewer,
executeRouter,
executeSwitch,
} from "./simpleNodeExecutors";
export { executeNanoBanana } from "./nanoBananaExecutor";

32
src/store/utils/connectedInputs.ts

@ -24,6 +24,7 @@ import {
PromptConstructorNodeData,
LLMGenerateNodeData,
GLBViewerNodeData,
SwitchNodeData,
} from "@/types";
/**
@ -191,6 +192,37 @@ export function getConnectedInputsPure(
return; // Skip normal getSourceOutput processing for this edge
}
// Switch passthrough — traverse upstream if output is enabled
if (sourceNode.type === "switch") {
const switchData = sourceNode.data as SwitchNodeData;
const switchId = edge.sourceHandle; // Handle ID matches switch entry id
const switchEntry = switchData.switches?.find(s => s.id === switchId);
// Skip disabled outputs — data does not flow through disabled switches
if (!switchEntry || !switchEntry.enabled) {
return; // Block this path
}
// Enabled switch: recursively get upstream data (same pattern as router)
const switchInputs = getConnectedInputsPure(sourceNode.id, nodes, edges, _visited);
const edgeType = switchData.inputType;
if (edgeType === "image") {
images.push(...switchInputs.images);
} else if (edgeType === "text") {
if (switchInputs.text) text = switchInputs.text;
} else if (edgeType === "video") {
videos.push(...switchInputs.videos);
} else if (edgeType === "audio") {
audio.push(...switchInputs.audio);
} else if (edgeType === "3d") {
if (switchInputs.model3d) model3d = switchInputs.model3d;
} else if (edgeType === "easeCurve") {
if (switchInputs.easeCurve) easeCurve = switchInputs.easeCurve;
}
return; // Skip normal getSourceOutput processing
}
const handleId = edge.targetHandle;
const { type, value } = getSourceOutput(
sourceNode,

7
src/store/workflowStore.ts

@ -78,6 +78,7 @@ import {
executeVideoFrameGrab,
executeGlbViewer,
executeRouter,
executeSwitch,
} from "./execution";
import type { NodeExecutionContext } from "./execution";
export type { LevelGroup } from "./utils/executionUtils";
@ -1012,6 +1013,9 @@ const workflowStoreImpl: StateCreator<WorkflowStore> = (set, get) => ({
case "router":
await executeRouter(executionCtx);
break;
case "switch":
await executeSwitch(executionCtx);
break;
}
}; // End of executeSingleNode helper
@ -1333,6 +1337,9 @@ const workflowStoreImpl: StateCreator<WorkflowStore> = (set, get) => ({
case "router":
await executeRouter(executionCtx);
break;
case "switch":
await executeSwitch(executionCtx);
break;
}
};

Loading…
Cancel
Save