griptape-nodes 0.55.0__py3-none-any.whl → 0.56.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- griptape_nodes/cli/commands/init.py +88 -0
- griptape_nodes/cli/commands/models.py +2 -0
- griptape_nodes/cli/shared.py +1 -0
- griptape_nodes/exe_types/core_types.py +104 -5
- griptape_nodes/exe_types/node_types.py +9 -12
- griptape_nodes/machines/control_flow.py +10 -0
- griptape_nodes/machines/dag_builder.py +21 -2
- griptape_nodes/machines/parallel_resolution.py +25 -10
- griptape_nodes/node_library/workflow_registry.py +73 -3
- griptape_nodes/retained_mode/events/execution_events.py +12 -2
- griptape_nodes/retained_mode/events/flow_events.py +58 -0
- griptape_nodes/retained_mode/events/resource_events.py +290 -0
- griptape_nodes/retained_mode/events/workflow_events.py +57 -2
- griptape_nodes/retained_mode/griptape_nodes.py +9 -1
- griptape_nodes/retained_mode/managers/flow_manager.py +678 -12
- griptape_nodes/retained_mode/managers/library_manager.py +13 -19
- griptape_nodes/retained_mode/managers/model_manager.py +184 -83
- griptape_nodes/retained_mode/managers/node_manager.py +3 -3
- griptape_nodes/retained_mode/managers/os_manager.py +118 -1
- griptape_nodes/retained_mode/managers/resource_components/__init__.py +1 -0
- griptape_nodes/retained_mode/managers/resource_components/capability_field.py +41 -0
- griptape_nodes/retained_mode/managers/resource_components/comparator.py +18 -0
- griptape_nodes/retained_mode/managers/resource_components/resource_instance.py +236 -0
- griptape_nodes/retained_mode/managers/resource_components/resource_type.py +79 -0
- griptape_nodes/retained_mode/managers/resource_manager.py +306 -0
- griptape_nodes/retained_mode/managers/resource_types/__init__.py +1 -0
- griptape_nodes/retained_mode/managers/resource_types/cpu_resource.py +108 -0
- griptape_nodes/retained_mode/managers/resource_types/os_resource.py +87 -0
- griptape_nodes/retained_mode/managers/settings.py +5 -0
- griptape_nodes/retained_mode/managers/sync_manager.py +10 -3
- griptape_nodes/retained_mode/managers/workflow_manager.py +359 -261
- {griptape_nodes-0.55.0.dist-info → griptape_nodes-0.56.0.dist-info}/METADATA +1 -1
- {griptape_nodes-0.55.0.dist-info → griptape_nodes-0.56.0.dist-info}/RECORD +35 -25
- {griptape_nodes-0.55.0.dist-info → griptape_nodes-0.56.0.dist-info}/WHEEL +1 -1
- {griptape_nodes-0.55.0.dist-info → griptape_nodes-0.56.0.dist-info}/entry_points.txt +0 -0
|
@@ -3,7 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from enum import StrEnum
|
|
5
5
|
from queue import Queue
|
|
6
|
-
from typing import TYPE_CHECKING, NamedTuple, cast
|
|
6
|
+
from typing import TYPE_CHECKING, Any, NamedTuple, cast
|
|
7
|
+
from uuid import uuid4
|
|
7
8
|
|
|
8
9
|
from griptape_nodes.exe_types.connections import Connections
|
|
9
10
|
from griptape_nodes.exe_types.core_types import (
|
|
@@ -19,6 +20,7 @@ from griptape_nodes.machines.control_flow import CompleteState, ControlFlowMachi
|
|
|
19
20
|
from griptape_nodes.machines.dag_builder import DagBuilder
|
|
20
21
|
from griptape_nodes.machines.parallel_resolution import ParallelResolutionMachine
|
|
21
22
|
from griptape_nodes.machines.sequential_resolution import SequentialResolutionMachine
|
|
23
|
+
from griptape_nodes.node_library.library_registry import LibraryNameAndVersion, LibraryRegistry
|
|
22
24
|
from griptape_nodes.retained_mode.events.base_events import (
|
|
23
25
|
ExecutionEvent,
|
|
24
26
|
ExecutionGriptapeNodeEvent,
|
|
@@ -33,6 +35,10 @@ from griptape_nodes.retained_mode.events.connection_events import (
|
|
|
33
35
|
DeleteConnectionRequest,
|
|
34
36
|
DeleteConnectionResultFailure,
|
|
35
37
|
DeleteConnectionResultSuccess,
|
|
38
|
+
IncomingConnection,
|
|
39
|
+
ListConnectionsForNodeRequest,
|
|
40
|
+
ListConnectionsForNodeResultSuccess,
|
|
41
|
+
OutgoingConnection,
|
|
36
42
|
)
|
|
37
43
|
from griptape_nodes.retained_mode.events.execution_events import (
|
|
38
44
|
CancelFlowRequest,
|
|
@@ -48,6 +54,7 @@ from griptape_nodes.retained_mode.events.execution_events import (
|
|
|
48
54
|
GetIsFlowRunningRequest,
|
|
49
55
|
GetIsFlowRunningResultFailure,
|
|
50
56
|
GetIsFlowRunningResultSuccess,
|
|
57
|
+
InvolvedNodesEvent,
|
|
51
58
|
SingleExecutionStepRequest,
|
|
52
59
|
SingleExecutionStepResultFailure,
|
|
53
60
|
SingleExecutionStepResultSuccess,
|
|
@@ -88,6 +95,9 @@ from griptape_nodes.retained_mode.events.flow_events import (
|
|
|
88
95
|
ListNodesInFlowRequest,
|
|
89
96
|
ListNodesInFlowResultFailure,
|
|
90
97
|
ListNodesInFlowResultSuccess,
|
|
98
|
+
PackageNodeAsSerializedFlowRequest,
|
|
99
|
+
PackageNodeAsSerializedFlowResultFailure,
|
|
100
|
+
PackageNodeAsSerializedFlowResultSuccess,
|
|
91
101
|
SerializedFlowCommands,
|
|
92
102
|
SerializeFlowToCommandsRequest,
|
|
93
103
|
SerializeFlowToCommandsResultFailure,
|
|
@@ -97,14 +107,18 @@ from griptape_nodes.retained_mode.events.flow_events import (
|
|
|
97
107
|
SetFlowMetadataResultSuccess,
|
|
98
108
|
)
|
|
99
109
|
from griptape_nodes.retained_mode.events.node_events import (
|
|
110
|
+
CreateNodeRequest,
|
|
100
111
|
DeleteNodeRequest,
|
|
101
112
|
DeleteNodeResultFailure,
|
|
102
113
|
DeserializeNodeFromCommandsRequest,
|
|
114
|
+
SerializedNodeCommands,
|
|
103
115
|
SerializedParameterValueTracker,
|
|
104
116
|
SerializeNodeToCommandsRequest,
|
|
105
117
|
SerializeNodeToCommandsResultSuccess,
|
|
106
118
|
)
|
|
107
119
|
from griptape_nodes.retained_mode.events.parameter_events import (
|
|
120
|
+
AddParameterToNodeRequest,
|
|
121
|
+
AlterParameterDetailsRequest,
|
|
108
122
|
SetParameterValueRequest,
|
|
109
123
|
)
|
|
110
124
|
from griptape_nodes.retained_mode.events.validation_events import (
|
|
@@ -121,6 +135,7 @@ from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
|
121
135
|
if TYPE_CHECKING:
|
|
122
136
|
from griptape_nodes.retained_mode.events.base_events import ResultPayload
|
|
123
137
|
from griptape_nodes.retained_mode.managers.event_manager import EventManager
|
|
138
|
+
from griptape_nodes.retained_mode.managers.workflow_manager import WorkflowShapeNodes
|
|
124
139
|
|
|
125
140
|
logger = logging.getLogger("griptape_nodes")
|
|
126
141
|
|
|
@@ -138,6 +153,39 @@ class QueueItem(NamedTuple):
|
|
|
138
153
|
dag_execution_type: DagExecutionType
|
|
139
154
|
|
|
140
155
|
|
|
156
|
+
class ConnectionAnalysis(NamedTuple):
|
|
157
|
+
"""Analysis of connections separated by type (data vs control) when packaging nodes."""
|
|
158
|
+
|
|
159
|
+
incoming_data_connections: list[IncomingConnection]
|
|
160
|
+
incoming_control_connections: list[IncomingConnection]
|
|
161
|
+
outgoing_data_connections: list[OutgoingConnection]
|
|
162
|
+
outgoing_control_connections: list[OutgoingConnection]
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class PackageNodeInfo(NamedTuple):
|
|
166
|
+
"""Information about the node being packaged."""
|
|
167
|
+
|
|
168
|
+
package_node: BaseNode
|
|
169
|
+
package_flow_name: str
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class PackagingStartNodeResult(NamedTuple):
|
|
173
|
+
"""Result of creating start node commands and data connections for flow packaging."""
|
|
174
|
+
|
|
175
|
+
start_node_commands: SerializedNodeCommands
|
|
176
|
+
start_to_package_data_connections: list[SerializedFlowCommands.IndirectConnectionSerialization]
|
|
177
|
+
input_shape_data: WorkflowShapeNodes
|
|
178
|
+
start_node_parameter_value_commands: list[SerializedNodeCommands.IndirectSetParameterValueCommand]
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class PackagingEndNodeResult(NamedTuple):
|
|
182
|
+
"""Result of creating end node commands and data connections for flow packaging."""
|
|
183
|
+
|
|
184
|
+
end_node_commands: SerializedNodeCommands
|
|
185
|
+
package_to_end_data_connections: list[SerializedFlowCommands.IndirectConnectionSerialization]
|
|
186
|
+
output_shape_data: WorkflowShapeNodes
|
|
187
|
+
|
|
188
|
+
|
|
141
189
|
class FlowManager:
|
|
142
190
|
_name_to_parent_name: dict[str, str | None]
|
|
143
191
|
_flow_to_referenced_workflow_name: dict[ControlFlow, str]
|
|
@@ -181,6 +229,9 @@ class FlowManager:
|
|
|
181
229
|
event_manager.assign_manager_to_request_type(
|
|
182
230
|
DeserializeFlowFromCommandsRequest, self.on_deserialize_flow_from_commands
|
|
183
231
|
)
|
|
232
|
+
event_manager.assign_manager_to_request_type(
|
|
233
|
+
PackageNodeAsSerializedFlowRequest, self.on_package_node_as_serialized_flow_request
|
|
234
|
+
)
|
|
184
235
|
event_manager.assign_manager_to_request_type(FlushParameterChangesRequest, self.on_flush_request)
|
|
185
236
|
|
|
186
237
|
self._name_to_parent_name = {}
|
|
@@ -1012,6 +1063,593 @@ class FlowManager:
|
|
|
1012
1063
|
result = DeleteConnectionResultSuccess(result_details=details)
|
|
1013
1064
|
return result
|
|
1014
1065
|
|
|
1066
|
+
def on_package_node_as_serialized_flow_request(self, request: PackageNodeAsSerializedFlowRequest) -> ResultPayload: # noqa: PLR0911
|
|
1067
|
+
"""Handle request to package a node as a serialized flow.
|
|
1068
|
+
|
|
1069
|
+
Creates a self-contained flow with Start node -> Package node -> End node structure,
|
|
1070
|
+
where artificial start/end nodes match the package node's connections.
|
|
1071
|
+
"""
|
|
1072
|
+
# Step 1: Validate package node and flow
|
|
1073
|
+
package_node_info = self._validate_package_node_and_flow(request=request)
|
|
1074
|
+
if isinstance(package_node_info, PackageNodeAsSerializedFlowResultFailure):
|
|
1075
|
+
return package_node_info
|
|
1076
|
+
|
|
1077
|
+
# Step 2: Validate library and get version
|
|
1078
|
+
library_version = self._validate_and_get_library_info(request=request)
|
|
1079
|
+
if isinstance(library_version, PackageNodeAsSerializedFlowResultFailure):
|
|
1080
|
+
return library_version
|
|
1081
|
+
|
|
1082
|
+
# Step 3: Analyze package node connections
|
|
1083
|
+
connection_analysis = self._analyze_package_node_connections(
|
|
1084
|
+
package_node=package_node_info.package_node,
|
|
1085
|
+
node_name=package_node_info.package_node.name,
|
|
1086
|
+
)
|
|
1087
|
+
if isinstance(connection_analysis, PackageNodeAsSerializedFlowResultFailure):
|
|
1088
|
+
return connection_analysis
|
|
1089
|
+
|
|
1090
|
+
# Step 4: Serialize the package node
|
|
1091
|
+
unique_parameter_uuid_to_values = {}
|
|
1092
|
+
serialized_parameter_value_tracker = SerializedParameterValueTracker()
|
|
1093
|
+
serialized_package_result = self._serialize_package_node(
|
|
1094
|
+
node_name=package_node_info.package_node.name,
|
|
1095
|
+
package_node=package_node_info.package_node,
|
|
1096
|
+
unique_parameter_uuid_to_values=unique_parameter_uuid_to_values,
|
|
1097
|
+
serialized_parameter_value_tracker=serialized_parameter_value_tracker,
|
|
1098
|
+
)
|
|
1099
|
+
if isinstance(serialized_package_result, PackageNodeAsSerializedFlowResultFailure):
|
|
1100
|
+
return serialized_package_result
|
|
1101
|
+
|
|
1102
|
+
# Step 5: Create start node commands and data connections
|
|
1103
|
+
start_node_result = self._create_start_node_commands(
|
|
1104
|
+
request=request,
|
|
1105
|
+
incoming_data_connections=connection_analysis.incoming_data_connections,
|
|
1106
|
+
package_node=package_node_info.package_node,
|
|
1107
|
+
package_node_uuid=serialized_package_result.serialized_node_commands.node_uuid,
|
|
1108
|
+
library_version=library_version,
|
|
1109
|
+
unique_parameter_uuid_to_values=unique_parameter_uuid_to_values,
|
|
1110
|
+
serialized_parameter_value_tracker=serialized_parameter_value_tracker,
|
|
1111
|
+
)
|
|
1112
|
+
if isinstance(start_node_result, PackageNodeAsSerializedFlowResultFailure):
|
|
1113
|
+
return start_node_result
|
|
1114
|
+
|
|
1115
|
+
# Step 6: Create end node commands and data connections
|
|
1116
|
+
end_node_result = self._create_end_node_commands(
|
|
1117
|
+
request=request,
|
|
1118
|
+
package_node=package_node_info.package_node,
|
|
1119
|
+
package_node_uuid=serialized_package_result.serialized_node_commands.node_uuid,
|
|
1120
|
+
library_version=library_version,
|
|
1121
|
+
)
|
|
1122
|
+
if isinstance(end_node_result, PackageNodeAsSerializedFlowResultFailure):
|
|
1123
|
+
return end_node_result
|
|
1124
|
+
|
|
1125
|
+
# Step 7a: Create start node control flow connection
|
|
1126
|
+
start_control_connection_result = self._create_start_node_control_connection(
|
|
1127
|
+
entry_control_parameter_name=request.entry_control_parameter_name,
|
|
1128
|
+
start_node_uuid=start_node_result.start_node_commands.node_uuid,
|
|
1129
|
+
package_node_uuid=serialized_package_result.serialized_node_commands.node_uuid,
|
|
1130
|
+
package_node=package_node_info.package_node,
|
|
1131
|
+
)
|
|
1132
|
+
if isinstance(start_control_connection_result, PackageNodeAsSerializedFlowResultFailure):
|
|
1133
|
+
return start_control_connection_result
|
|
1134
|
+
|
|
1135
|
+
start_control_connections = [start_control_connection_result]
|
|
1136
|
+
|
|
1137
|
+
# Use only start control connections for now (end node control connections not implemented yet)
|
|
1138
|
+
control_flow_connections = start_control_connections
|
|
1139
|
+
|
|
1140
|
+
# Step 8: Assemble the complete serialized flow
|
|
1141
|
+
packaged_flow = self._assemble_serialized_flow(
|
|
1142
|
+
serialized_package_result=serialized_package_result,
|
|
1143
|
+
start_node_result=start_node_result,
|
|
1144
|
+
end_node_result=end_node_result,
|
|
1145
|
+
control_flow_connections=control_flow_connections,
|
|
1146
|
+
unique_parameter_uuid_to_values=unique_parameter_uuid_to_values,
|
|
1147
|
+
library_version=library_version,
|
|
1148
|
+
request=request,
|
|
1149
|
+
)
|
|
1150
|
+
|
|
1151
|
+
# Step 9: Build WorkflowShape from collected parameter shape data
|
|
1152
|
+
workflow_shape = GriptapeNodes.WorkflowManager().build_workflow_shape_from_parameter_info(
|
|
1153
|
+
input_node_params=start_node_result.input_shape_data, output_node_params=end_node_result.output_shape_data
|
|
1154
|
+
)
|
|
1155
|
+
|
|
1156
|
+
# Return success result
|
|
1157
|
+
return PackageNodeAsSerializedFlowResultSuccess(
|
|
1158
|
+
result_details=f'Successfully packaged node "{package_node_info.package_node.name}" from flow "{package_node_info.package_flow_name}" as serialized flow with start node type "{request.start_node_type}" and end node type "{request.end_node_type}" from library "{request.start_end_specific_library_name}".',
|
|
1159
|
+
serialized_flow_commands=packaged_flow,
|
|
1160
|
+
workflow_shape=workflow_shape,
|
|
1161
|
+
)
|
|
1162
|
+
|
|
1163
|
+
def _validate_package_node_and_flow( # noqa: PLR0911
|
|
1164
|
+
self, request: PackageNodeAsSerializedFlowRequest
|
|
1165
|
+
) -> PackageNodeInfo | PackageNodeAsSerializedFlowResultFailure:
|
|
1166
|
+
"""Validate and retrieve the package node and its parent flow."""
|
|
1167
|
+
node_name = request.node_name
|
|
1168
|
+
package_node = None
|
|
1169
|
+
|
|
1170
|
+
if node_name is None:
|
|
1171
|
+
# First check if we have a current node
|
|
1172
|
+
if not GriptapeNodes.ContextManager().has_current_node():
|
|
1173
|
+
details = (
|
|
1174
|
+
"Attempted to package node from Current Context. Failed because the Current Context was empty."
|
|
1175
|
+
)
|
|
1176
|
+
return PackageNodeAsSerializedFlowResultFailure(result_details=details)
|
|
1177
|
+
|
|
1178
|
+
# Get the current node from context
|
|
1179
|
+
package_node = GriptapeNodes.ContextManager().get_current_node()
|
|
1180
|
+
node_name = package_node.name
|
|
1181
|
+
|
|
1182
|
+
if package_node is None:
|
|
1183
|
+
try:
|
|
1184
|
+
package_node = GriptapeNodes.NodeManager().get_node_by_name(node_name)
|
|
1185
|
+
except ValueError as err:
|
|
1186
|
+
details = f"Attempted to package node '{node_name}'. Failed because node does not exist. Error: {err}."
|
|
1187
|
+
return PackageNodeAsSerializedFlowResultFailure(result_details=details)
|
|
1188
|
+
|
|
1189
|
+
# Get the flow containing this node using the same pattern
|
|
1190
|
+
package_flow_name = GriptapeNodes.NodeManager().get_node_parent_flow_by_name(node_name)
|
|
1191
|
+
if package_flow_name is None:
|
|
1192
|
+
details = f"Attempted to package node '{node_name}'. Failed because node is not assigned to any flow."
|
|
1193
|
+
return PackageNodeAsSerializedFlowResultFailure(result_details=details)
|
|
1194
|
+
|
|
1195
|
+
try:
|
|
1196
|
+
self.get_flow_by_name(flow_name=package_flow_name)
|
|
1197
|
+
except KeyError as err:
|
|
1198
|
+
details = f"Attempted to package node '{node_name}' from flow '{package_flow_name}'. Failed because flow does not exist. Error: {err}."
|
|
1199
|
+
return PackageNodeAsSerializedFlowResultFailure(result_details=details)
|
|
1200
|
+
|
|
1201
|
+
# Validate entry control parameter if specified
|
|
1202
|
+
if request.entry_control_parameter_name is not None:
|
|
1203
|
+
entry_param = package_node.get_parameter_by_name(request.entry_control_parameter_name)
|
|
1204
|
+
if entry_param is None:
|
|
1205
|
+
details = f"Attempted to package node '{node_name}' with entry control parameter '{request.entry_control_parameter_name}'. Failed because the parameter does not exist on the node."
|
|
1206
|
+
return PackageNodeAsSerializedFlowResultFailure(result_details=details)
|
|
1207
|
+
|
|
1208
|
+
# Verify it's actually a control parameter
|
|
1209
|
+
if ParameterTypeBuiltin.CONTROL_TYPE.value not in entry_param.input_types:
|
|
1210
|
+
details = f"Attempted to package node '{node_name}' with entry control parameter '{request.entry_control_parameter_name}'. Failed because the parameter is not a control type parameter."
|
|
1211
|
+
return PackageNodeAsSerializedFlowResultFailure(result_details=details)
|
|
1212
|
+
|
|
1213
|
+
return PackageNodeInfo(package_node=package_node, package_flow_name=package_flow_name)
|
|
1214
|
+
|
|
1215
|
+
def _validate_and_get_library_info(
|
|
1216
|
+
self, request: PackageNodeAsSerializedFlowRequest
|
|
1217
|
+
) -> str | PackageNodeAsSerializedFlowResultFailure:
|
|
1218
|
+
"""Validate start/end node types exist in library and return library version."""
|
|
1219
|
+
# Early validation - ensure both start and end node types exist in the specified library
|
|
1220
|
+
try:
|
|
1221
|
+
start_end_library = LibraryRegistry.get_library_for_node_type(
|
|
1222
|
+
node_type=request.start_node_type, specific_library_name=request.start_end_specific_library_name
|
|
1223
|
+
)
|
|
1224
|
+
except KeyError as err:
|
|
1225
|
+
details = f"Attempted to package node with start node type '{request.start_node_type}' from library '{request.start_end_specific_library_name}'. Failed because start node type was not found in library. Error: {err}."
|
|
1226
|
+
return PackageNodeAsSerializedFlowResultFailure(result_details=details)
|
|
1227
|
+
|
|
1228
|
+
try:
|
|
1229
|
+
LibraryRegistry.get_library_for_node_type(
|
|
1230
|
+
node_type=request.end_node_type, specific_library_name=request.start_end_specific_library_name
|
|
1231
|
+
)
|
|
1232
|
+
except KeyError as err:
|
|
1233
|
+
details = f"Attempted to package node with end node type '{request.end_node_type}' from library '{request.start_end_specific_library_name}'. Failed because end node type was not found in library. Error: {err}."
|
|
1234
|
+
return PackageNodeAsSerializedFlowResultFailure(result_details=details)
|
|
1235
|
+
|
|
1236
|
+
# Get the actual library version
|
|
1237
|
+
start_end_library_metadata = start_end_library.get_metadata()
|
|
1238
|
+
return start_end_library_metadata.library_version
|
|
1239
|
+
|
|
1240
|
+
def _analyze_package_node_connections(
|
|
1241
|
+
self, package_node: BaseNode, node_name: str
|
|
1242
|
+
) -> ConnectionAnalysis | PackageNodeAsSerializedFlowResultFailure:
|
|
1243
|
+
"""Analyze package node connections and separate control from data connections."""
|
|
1244
|
+
# Get connection details using the efficient approach
|
|
1245
|
+
list_connections_request = ListConnectionsForNodeRequest(node_name=node_name)
|
|
1246
|
+
list_connections_result = GriptapeNodes.NodeManager().on_list_connections_for_node_request(
|
|
1247
|
+
list_connections_request
|
|
1248
|
+
)
|
|
1249
|
+
|
|
1250
|
+
if not isinstance(list_connections_result, ListConnectionsForNodeResultSuccess):
|
|
1251
|
+
details = f"Attempted to analyze connections for package node '{node_name}'. Failed because connection listing failed."
|
|
1252
|
+
return PackageNodeAsSerializedFlowResultFailure(result_details=details)
|
|
1253
|
+
|
|
1254
|
+
# Separate control connections from data connections based on package node's parameter types
|
|
1255
|
+
incoming_data_connections = []
|
|
1256
|
+
incoming_control_connections = []
|
|
1257
|
+
for incoming_conn in list_connections_result.incoming_connections:
|
|
1258
|
+
# Get the package node's parameter to check if it's a control type
|
|
1259
|
+
package_param = package_node.get_parameter_by_name(incoming_conn.target_parameter_name)
|
|
1260
|
+
if package_param and ParameterTypeBuiltin.CONTROL_TYPE.value in package_param.input_types:
|
|
1261
|
+
incoming_control_connections.append(incoming_conn)
|
|
1262
|
+
else:
|
|
1263
|
+
incoming_data_connections.append(incoming_conn)
|
|
1264
|
+
|
|
1265
|
+
outgoing_data_connections = []
|
|
1266
|
+
outgoing_control_connections = []
|
|
1267
|
+
for outgoing_conn in list_connections_result.outgoing_connections:
|
|
1268
|
+
# Get the package node's parameter to check if it's a control type
|
|
1269
|
+
package_param = package_node.get_parameter_by_name(outgoing_conn.source_parameter_name)
|
|
1270
|
+
if package_param and ParameterTypeBuiltin.CONTROL_TYPE.value == package_param.output_type:
|
|
1271
|
+
outgoing_control_connections.append(outgoing_conn)
|
|
1272
|
+
else:
|
|
1273
|
+
outgoing_data_connections.append(outgoing_conn)
|
|
1274
|
+
|
|
1275
|
+
return ConnectionAnalysis(
|
|
1276
|
+
incoming_data_connections=incoming_data_connections,
|
|
1277
|
+
incoming_control_connections=incoming_control_connections,
|
|
1278
|
+
outgoing_data_connections=outgoing_data_connections,
|
|
1279
|
+
outgoing_control_connections=outgoing_control_connections,
|
|
1280
|
+
)
|
|
1281
|
+
|
|
1282
|
+
def _serialize_package_node(
|
|
1283
|
+
self,
|
|
1284
|
+
node_name: str,
|
|
1285
|
+
package_node: BaseNode,
|
|
1286
|
+
unique_parameter_uuid_to_values: dict[SerializedNodeCommands.UniqueParameterValueUUID, Any],
|
|
1287
|
+
serialized_parameter_value_tracker: SerializedParameterValueTracker,
|
|
1288
|
+
) -> SerializeNodeToCommandsResultSuccess | PackageNodeAsSerializedFlowResultFailure:
|
|
1289
|
+
"""Serialize the package node to commands, adding OUTPUT mode to PROPERTY-only parameters."""
|
|
1290
|
+
# Use the provided parameter tracking structures
|
|
1291
|
+
|
|
1292
|
+
# Create serialization request for the package node
|
|
1293
|
+
serialize_node_request = SerializeNodeToCommandsRequest(
|
|
1294
|
+
node_name=node_name,
|
|
1295
|
+
unique_parameter_uuid_to_values=unique_parameter_uuid_to_values,
|
|
1296
|
+
serialized_parameter_value_tracker=serialized_parameter_value_tracker,
|
|
1297
|
+
)
|
|
1298
|
+
|
|
1299
|
+
# Execute the serialization
|
|
1300
|
+
serialize_node_result = GriptapeNodes.handle_request(serialize_node_request)
|
|
1301
|
+
if not isinstance(serialize_node_result, SerializeNodeToCommandsResultSuccess):
|
|
1302
|
+
details = f"Attempted to serialize package node '{node_name}'. Failed because node serialization failed."
|
|
1303
|
+
return PackageNodeAsSerializedFlowResultFailure(result_details=details)
|
|
1304
|
+
|
|
1305
|
+
# Add ALTER parameter commands for PROPERTY-only parameters to enable OUTPUT mode
|
|
1306
|
+
# We need these to emit their values back so that the orchestrator/caller
|
|
1307
|
+
# can reconcile the packaged node's values after it is executed.
|
|
1308
|
+
package_alter_parameter_commands = []
|
|
1309
|
+
for package_param in package_node.parameters:
|
|
1310
|
+
has_output_mode = ParameterMode.OUTPUT in package_param.allowed_modes
|
|
1311
|
+
has_property_mode = ParameterMode.PROPERTY in package_param.allowed_modes
|
|
1312
|
+
|
|
1313
|
+
# If has PROPERTY but not OUTPUT, add ALTER command to enable OUTPUT
|
|
1314
|
+
if has_property_mode and not has_output_mode:
|
|
1315
|
+
alter_param_request = AlterParameterDetailsRequest(
|
|
1316
|
+
parameter_name=package_param.name,
|
|
1317
|
+
node_name=package_node.name,
|
|
1318
|
+
mode_allowed_output=True,
|
|
1319
|
+
)
|
|
1320
|
+
package_alter_parameter_commands.append(alter_param_request)
|
|
1321
|
+
|
|
1322
|
+
# If we have alter parameter commands, append them to the existing element_modification_commands
|
|
1323
|
+
if package_alter_parameter_commands:
|
|
1324
|
+
serialize_node_result.serialized_node_commands.element_modification_commands.extend(
|
|
1325
|
+
package_alter_parameter_commands
|
|
1326
|
+
)
|
|
1327
|
+
|
|
1328
|
+
return serialize_node_result
|
|
1329
|
+
|
|
1330
|
+
def _create_start_node_commands( # noqa: PLR0913
|
|
1331
|
+
self,
|
|
1332
|
+
request: PackageNodeAsSerializedFlowRequest,
|
|
1333
|
+
incoming_data_connections: list[IncomingConnection],
|
|
1334
|
+
package_node: BaseNode,
|
|
1335
|
+
package_node_uuid: SerializedNodeCommands.NodeUUID,
|
|
1336
|
+
library_version: str,
|
|
1337
|
+
unique_parameter_uuid_to_values: dict[SerializedNodeCommands.UniqueParameterValueUUID, Any],
|
|
1338
|
+
serialized_parameter_value_tracker: SerializedParameterValueTracker,
|
|
1339
|
+
) -> PackagingStartNodeResult | PackageNodeAsSerializedFlowResultFailure:
|
|
1340
|
+
"""Create start node commands and connections for incoming data connections."""
|
|
1341
|
+
# Generate UUID and name for start node
|
|
1342
|
+
start_node_uuid = SerializedNodeCommands.NodeUUID(str(uuid4()))
|
|
1343
|
+
start_node_name = f"Start_Package_{package_node.name}"
|
|
1344
|
+
|
|
1345
|
+
# Build start node CreateNodeRequest
|
|
1346
|
+
start_create_node_command = CreateNodeRequest(
|
|
1347
|
+
node_type=request.start_node_type,
|
|
1348
|
+
specific_library_name=request.start_end_specific_library_name,
|
|
1349
|
+
node_name=start_node_name,
|
|
1350
|
+
metadata={},
|
|
1351
|
+
initial_setup=True,
|
|
1352
|
+
create_error_proxy_on_failure=False,
|
|
1353
|
+
)
|
|
1354
|
+
|
|
1355
|
+
# Create library details
|
|
1356
|
+
start_node_library_details = LibraryNameAndVersion(
|
|
1357
|
+
library_name=request.start_end_specific_library_name,
|
|
1358
|
+
library_version=library_version,
|
|
1359
|
+
)
|
|
1360
|
+
|
|
1361
|
+
# Create parameter modification commands and connection mappings for the start node based on incoming DATA connections
|
|
1362
|
+
start_node_parameter_commands = []
|
|
1363
|
+
start_to_package_data_connections = []
|
|
1364
|
+
start_node_parameter_value_commands = []
|
|
1365
|
+
input_shape_data: WorkflowShapeNodes = {}
|
|
1366
|
+
|
|
1367
|
+
for incoming_conn in incoming_data_connections:
|
|
1368
|
+
# Parameter name: use the package node's parameter name
|
|
1369
|
+
param_name = incoming_conn.target_parameter_name
|
|
1370
|
+
|
|
1371
|
+
# Get the source node to determine parameter type
|
|
1372
|
+
try:
|
|
1373
|
+
source_node = GriptapeNodes.NodeManager().get_node_by_name(incoming_conn.source_node_name)
|
|
1374
|
+
except ValueError as err:
|
|
1375
|
+
details = f"Attempted to package node '{package_node.name}'. Failed because source node '{incoming_conn.source_node_name}' from incoming connection could not be found. Error: {err}."
|
|
1376
|
+
return PackageNodeAsSerializedFlowResultFailure(result_details=details)
|
|
1377
|
+
|
|
1378
|
+
# Get the source parameter
|
|
1379
|
+
source_param = source_node.get_parameter_by_name(incoming_conn.source_parameter_name)
|
|
1380
|
+
if not source_param:
|
|
1381
|
+
details = f"Attempted to package node '{package_node.name}'. Failed because source parameter '{incoming_conn.source_parameter_name}' on node '{incoming_conn.source_node_name}' from incoming connection could not be found."
|
|
1382
|
+
return PackageNodeAsSerializedFlowResultFailure(result_details=details)
|
|
1383
|
+
|
|
1384
|
+
# Extract parameter shape info for workflow shape (inputs from external sources)
|
|
1385
|
+
param_shape_info = GriptapeNodes.WorkflowManager().extract_parameter_shape_info(
|
|
1386
|
+
source_param, include_control_params=True
|
|
1387
|
+
)
|
|
1388
|
+
if param_shape_info is not None:
|
|
1389
|
+
if start_node_name not in input_shape_data:
|
|
1390
|
+
input_shape_data[start_node_name] = {}
|
|
1391
|
+
input_shape_data[start_node_name][param_name] = param_shape_info
|
|
1392
|
+
|
|
1393
|
+
# Extract parameter value from source node to set on start node
|
|
1394
|
+
param_value_commands = GriptapeNodes.NodeManager().handle_parameter_value_saving(
|
|
1395
|
+
parameter=source_param,
|
|
1396
|
+
node=source_node,
|
|
1397
|
+
unique_parameter_uuid_to_values=unique_parameter_uuid_to_values,
|
|
1398
|
+
serialized_parameter_value_tracker=serialized_parameter_value_tracker,
|
|
1399
|
+
create_node_request=start_create_node_command,
|
|
1400
|
+
)
|
|
1401
|
+
if param_value_commands is not None:
|
|
1402
|
+
# Modify each command to target the start node parameter instead
|
|
1403
|
+
for param_value_command in param_value_commands:
|
|
1404
|
+
param_value_command.set_parameter_value_command.node_name = start_node_name
|
|
1405
|
+
param_value_command.set_parameter_value_command.parameter_name = param_name
|
|
1406
|
+
start_node_parameter_value_commands.append(param_value_command)
|
|
1407
|
+
|
|
1408
|
+
# Create parameter command for start node
|
|
1409
|
+
add_param_request = AddParameterToNodeRequest(
|
|
1410
|
+
node_name=start_node_name,
|
|
1411
|
+
parameter_name=param_name,
|
|
1412
|
+
# Use the source parameter's output_type as the type for our start node parameter
|
|
1413
|
+
# since we want to match what the original connection was providing
|
|
1414
|
+
type=source_param.output_type,
|
|
1415
|
+
default_value=None,
|
|
1416
|
+
tooltip=f"Parameter {param_name} from packaged flow",
|
|
1417
|
+
initial_setup=True,
|
|
1418
|
+
)
|
|
1419
|
+
start_node_parameter_commands.append(add_param_request)
|
|
1420
|
+
|
|
1421
|
+
# Create connection from start node to package node
|
|
1422
|
+
start_to_package_connection = SerializedFlowCommands.IndirectConnectionSerialization(
|
|
1423
|
+
source_node_uuid=start_node_uuid,
|
|
1424
|
+
source_parameter_name=param_name,
|
|
1425
|
+
target_node_uuid=package_node_uuid,
|
|
1426
|
+
target_parameter_name=param_name,
|
|
1427
|
+
)
|
|
1428
|
+
start_to_package_data_connections.append(start_to_package_connection)
|
|
1429
|
+
|
|
1430
|
+
# Build complete SerializedNodeCommands for start node
|
|
1431
|
+
start_node_commands = SerializedNodeCommands(
|
|
1432
|
+
create_node_command=start_create_node_command,
|
|
1433
|
+
element_modification_commands=start_node_parameter_commands,
|
|
1434
|
+
node_library_details=start_node_library_details,
|
|
1435
|
+
node_uuid=start_node_uuid,
|
|
1436
|
+
)
|
|
1437
|
+
|
|
1438
|
+
return PackagingStartNodeResult(
|
|
1439
|
+
start_node_commands=start_node_commands,
|
|
1440
|
+
start_to_package_data_connections=start_to_package_data_connections,
|
|
1441
|
+
input_shape_data=input_shape_data,
|
|
1442
|
+
start_node_parameter_value_commands=start_node_parameter_value_commands,
|
|
1443
|
+
)
|
|
1444
|
+
|
|
1445
|
+
def _create_end_node_commands(
|
|
1446
|
+
self,
|
|
1447
|
+
request: PackageNodeAsSerializedFlowRequest,
|
|
1448
|
+
package_node: BaseNode,
|
|
1449
|
+
package_node_uuid: SerializedNodeCommands.NodeUUID,
|
|
1450
|
+
library_version: str,
|
|
1451
|
+
) -> PackagingEndNodeResult | PackageNodeAsSerializedFlowResultFailure:
|
|
1452
|
+
"""Create end node commands and connections for ALL package parameters that meet criteria."""
|
|
1453
|
+
# Generate UUID and name for end node
|
|
1454
|
+
end_node_uuid = SerializedNodeCommands.NodeUUID(str(uuid4()))
|
|
1455
|
+
end_node_name = f"End_Package_{package_node.name}"
|
|
1456
|
+
|
|
1457
|
+
# Build end node CreateNodeRequest
|
|
1458
|
+
end_create_node_command = CreateNodeRequest(
|
|
1459
|
+
node_type=request.end_node_type,
|
|
1460
|
+
specific_library_name=request.start_end_specific_library_name,
|
|
1461
|
+
node_name=end_node_name,
|
|
1462
|
+
metadata={},
|
|
1463
|
+
initial_setup=True,
|
|
1464
|
+
create_error_proxy_on_failure=False,
|
|
1465
|
+
)
|
|
1466
|
+
|
|
1467
|
+
# Create library details
|
|
1468
|
+
end_node_library_details = LibraryNameAndVersion(
|
|
1469
|
+
library_name=request.start_end_specific_library_name,
|
|
1470
|
+
library_version=library_version,
|
|
1471
|
+
)
|
|
1472
|
+
|
|
1473
|
+
# Process ALL package node parameters to create end node parameters and connections
|
|
1474
|
+
# Note: PROPERTY-only parameters are guaranteed to have OUTPUT mode after serialization
|
|
1475
|
+
end_node_parameter_commands = []
|
|
1476
|
+
package_to_end_data_connections = []
|
|
1477
|
+
output_shape_data: WorkflowShapeNodes = {}
|
|
1478
|
+
|
|
1479
|
+
for package_param in package_node.parameters:
|
|
1480
|
+
# Only ignore parameters that have ONLY INPUT mode (no OUTPUT or PROPERTY)
|
|
1481
|
+
has_output_mode = ParameterMode.OUTPUT in package_param.allowed_modes
|
|
1482
|
+
has_property_mode = ParameterMode.PROPERTY in package_param.allowed_modes
|
|
1483
|
+
|
|
1484
|
+
# Skip parameters that only have INPUT mode
|
|
1485
|
+
if not has_output_mode and not has_property_mode:
|
|
1486
|
+
continue
|
|
1487
|
+
|
|
1488
|
+
# Create prefixed parameter name for end node to avoid collisions
|
|
1489
|
+
end_param_name = f"{request.output_parameter_prefix}{package_param.name}"
|
|
1490
|
+
|
|
1491
|
+
# Extract parameter shape info for workflow shape (outputs to external consumers)
|
|
1492
|
+
param_shape_info = GriptapeNodes.WorkflowManager().extract_parameter_shape_info(
|
|
1493
|
+
package_param, include_control_params=True
|
|
1494
|
+
)
|
|
1495
|
+
if param_shape_info is not None:
|
|
1496
|
+
if end_node_name not in output_shape_data:
|
|
1497
|
+
output_shape_data[end_node_name] = {}
|
|
1498
|
+
output_shape_data[end_node_name][end_param_name] = param_shape_info
|
|
1499
|
+
|
|
1500
|
+
# Create parameter command for end node
|
|
1501
|
+
add_param_request = AddParameterToNodeRequest(
|
|
1502
|
+
node_name=end_node_name,
|
|
1503
|
+
parameter_name=end_param_name,
|
|
1504
|
+
# Use the package node's output_type as the type for our end node parameter
|
|
1505
|
+
type=package_param.output_type,
|
|
1506
|
+
default_value=None,
|
|
1507
|
+
tooltip=f"Output parameter {package_param.name} from packaged node {package_node.name}",
|
|
1508
|
+
initial_setup=True,
|
|
1509
|
+
)
|
|
1510
|
+
end_node_parameter_commands.append(add_param_request)
|
|
1511
|
+
|
|
1512
|
+
# Create connection from package node to end node
|
|
1513
|
+
package_to_end_connection = SerializedFlowCommands.IndirectConnectionSerialization(
|
|
1514
|
+
source_node_uuid=package_node_uuid,
|
|
1515
|
+
source_parameter_name=package_param.name,
|
|
1516
|
+
target_node_uuid=end_node_uuid,
|
|
1517
|
+
target_parameter_name=end_param_name,
|
|
1518
|
+
)
|
|
1519
|
+
package_to_end_data_connections.append(package_to_end_connection)
|
|
1520
|
+
|
|
1521
|
+
# Build complete SerializedNodeCommands for end node
|
|
1522
|
+
end_node_commands = SerializedNodeCommands(
|
|
1523
|
+
create_node_command=end_create_node_command,
|
|
1524
|
+
element_modification_commands=end_node_parameter_commands,
|
|
1525
|
+
node_library_details=end_node_library_details,
|
|
1526
|
+
node_uuid=end_node_uuid,
|
|
1527
|
+
)
|
|
1528
|
+
|
|
1529
|
+
return PackagingEndNodeResult(
|
|
1530
|
+
end_node_commands=end_node_commands,
|
|
1531
|
+
package_to_end_data_connections=package_to_end_data_connections,
|
|
1532
|
+
output_shape_data=output_shape_data,
|
|
1533
|
+
)
|
|
1534
|
+
|
|
1535
|
+
def _create_start_node_control_connection(
|
|
1536
|
+
self,
|
|
1537
|
+
entry_control_parameter_name: str | None,
|
|
1538
|
+
start_node_uuid: SerializedNodeCommands.NodeUUID,
|
|
1539
|
+
package_node_uuid: SerializedNodeCommands.NodeUUID,
|
|
1540
|
+
package_node: BaseNode,
|
|
1541
|
+
) -> SerializedFlowCommands.IndirectConnectionSerialization | PackageNodeAsSerializedFlowResultFailure:
|
|
1542
|
+
"""Create control flow connection from start node to package node.
|
|
1543
|
+
|
|
1544
|
+
Connects the start node's first control output to the specified or first available package node control input.
|
|
1545
|
+
"""
|
|
1546
|
+
if entry_control_parameter_name is not None:
|
|
1547
|
+
# Case 1: Specific entry parameter name provided
|
|
1548
|
+
package_control_input_name = entry_control_parameter_name
|
|
1549
|
+
else:
|
|
1550
|
+
# Case 2: Find the first available control input parameter
|
|
1551
|
+
package_control_input_name = None
|
|
1552
|
+
for param in package_node.parameters:
|
|
1553
|
+
if ParameterTypeBuiltin.CONTROL_TYPE.value in param.input_types:
|
|
1554
|
+
package_control_input_name = param.name
|
|
1555
|
+
logger.warning(
|
|
1556
|
+
"No entry_control_parameter_name specified for packaging node '%s'. "
|
|
1557
|
+
"Using first available control input parameter: '%s'",
|
|
1558
|
+
package_node.name,
|
|
1559
|
+
package_control_input_name,
|
|
1560
|
+
)
|
|
1561
|
+
break
|
|
1562
|
+
|
|
1563
|
+
if package_control_input_name is None:
|
|
1564
|
+
details = f"Attempted to package node '{package_node.name}'. Failed because no control input parameters found on the node, so cannot create control flow connection."
|
|
1565
|
+
return PackageNodeAsSerializedFlowResultFailure(result_details=details)
|
|
1566
|
+
|
|
1567
|
+
# StartNode always has a control output parameter with name "exec_out"
|
|
1568
|
+
source_control_parameter_name = "exec_out"
|
|
1569
|
+
|
|
1570
|
+
# Create the connection
|
|
1571
|
+
control_connection = SerializedFlowCommands.IndirectConnectionSerialization(
|
|
1572
|
+
source_node_uuid=start_node_uuid,
|
|
1573
|
+
source_parameter_name=source_control_parameter_name,
|
|
1574
|
+
target_node_uuid=package_node_uuid,
|
|
1575
|
+
target_parameter_name=package_control_input_name,
|
|
1576
|
+
)
|
|
1577
|
+
return control_connection
|
|
1578
|
+
|
|
1579
|
+
def _assemble_serialized_flow( # noqa: PLR0913
|
|
1580
|
+
self,
|
|
1581
|
+
serialized_package_result: SerializeNodeToCommandsResultSuccess,
|
|
1582
|
+
start_node_result: PackagingStartNodeResult,
|
|
1583
|
+
end_node_result: PackagingEndNodeResult,
|
|
1584
|
+
control_flow_connections: list[SerializedFlowCommands.IndirectConnectionSerialization],
|
|
1585
|
+
unique_parameter_uuid_to_values: dict[SerializedNodeCommands.UniqueParameterValueUUID, Any],
|
|
1586
|
+
library_version: str,
|
|
1587
|
+
request: PackageNodeAsSerializedFlowRequest,
|
|
1588
|
+
) -> SerializedFlowCommands:
|
|
1589
|
+
"""Assemble the complete SerializedFlowCommands from all components."""
|
|
1590
|
+
# Combine all connections: Start->Package + Package->End + Control Flow
|
|
1591
|
+
all_connections = (
|
|
1592
|
+
start_node_result.start_to_package_data_connections
|
|
1593
|
+
+ end_node_result.package_to_end_data_connections
|
|
1594
|
+
+ control_flow_connections
|
|
1595
|
+
)
|
|
1596
|
+
|
|
1597
|
+
# Set up lock commands if needed
|
|
1598
|
+
set_lock_commands_per_node = {}
|
|
1599
|
+
if serialized_package_result.serialized_node_commands.lock_node_command:
|
|
1600
|
+
set_lock_commands_per_node[serialized_package_result.serialized_node_commands.node_uuid] = (
|
|
1601
|
+
serialized_package_result.serialized_node_commands.lock_node_command
|
|
1602
|
+
)
|
|
1603
|
+
|
|
1604
|
+
# Collect all libraries used
|
|
1605
|
+
end_node_library_details = LibraryNameAndVersion(
|
|
1606
|
+
library_name=request.start_end_specific_library_name,
|
|
1607
|
+
library_version=library_version,
|
|
1608
|
+
)
|
|
1609
|
+
|
|
1610
|
+
node_libraries_used = {
|
|
1611
|
+
serialized_package_result.serialized_node_commands.node_library_details,
|
|
1612
|
+
start_node_result.start_node_commands.node_library_details,
|
|
1613
|
+
end_node_library_details,
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
# Include all three nodes in the flow
|
|
1617
|
+
all_serialized_nodes = [
|
|
1618
|
+
start_node_result.start_node_commands,
|
|
1619
|
+
serialized_package_result.serialized_node_commands,
|
|
1620
|
+
end_node_result.end_node_commands,
|
|
1621
|
+
]
|
|
1622
|
+
|
|
1623
|
+
# Create a CreateFlowRequest for the packaged flow so that it can
|
|
1624
|
+
# run as a standalone workflow.
|
|
1625
|
+
package_flow_name = (
|
|
1626
|
+
f"Packaged_{serialized_package_result.serialized_node_commands.create_node_command.node_name}"
|
|
1627
|
+
)
|
|
1628
|
+
packaged_flow_metadata = {} # Keep it simple until we have reason to populate it
|
|
1629
|
+
|
|
1630
|
+
create_packaged_flow_request = CreateFlowRequest(
|
|
1631
|
+
parent_flow_name=None, # Standalone flow
|
|
1632
|
+
flow_name=package_flow_name,
|
|
1633
|
+
set_as_new_context=False, # Let deserializer decide
|
|
1634
|
+
metadata=packaged_flow_metadata,
|
|
1635
|
+
)
|
|
1636
|
+
|
|
1637
|
+
# Build the complete SerializedFlowCommands
|
|
1638
|
+
return SerializedFlowCommands(
|
|
1639
|
+
node_libraries_used=node_libraries_used,
|
|
1640
|
+
flow_initialization_command=create_packaged_flow_request,
|
|
1641
|
+
serialized_node_commands=all_serialized_nodes,
|
|
1642
|
+
serialized_connections=all_connections,
|
|
1643
|
+
unique_parameter_uuid_to_values=unique_parameter_uuid_to_values,
|
|
1644
|
+
set_parameter_value_commands={
|
|
1645
|
+
serialized_package_result.serialized_node_commands.node_uuid: serialized_package_result.set_parameter_value_commands,
|
|
1646
|
+
start_node_result.start_node_commands.node_uuid: start_node_result.start_node_parameter_value_commands,
|
|
1647
|
+
},
|
|
1648
|
+
set_lock_commands_per_node=set_lock_commands_per_node,
|
|
1649
|
+
sub_flows_commands=[],
|
|
1650
|
+
referenced_workflows=set(),
|
|
1651
|
+
)
|
|
1652
|
+
|
|
1015
1653
|
async def on_start_flow_request(self, request: StartFlowRequest) -> ResultPayload: # noqa: C901, PLR0911, PLR0912
|
|
1016
1654
|
# which flow
|
|
1017
1655
|
flow_name = request.flow_name
|
|
@@ -1090,7 +1728,7 @@ class FlowManager:
|
|
|
1090
1728
|
details = f"Could not get flow state. Error: {err}"
|
|
1091
1729
|
return GetFlowStateResultFailure(result_details=details)
|
|
1092
1730
|
try:
|
|
1093
|
-
control_nodes, resolving_nodes
|
|
1731
|
+
control_nodes, resolving_nodes = self.flow_state(flow)
|
|
1094
1732
|
except Exception as e:
|
|
1095
1733
|
details = f"Failed to get flow state of flow with name {flow_name}. Exception occurred: {e} "
|
|
1096
1734
|
logger.exception(details)
|
|
@@ -1100,7 +1738,6 @@ class FlowManager:
|
|
|
1100
1738
|
control_nodes=control_nodes,
|
|
1101
1739
|
resolving_node=resolving_nodes,
|
|
1102
1740
|
result_details=details,
|
|
1103
|
-
involved_nodes=involved_nodes,
|
|
1104
1741
|
)
|
|
1105
1742
|
|
|
1106
1743
|
def on_cancel_flow_request(self, request: CancelFlowRequest) -> ResultPayload:
|
|
@@ -1608,12 +2245,16 @@ class FlowManager:
|
|
|
1608
2245
|
# Initialize global control flow machine and DAG builder
|
|
1609
2246
|
|
|
1610
2247
|
self._global_control_flow_machine = ControlFlowMachine(flow.name)
|
|
2248
|
+
# Set off the request here.
|
|
1611
2249
|
try:
|
|
1612
2250
|
await self._global_control_flow_machine.start_flow(start_node, debug_mode)
|
|
1613
2251
|
except Exception:
|
|
1614
2252
|
if self.check_for_existing_running_flow():
|
|
1615
2253
|
self.cancel_flow_run()
|
|
1616
2254
|
raise
|
|
2255
|
+
GriptapeNodes.EventManager().put_event(
|
|
2256
|
+
ExecutionGriptapeNodeEvent(wrapped_event=ExecutionEvent(payload=InvolvedNodesEvent(involved_nodes=[])))
|
|
2257
|
+
)
|
|
1617
2258
|
|
|
1618
2259
|
def check_for_existing_running_flow(self) -> bool:
|
|
1619
2260
|
if self._global_control_flow_machine is None:
|
|
@@ -1720,6 +2361,13 @@ class FlowManager:
|
|
|
1720
2361
|
if self.check_for_existing_running_flow():
|
|
1721
2362
|
# Now we know something is running, it's ParallelResolutionMachine, and that we are in single_node_resolution.
|
|
1722
2363
|
self._global_dag_builder.add_node_with_dependencies(node, node.name)
|
|
2364
|
+
# Emit involved nodes update after adding node to DAG
|
|
2365
|
+
involved_nodes = list(self._global_dag_builder.node_to_reference.keys())
|
|
2366
|
+
GriptapeNodes.EventManager().put_event(
|
|
2367
|
+
ExecutionGriptapeNodeEvent(
|
|
2368
|
+
wrapped_event=ExecutionEvent(payload=InvolvedNodesEvent(involved_nodes=involved_nodes))
|
|
2369
|
+
)
|
|
2370
|
+
)
|
|
1723
2371
|
else:
|
|
1724
2372
|
# Set that we are only working on one node right now!
|
|
1725
2373
|
self._global_single_node_resolution = True
|
|
@@ -1733,10 +2381,30 @@ class FlowManager:
|
|
|
1733
2381
|
if isinstance(resolution_machine, ParallelResolutionMachine):
|
|
1734
2382
|
self._global_dag_builder.add_node_with_dependencies(node)
|
|
1735
2383
|
resolution_machine.context.dag_builder = self._global_dag_builder
|
|
1736
|
-
|
|
2384
|
+
involved_nodes = list(self._global_dag_builder.node_to_reference.keys())
|
|
2385
|
+
else:
|
|
2386
|
+
involved_nodes = list(flow.nodes.keys())
|
|
2387
|
+
# Send a InvolvedNodesRequest
|
|
2388
|
+
|
|
2389
|
+
GriptapeNodes.EventManager().put_event(
|
|
2390
|
+
ExecutionGriptapeNodeEvent(
|
|
2391
|
+
wrapped_event=ExecutionEvent(payload=InvolvedNodesEvent(involved_nodes=involved_nodes))
|
|
2392
|
+
)
|
|
2393
|
+
)
|
|
2394
|
+
try:
|
|
2395
|
+
await resolution_machine.resolve_node(node)
|
|
2396
|
+
except Exception as e:
|
|
2397
|
+
if self.check_for_existing_running_flow():
|
|
2398
|
+
self.cancel_flow_run()
|
|
2399
|
+
raise RuntimeError(e) from e
|
|
1737
2400
|
if resolution_machine.is_complete():
|
|
1738
2401
|
self._global_single_node_resolution = False
|
|
1739
2402
|
self._global_control_flow_machine.context.current_nodes = []
|
|
2403
|
+
GriptapeNodes.EventManager().put_event(
|
|
2404
|
+
ExecutionGriptapeNodeEvent(
|
|
2405
|
+
wrapped_event=ExecutionEvent(payload=InvolvedNodesEvent(involved_nodes=[]))
|
|
2406
|
+
)
|
|
2407
|
+
)
|
|
1740
2408
|
|
|
1741
2409
|
async def single_execution_step(self, flow: ControlFlow, change_debug_mode: bool) -> None: # noqa: FBT001
|
|
1742
2410
|
# do a granular step
|
|
@@ -1794,12 +2462,11 @@ class FlowManager:
|
|
|
1794
2462
|
# Clear entry control parameter for new execution
|
|
1795
2463
|
node.set_entry_control_parameter(None)
|
|
1796
2464
|
|
|
1797
|
-
def flow_state(self, flow: ControlFlow) -> tuple[list[str] | None, list[str] | None
|
|
2465
|
+
def flow_state(self, flow: ControlFlow) -> tuple[list[str] | None, list[str] | None]: # noqa: ARG002
|
|
1798
2466
|
if not self.check_for_existing_running_flow():
|
|
1799
|
-
|
|
1800
|
-
raise RuntimeError(msg)
|
|
2467
|
+
return None, None
|
|
1801
2468
|
if self._global_control_flow_machine is None:
|
|
1802
|
-
return None, None
|
|
2469
|
+
return None, None
|
|
1803
2470
|
control_flow_context = self._global_control_flow_machine.context
|
|
1804
2471
|
current_control_nodes = (
|
|
1805
2472
|
[control_flow_node.name for control_flow_node in control_flow_context.current_nodes]
|
|
@@ -1812,13 +2479,12 @@ class FlowManager:
|
|
|
1812
2479
|
node.node_reference.name
|
|
1813
2480
|
for node in control_flow_context.resolution_machine.context.task_to_node.values()
|
|
1814
2481
|
]
|
|
1815
|
-
|
|
1816
|
-
return current_control_nodes, current_resolving_nodes, involved_nodes if len(involved_nodes) != 0 else None
|
|
2482
|
+
return current_control_nodes, current_resolving_nodes
|
|
1817
2483
|
if isinstance(control_flow_context.resolution_machine, SequentialResolutionMachine):
|
|
1818
2484
|
focus_stack_for_node = control_flow_context.resolution_machine.context.focus_stack
|
|
1819
2485
|
current_resolving_node = focus_stack_for_node[-1].node.name if len(focus_stack_for_node) else None
|
|
1820
|
-
return current_control_nodes, [current_resolving_node] if current_resolving_node else None
|
|
1821
|
-
return current_control_nodes, None
|
|
2486
|
+
return current_control_nodes, [current_resolving_node] if current_resolving_node else None
|
|
2487
|
+
return current_control_nodes, None
|
|
1822
2488
|
|
|
1823
2489
|
def get_start_node_from_node(self, flow: ControlFlow, node: BaseNode) -> BaseNode | None:
|
|
1824
2490
|
# backwards chain in control outputs.
|