Skip to content

Commit e6075c7

Browse files
committed
Split TaskInput and TaskOutput Node Ids from Input and Output Node Ids
1 parent 240932c commit e6075c7

File tree

6 files changed

+160
-109
lines changed

6 files changed

+160
-109
lines changed

src/components/shared/ReactFlow/FlowCanvas/IONode/IONode.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ const IONode = ({ type, data, selected = false }: IONodeProps) => {
176176
</InlineStack>
177177
</BlockStack>
178178
<Handle
179+
id={nodeHandleId}
179180
type={handleType}
180181
position={handlePosition}
181182
className={cn(handleDefaultClassName, handleClassName)}

src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskNodeCard/Handles.tsx

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
TooltipContent,
1212
TooltipTrigger,
1313
} from "@/components/ui/tooltip";
14+
import { useNodeManager } from "@/hooks/useNodeManager";
1415
import { cn } from "@/lib/utils";
1516
import { useTaskNode } from "@/providers/TaskNodeProvider";
1617
import type { InputSpec, OutputSpec } from "@/utils/componentSpec";
@@ -33,7 +34,8 @@ export const InputHandle = ({
3334
onLabelClick,
3435
onHandleSelectionChange,
3536
}: InputHandleProps) => {
36-
const { nodeId, state, name } = useTaskNode();
37+
const { getTaskInputNodeId } = useNodeManager();
38+
const { taskId, nodeId, state, name } = useTaskNode();
3739

3840
const fromHandle = useConnection((connection) => connection.fromHandle?.id);
3941
const toHandle = useConnection((connection) => connection.toHandle?.id);
@@ -45,7 +47,7 @@ export const InputHandle = ({
4547
const [selected, setSelected] = useState(false);
4648
const [active, setActive] = useState(false);
4749

48-
const handleId = getInputHandleId(input.name);
50+
const handleId = getTaskInputNodeId(taskId, input.name);
4951

5052
const missing = invalid ? "bg-red-700!" : "bg-gray-500!";
5153
const hasValue = value !== undefined && value !== null;
@@ -228,7 +230,8 @@ export const OutputHandle = ({
228230
onLabelClick,
229231
onHandleSelectionChange,
230232
}: OutputHandleProps) => {
231-
const { nodeId, state, name } = useTaskNode();
233+
const { getTaskOutputNodeId } = useNodeManager();
234+
const { taskId, nodeId, state, name } = useTaskNode();
232235

233236
const fromHandle = useConnection((connection) => connection.fromHandle?.id);
234237
const toHandle = useConnection((connection) => connection.toHandle?.id);
@@ -240,7 +243,7 @@ export const OutputHandle = ({
240243
const [selected, setSelected] = useState(false);
241244
const [active, setActive] = useState(false);
242245

243-
const handleId = getOutputHandleId(output.name);
246+
const handleId = getTaskOutputNodeId(taskId, output.name);
244247
const hasValue = value !== undefined && value !== "" && value !== null;
245248

246249
const handleHandleClick = useCallback(
@@ -374,14 +377,6 @@ export const OutputHandle = ({
374377
);
375378
};
376379

377-
const getOutputHandleId = (outputName: string) => {
378-
return `output_${outputName}`;
379-
};
380-
381-
const getInputHandleId = (inputName: string) => {
382-
return `input_${inputName}`;
383-
};
384-
385380
const skipHandleDeselect = (e: MouseEvent) => {
386381
let el = e.target as HTMLElement | null;
387382
while (el) {

src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskNodeCard/TaskNodeOutputs.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { isValidFilterRequest } from "@/providers/ComponentLibraryProvider/types
88
import { useTaskNode } from "@/providers/TaskNodeProvider";
99
import type { OutputSpec } from "@/utils/componentSpec";
1010
import { ComponentSearchFilter } from "@/utils/constants";
11-
import { outputNameToOutputId } from "@/utils/nodes/conversions";
1211
import { checkArtifactMatchesSearchFilters } from "@/utils/searchUtils";
1312

1413
import { OutputHandle } from "./Handles";
@@ -24,8 +23,8 @@ export function TaskNodeOutputs({
2423
expanded,
2524
onBackgroundClick,
2625
}: TaskNodeOutputsProps) {
27-
const { getOutputNodeId } = useNodeManager();
28-
const { nodeId, outputs, state, select } = useTaskNode();
26+
const { getTaskOutputNodeId } = useNodeManager();
27+
const { taskId, nodeId, outputs, state, select } = useTaskNode();
2928
const {
3029
highlightSearchFilter,
3130
resetSearchFilter,
@@ -42,8 +41,7 @@ export function TaskNodeOutputs({
4241
edges.some(
4342
(edge) =>
4443
edge.source === nodeId &&
45-
edge.sourceHandle ===
46-
getOutputNodeId(outputNameToOutputId(output.name)),
44+
edge.sourceHandle === getTaskOutputNodeId(taskId, output.name),
4745
),
4846
);
4947

@@ -141,7 +139,7 @@ export function TaskNodeOutputs({
141139
}
142140

143141
const output = outputs.find(
144-
(o) => getOutputNodeId(outputNameToOutputId(o.name)) === fromHandle?.id,
142+
(o) => getTaskOutputNodeId(taskId, o.name) === fromHandle?.id,
145143
);
146144

147145
if (!output) return;

src/components/shared/ReactFlow/FlowCanvas/utils/addAndConnectNode.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export function addAndConnectNode({
118118
}
119119

120120
const inputId = inputNameToInputId(handleName);
121-
targetHandleId = nodeManager.getNodeId(inputId, "input");
121+
targetHandleId = nodeManager.getNodeId(inputId, "taskInput");
122122
} else if (toHandleType === "output") {
123123
const handleName = componentRef.spec?.outputs?.find(
124124
(io) => io.type === connectionType,
@@ -128,7 +128,7 @@ export function addAndConnectNode({
128128
}
129129

130130
const outputId = outputNameToOutputId(handleName);
131-
targetHandleId = nodeManager.getNodeId(outputId, "output");
131+
targetHandleId = nodeManager.getNodeId(outputId, "taskOutput");
132132
}
133133

134134
// 4. Build a Connection object and use handleConnection to add the edge
Lines changed: 137 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,159 @@
11
import type { Connection } from "@xyflow/react";
22

3-
import type { NodeManager } from "@/nodeManager";
3+
import type { NodeManager, NodeType } from "@/nodeManager";
44
import type {
55
GraphInputArgument,
66
GraphSpec,
77
TaskOutputArgument,
88
} from "@/utils/componentSpec";
9-
import { inputIdToInputName } from "@/utils/nodes/conversions";
9+
import {
10+
inputIdToInputName,
11+
outputIdToOutputName,
12+
} from "@/utils/nodes/conversions";
1013

1114
import { setGraphOutputValue } from "./setGraphOutputValue";
1215
import { setTaskArgument } from "./setTaskArgument";
1316

17+
type NodeInfo = {
18+
id: string;
19+
handle?: string;
20+
type?: NodeType;
21+
};
22+
1423
export const handleConnection = (
1524
graphSpec: GraphSpec,
1625
connection: Connection,
1726
nodeManager: NodeManager,
1827
) => {
19-
const targetTaskInputName = connection.targetHandle?.replace(/^input_/, "");
20-
const sourceTaskOutputName = connection.sourceHandle?.replace(/^output_/, "");
21-
22-
const targetId = nodeManager.getTaskId(connection.target);
2328
const sourceId = nodeManager.getTaskId(connection.source);
29+
const targetId = nodeManager.getTaskId(connection.target);
2430

25-
if (sourceTaskOutputName !== undefined) {
26-
if (!sourceId) {
27-
console.error(
28-
"addConnection: Could not find task ID for source node: ",
29-
connection.source,
30-
);
31-
return graphSpec;
32-
}
33-
34-
const taskOutputArgument: TaskOutputArgument = {
35-
taskOutput: {
36-
taskId: sourceId,
37-
outputName: sourceTaskOutputName,
38-
},
39-
};
40-
41-
if (targetTaskInputName !== undefined) {
42-
if (!targetId) {
43-
console.error(
44-
"addConnection: Could not find Input ID for target node: ",
45-
connection.target,
46-
);
47-
return graphSpec;
48-
}
49-
50-
return setTaskArgument(
51-
graphSpec,
52-
targetId,
53-
targetTaskInputName,
54-
taskOutputArgument,
55-
);
56-
} else {
57-
if (!targetId) {
58-
console.error(
59-
"addConnection: Could not find Output ID for target node: ",
60-
connection.target,
61-
);
62-
return graphSpec;
63-
}
64-
65-
return setGraphOutputValue(graphSpec, targetId, taskOutputArgument);
66-
// TODO: Perhaps propagate type information
67-
}
68-
} else {
69-
if (!sourceId) {
70-
console.error(
71-
"addConnection: Could not find task ID for source node: ",
72-
connection.source,
73-
);
31+
if (!sourceId || !targetId) {
32+
console.warn("Source or Target ID is missing in the connection.");
33+
return graphSpec;
34+
}
35+
36+
if (sourceId === targetId) {
37+
console.warn(
38+
"Source and Target IDs are the same. Self-connections are not allowed.",
39+
);
40+
return graphSpec;
41+
}
42+
43+
const sourceHandleId = connection.sourceHandle
44+
? nodeManager.getTaskId(connection.sourceHandle)
45+
: undefined;
46+
47+
const targetHandleId = connection.targetHandle
48+
? nodeManager.getTaskId(connection.targetHandle)
49+
: undefined;
50+
51+
const source: NodeInfo = {
52+
id: sourceId,
53+
handle: sourceHandleId,
54+
type: nodeManager.getNodeType(connection.source),
55+
};
56+
57+
const target: NodeInfo = {
58+
id: targetId,
59+
handle: targetHandleId,
60+
type: nodeManager.getNodeType(connection.target),
61+
};
62+
63+
const connectionType = `${source.type}_to_${target.type}` as const;
64+
65+
switch (connectionType) {
66+
case "input_to_task":
67+
return handleGraphInputToTask(graphSpec, source, target);
68+
69+
case "task_to_task":
70+
return handleTaskToTask(graphSpec, source, target);
71+
72+
case "task_to_output":
73+
return handleTaskToGraphOutput(graphSpec, source, target);
74+
75+
default:
76+
console.warn("Unsupported connection pattern:", connectionType);
7477
return graphSpec;
75-
}
76-
const inputName = inputIdToInputName(sourceId);
77-
const graphInputArgument: GraphInputArgument = {
78-
graphInput: {
79-
inputName: inputName,
80-
},
81-
};
82-
if (targetTaskInputName !== undefined) {
83-
if (!targetId) {
84-
console.error(
85-
"addConnection: Could not find Output ID for target node: ",
86-
connection.target,
87-
);
88-
return graphSpec;
89-
}
90-
91-
return setTaskArgument(
92-
graphSpec,
93-
targetId,
94-
targetTaskInputName,
95-
graphInputArgument,
96-
);
97-
} else {
98-
console.error(
99-
"addConnection: Cannot directly connect graph input to graph output: ",
100-
connection,
101-
);
102-
}
10378
}
79+
};
80+
81+
const handleGraphInputToTask = (
82+
graphSpec: GraphSpec,
83+
source: NodeInfo,
84+
target: NodeInfo,
85+
): GraphSpec => {
86+
if (!target.handle) {
87+
console.warn("Handle ID is missing for target task node.");
88+
return graphSpec;
89+
}
90+
91+
const sourceInputName = inputIdToInputName(source.id);
92+
const targetInputName = inputIdToInputName(target.handle);
93+
94+
const graphInputArgument: GraphInputArgument = {
95+
graphInput: { inputName: sourceInputName },
96+
};
97+
98+
return setTaskArgument(
99+
graphSpec,
100+
target.id,
101+
targetInputName,
102+
graphInputArgument,
103+
);
104+
};
105+
106+
const handleTaskToTask = (
107+
graphSpec: GraphSpec,
108+
source: NodeInfo,
109+
target: NodeInfo,
110+
): GraphSpec => {
111+
if (!source.handle) {
112+
console.warn("Handle ID is missing for source task node.");
113+
return graphSpec;
114+
}
115+
116+
if (!target.handle) {
117+
console.warn("Handle ID is missing for target task node.");
118+
return graphSpec;
119+
}
120+
121+
const sourceOutputName = outputIdToOutputName(source.handle);
122+
const targetInputName = inputIdToInputName(target.handle);
123+
124+
const taskOutputArgument: TaskOutputArgument = {
125+
taskOutput: {
126+
taskId: source.id,
127+
outputName: sourceOutputName,
128+
},
129+
};
130+
131+
return setTaskArgument(
132+
graphSpec,
133+
target.id,
134+
targetInputName,
135+
taskOutputArgument,
136+
);
137+
};
138+
139+
const handleTaskToGraphOutput = (
140+
graphSpec: GraphSpec,
141+
source: NodeInfo,
142+
target: NodeInfo,
143+
): GraphSpec => {
144+
if (!source.handle) {
145+
console.warn("Handle ID is missing for source task node.");
146+
return graphSpec;
147+
}
148+
149+
const sourceOutputName = outputIdToOutputName(source.handle);
150+
151+
const taskOutputArgument: TaskOutputArgument = {
152+
taskOutput: {
153+
taskId: source.id,
154+
outputName: sourceOutputName,
155+
},
156+
};
104157

105-
// GraphSpec was not updated (due to an error or other reason)
106-
return graphSpec;
158+
return setGraphOutputValue(graphSpec, target.id, taskOutputArgument);
107159
};

0 commit comments

Comments
 (0)