griptape-nodes 0.52.0__py3-none-any.whl → 0.53.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.
Files changed (48) hide show
  1. griptape_nodes/__init__.py +6 -943
  2. griptape_nodes/__main__.py +6 -0
  3. griptape_nodes/app/api.py +1 -12
  4. griptape_nodes/app/app.py +256 -209
  5. griptape_nodes/cli/__init__.py +1 -0
  6. griptape_nodes/cli/commands/__init__.py +1 -0
  7. griptape_nodes/cli/commands/config.py +71 -0
  8. griptape_nodes/cli/commands/engine.py +80 -0
  9. griptape_nodes/cli/commands/init.py +548 -0
  10. griptape_nodes/cli/commands/libraries.py +90 -0
  11. griptape_nodes/cli/commands/self.py +117 -0
  12. griptape_nodes/cli/main.py +46 -0
  13. griptape_nodes/cli/shared.py +84 -0
  14. griptape_nodes/common/__init__.py +1 -0
  15. griptape_nodes/common/directed_graph.py +55 -0
  16. griptape_nodes/drivers/storage/local_storage_driver.py +7 -2
  17. griptape_nodes/exe_types/core_types.py +60 -2
  18. griptape_nodes/exe_types/node_types.py +38 -24
  19. griptape_nodes/machines/control_flow.py +86 -22
  20. griptape_nodes/machines/fsm.py +10 -1
  21. griptape_nodes/machines/parallel_resolution.py +570 -0
  22. griptape_nodes/machines/{node_resolution.py → sequential_resolution.py} +22 -51
  23. griptape_nodes/mcp_server/server.py +1 -1
  24. griptape_nodes/retained_mode/events/base_events.py +2 -2
  25. griptape_nodes/retained_mode/events/node_events.py +4 -3
  26. griptape_nodes/retained_mode/griptape_nodes.py +25 -12
  27. griptape_nodes/retained_mode/managers/agent_manager.py +9 -5
  28. griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py +3 -1
  29. griptape_nodes/retained_mode/managers/context_manager.py +6 -5
  30. griptape_nodes/retained_mode/managers/flow_manager.py +117 -204
  31. griptape_nodes/retained_mode/managers/library_lifecycle/library_directory.py +1 -1
  32. griptape_nodes/retained_mode/managers/library_manager.py +35 -25
  33. griptape_nodes/retained_mode/managers/node_manager.py +81 -199
  34. griptape_nodes/retained_mode/managers/object_manager.py +11 -5
  35. griptape_nodes/retained_mode/managers/os_manager.py +24 -9
  36. griptape_nodes/retained_mode/managers/secrets_manager.py +8 -4
  37. griptape_nodes/retained_mode/managers/settings.py +32 -1
  38. griptape_nodes/retained_mode/managers/static_files_manager.py +8 -3
  39. griptape_nodes/retained_mode/managers/sync_manager.py +8 -5
  40. griptape_nodes/retained_mode/managers/workflow_manager.py +110 -122
  41. griptape_nodes/traits/add_param_button.py +1 -1
  42. griptape_nodes/traits/button.py +216 -6
  43. griptape_nodes/traits/color_picker.py +66 -0
  44. griptape_nodes/traits/traits.json +4 -0
  45. {griptape_nodes-0.52.0.dist-info → griptape_nodes-0.53.0.dist-info}/METADATA +2 -1
  46. {griptape_nodes-0.52.0.dist-info → griptape_nodes-0.53.0.dist-info}/RECORD +48 -34
  47. {griptape_nodes-0.52.0.dist-info → griptape_nodes-0.53.0.dist-info}/WHEEL +0 -0
  48. {griptape_nodes-0.52.0.dist-info → griptape_nodes-0.53.0.dist-info}/entry_points.txt +0 -0
@@ -1,8 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
+ from enum import StrEnum
4
5
  from queue import Queue
5
- from typing import TYPE_CHECKING, cast
6
+ from typing import TYPE_CHECKING, NamedTuple, cast
6
7
 
7
8
  from griptape_nodes.exe_types.connections import Connections
8
9
  from griptape_nodes.exe_types.core_types import (
@@ -20,6 +21,7 @@ from griptape_nodes.retained_mode.events.base_events import (
20
21
  ExecutionGriptapeNodeEvent,
21
22
  FlushParameterChangesRequest,
22
23
  FlushParameterChangesResultSuccess,
24
+ ResultDetails,
23
25
  )
24
26
  from griptape_nodes.retained_mode.events.connection_events import (
25
27
  CreateConnectionRequest,
@@ -120,13 +122,26 @@ if TYPE_CHECKING:
120
122
  logger = logging.getLogger("griptape_nodes")
121
123
 
122
124
 
125
+ class DagExecutionType(StrEnum):
126
+ START_NODE = "start_node"
127
+ CONTROL_NODE = "control_node"
128
+ DATA_NODE = "data_node"
129
+
130
+
131
+ class QueueItem(NamedTuple):
132
+ """Represents an item in the flow execution queue."""
133
+
134
+ node: BaseNode
135
+ dag_execution_type: DagExecutionType
136
+
137
+
123
138
  class FlowManager:
124
139
  _name_to_parent_name: dict[str, str | None]
125
140
  _flow_to_referenced_workflow_name: dict[ControlFlow, str]
126
141
  _connections: Connections
127
142
 
128
143
  # Global execution state (moved from individual ControlFlows)
129
- _global_flow_queue: Queue[BaseNode]
144
+ _global_flow_queue: Queue[QueueItem]
130
145
  _global_control_flow_machine: ControlFlowMachine | None
131
146
  _global_single_node_resolution: bool
132
147
 
@@ -169,10 +184,14 @@ class FlowManager:
169
184
  self._connections = Connections()
170
185
 
171
186
  # Initialize global execution state
172
- self._global_flow_queue = Queue[BaseNode]()
173
- self._global_control_flow_machine = None # Will be initialized when first flow starts
187
+ self._global_flow_queue = Queue[QueueItem]()
188
+ self._global_control_flow_machine = None # Track the current control flow machine
174
189
  self._global_single_node_resolution = False
175
190
 
191
+ @property
192
+ def global_flow_queue(self) -> Queue[QueueItem]:
193
+ return self._global_flow_queue
194
+
176
195
  def get_connections(self) -> Connections:
177
196
  """Get the connections instance."""
178
197
  return self._connections
@@ -238,10 +257,12 @@ class FlowManager:
238
257
  def on_get_top_level_flow_request(self, request: GetTopLevelFlowRequest) -> ResultPayload: # noqa: ARG002 (the request has to be assigned to the method)
239
258
  for flow_name, parent in self._name_to_parent_name.items():
240
259
  if parent is None:
241
- return GetTopLevelFlowResultSuccess(flow_name=flow_name)
260
+ return GetTopLevelFlowResultSuccess(
261
+ flow_name=flow_name, result_details=f"Successfully found top level flow: '{flow_name}'"
262
+ )
242
263
  msg = "Attempted to get top level flow, but no such flow exists"
243
264
  logger.debug(msg)
244
- return GetTopLevelFlowResultSuccess(flow_name=None)
265
+ return GetTopLevelFlowResultSuccess(flow_name=None, result_details=msg)
245
266
 
246
267
  def on_get_flow_details_request(self, request: GetFlowDetailsRequest) -> ResultPayload:
247
268
  flow_name = request.flow_name
@@ -251,7 +272,6 @@ class FlowManager:
251
272
  # We want to get details for whatever is at the top of the Current Context.
252
273
  if not GriptapeNodes.ContextManager().has_current_flow():
253
274
  details = "Attempted to get Flow details from the Current Context. Failed because the Current Context was empty."
254
- logger.error(details)
255
275
  return GetFlowDetailsResultFailure(result_details=details)
256
276
  flow = GriptapeNodes.ContextManager().get_current_flow()
257
277
  flow_name = flow.name
@@ -261,14 +281,12 @@ class FlowManager:
261
281
  details = (
262
282
  f"Attempted to get Flow details for '{flow_name}'. Failed because no Flow with that name exists."
263
283
  )
264
- logger.error(details)
265
284
  return GetFlowDetailsResultFailure(result_details=details)
266
285
 
267
286
  try:
268
287
  parent_flow_name = self.get_parent_flow(flow_name)
269
288
  except ValueError:
270
289
  details = f"Attempted to get Flow details for '{flow_name}'. Failed because Flow does not exist in parent mapping."
271
- logger.error(details)
272
290
  return GetFlowDetailsResultFailure(result_details=details)
273
291
 
274
292
  referenced_workflow_name = None
@@ -276,10 +294,8 @@ class FlowManager:
276
294
  referenced_workflow_name = self.get_referenced_workflow_name(flow)
277
295
 
278
296
  details = f"Successfully retrieved Flow details for '{flow_name}'."
279
- logger.debug(details)
280
297
  return GetFlowDetailsResultSuccess(
281
- referenced_workflow_name=referenced_workflow_name,
282
- parent_flow_name=parent_flow_name,
298
+ referenced_workflow_name=referenced_workflow_name, parent_flow_name=parent_flow_name, result_details=details
283
299
  )
284
300
 
285
301
  def on_get_flow_metadata_request(self, request: GetFlowMetadataRequest) -> ResultPayload:
@@ -289,7 +305,6 @@ class FlowManager:
289
305
  # Get from the current context.
290
306
  if not GriptapeNodes.ContextManager().has_current_flow():
291
307
  details = "Attempted to get metadata for a Flow from the Current Context. Failed because the Current Context is empty."
292
- logger.error(details)
293
308
  return GetFlowMetadataResultFailure(result_details=details)
294
309
 
295
310
  flow = GriptapeNodes.ContextManager().get_current_flow()
@@ -301,14 +316,12 @@ class FlowManager:
301
316
  flow = obj_mgr.attempt_get_object_by_name_as_type(flow_name, ControlFlow)
302
317
  if flow is None:
303
318
  details = f"Attempted to get metadata for a Flow '{flow_name}', but no such Flow was found."
304
- logger.error(details)
305
319
  return GetFlowMetadataResultFailure(result_details=details)
306
320
 
307
321
  metadata = flow.metadata
308
322
  details = f"Successfully retrieved metadata for a Flow '{flow_name}'."
309
- logger.debug(details)
310
323
 
311
- return GetFlowMetadataResultSuccess(metadata=metadata)
324
+ return GetFlowMetadataResultSuccess(metadata=metadata, result_details=details)
312
325
 
313
326
  def on_set_flow_metadata_request(self, request: SetFlowMetadataRequest) -> ResultPayload:
314
327
  flow_name = request.flow_name
@@ -317,7 +330,6 @@ class FlowManager:
317
330
  # Get from the current context.
318
331
  if not GriptapeNodes.ContextManager().has_current_flow():
319
332
  details = "Attempted to set metadata for a Flow from the Current Context. Failed because the Current Context is empty."
320
- logger.error(details)
321
333
  return SetFlowMetadataResultFailure(result_details=details)
322
334
 
323
335
  flow = GriptapeNodes.ContextManager().get_current_flow()
@@ -329,16 +341,14 @@ class FlowManager:
329
341
  flow = obj_mgr.attempt_get_object_by_name_as_type(flow_name, ControlFlow)
330
342
  if flow is None:
331
343
  details = f"Attempted to set metadata for a Flow '{flow_name}', but no such Flow was found."
332
- logger.error(details)
333
344
  return SetFlowMetadataResultFailure(result_details=details)
334
345
 
335
346
  # We can't completely overwrite metadata.
336
347
  for key, value in request.metadata.items():
337
348
  flow.metadata[key] = value
338
349
  details = f"Successfully set metadata for a Flow '{flow_name}'."
339
- logger.debug(details)
340
350
 
341
- return SetFlowMetadataResultSuccess()
351
+ return SetFlowMetadataResultSuccess(result_details=details)
342
352
 
343
353
  def does_canvas_exist(self) -> bool:
344
354
  """Determines if there is already an existing flow with no parent flow.Returns True if there is an existing flow with no parent flow.Return False if there is no existing flow with no parent flow."""
@@ -368,13 +378,11 @@ class FlowManager:
368
378
  if self.does_canvas_exist():
369
379
  # We're trying to create the canvas. Ensure that parent does NOT already exist.
370
380
  details = "Attempted to create a Flow as the Canvas (top-level Flow with no parents), but the Canvas already exists."
371
- logger.error(details)
372
381
  result = CreateFlowResultFailure(result_details=details)
373
382
  return result
374
383
  # Now our parent exists, right?
375
384
  elif parent is None:
376
385
  details = f"Attempted to create a Flow with a parent '{request.parent_flow_name}', but no parent with that name could be found."
377
- logger.error(details)
378
386
 
379
387
  result = CreateFlowResultFailure(result_details=details)
380
388
 
@@ -383,7 +391,6 @@ class FlowManager:
383
391
  # We need to have a current workflow context to proceed.
384
392
  if not GriptapeNodes.ContextManager().has_current_workflow():
385
393
  details = "Attempted to create a Flow, but no Workflow was active in the Current Context."
386
- logger.error(details)
387
394
  return CreateFlowResultFailure(result_details=details)
388
395
 
389
396
  # Create it.
@@ -409,13 +416,14 @@ class FlowManager:
409
416
 
410
417
  # Success
411
418
  details = f"Successfully created Flow '{final_flow_name}'."
412
- log_level = logging.DEBUG
419
+ log_level = "DEBUG"
413
420
  if (request.flow_name is not None) and (final_flow_name != request.flow_name):
414
421
  details = f"{details} WARNING: Had to rename from original Flow requested '{request.flow_name}' as an object with this name already existed."
415
- log_level = logging.WARNING
422
+ log_level = "WARNING"
416
423
 
417
- logger.log(level=log_level, msg=details)
418
- result = CreateFlowResultSuccess(flow_name=final_flow_name)
424
+ result = CreateFlowResultSuccess(
425
+ flow_name=final_flow_name, result_details=ResultDetails(message=details, level=log_level)
426
+ )
419
427
  return result
420
428
 
421
429
  # This needs to have a lot of branches to check the flow in all possible situations. In Current Context, or when the name is passed in.
@@ -428,7 +436,6 @@ class FlowManager:
428
436
  details = (
429
437
  "Attempted to delete a Flow from the Current Context. Failed because the Current Context was empty."
430
438
  )
431
- logger.error(details)
432
439
  result = DeleteFlowResultFailure(result_details=details)
433
440
  return result
434
441
  # We pop it off here, but we'll re-add it using context in a moment.
@@ -440,14 +447,12 @@ class FlowManager:
440
447
  flow = obj_mgr.attempt_get_object_by_name_as_type(flow_name, ControlFlow)
441
448
  if flow is None:
442
449
  details = f"Attempted to delete Flow '{flow_name}', but no Flow with that name could be found."
443
- logger.error(details)
444
450
  result = DeleteFlowResultFailure(result_details=details)
445
451
  return result
446
452
  if self.check_for_existing_running_flow():
447
453
  result = GriptapeNodes.handle_request(CancelFlowRequest(flow_name=flow.name))
448
454
  if not result.succeeded():
449
455
  details = f"Attempted to delete flow '{flow_name}'. Failed because running flow could not cancel."
450
- logger.error(details)
451
456
  return DeleteFlowResultFailure(result_details=details)
452
457
 
453
458
  # Let this Flow assume the Current Context while we delete everything within it.
@@ -457,7 +462,6 @@ class FlowManager:
457
462
  list_nodes_result = GriptapeNodes.handle_request(list_nodes_request)
458
463
  if not isinstance(list_nodes_result, ListNodesInFlowResultSuccess):
459
464
  details = f"Attempted to delete Flow '{flow.name}', but failed while attempting to get the list of Nodes owned by this Flow."
460
- logger.error(details)
461
465
  result = DeleteFlowResultFailure(result_details=details)
462
466
  return result
463
467
  node_names = list_nodes_result.node_names
@@ -466,7 +470,6 @@ class FlowManager:
466
470
  delete_node_result = GriptapeNodes.handle_request(delete_node_request)
467
471
  if isinstance(delete_node_result, DeleteNodeResultFailure):
468
472
  details = f"Attempted to delete Flow '{flow.name}', but failed while attempting to delete child Node '{node_name}'."
469
- logger.error(details)
470
473
  result = DeleteFlowResultFailure(result_details=details)
471
474
  return result
472
475
 
@@ -478,7 +481,6 @@ class FlowManager:
478
481
  list_flows_result = GriptapeNodes.handle_request(list_flows_request)
479
482
  if not isinstance(list_flows_result, ListFlowsInCurrentContextResultSuccess):
480
483
  details = f"Attempted to delete Flow '{flow_name}', but failed while attempting to get the list of Flows owned by this Flow."
481
- logger.error(details)
482
484
  result = DeleteFlowResultFailure(result_details=details)
483
485
  return result
484
486
  flow_names = list_flows_result.flow_names
@@ -489,7 +491,6 @@ class FlowManager:
489
491
  details = (
490
492
  f"Attempted to delete Flow '{child_flow_name}', but no Flow with that name could be found."
491
493
  )
492
- logger.error(details)
493
494
  result = DeleteFlowResultFailure(result_details=details)
494
495
  return result
495
496
  with GriptapeNodes.ContextManager().flow(flow=child_flow):
@@ -498,7 +499,6 @@ class FlowManager:
498
499
  delete_flow_result = GriptapeNodes.handle_request(delete_flow_request)
499
500
  if isinstance(delete_flow_result, DeleteFlowResultFailure):
500
501
  details = f"Attempted to delete Flow '{flow.name}', but failed while attempting to delete child Flow '{child_flow.name}'."
501
- logger.error(details)
502
502
  result = DeleteFlowResultFailure(result_details=details)
503
503
  return result
504
504
 
@@ -511,31 +511,32 @@ class FlowManager:
511
511
  if flow in self._flow_to_referenced_workflow_name:
512
512
  del self._flow_to_referenced_workflow_name[flow]
513
513
 
514
+ # Clean up ControlFlowMachine and DAG orchestrator for this flow
515
+ self._global_control_flow_machine = None
516
+
514
517
  details = f"Successfully deleted Flow '{flow_name}'."
515
- logger.debug(details)
516
- result = DeleteFlowResultSuccess()
518
+ result = DeleteFlowResultSuccess(result_details=details)
517
519
  return result
518
520
 
519
521
  def on_get_is_flow_running_request(self, request: GetIsFlowRunningRequest) -> ResultPayload:
520
522
  obj_mgr = GriptapeNodes.ObjectManager()
521
523
  if request.flow_name is None:
522
524
  details = "Attempted to get Flow, but no flow name was provided."
523
- logger.error(details)
524
525
  return GetIsFlowRunningResultFailure(result_details=details)
525
526
  flow = obj_mgr.attempt_get_object_by_name_as_type(request.flow_name, ControlFlow)
526
527
  if flow is None:
527
528
  details = f"Attempted to get Flow '{request.flow_name}', but no Flow with that name could be found."
528
- logger.error(details)
529
529
  result = GetIsFlowRunningResultFailure(result_details=details)
530
530
  return result
531
531
  try:
532
532
  is_running = self.check_for_existing_running_flow()
533
533
  except Exception:
534
534
  details = f"Error while trying to get status of '{request.flow_name}'."
535
- logger.error(details)
536
535
  result = GetIsFlowRunningResultFailure(result_details=details)
537
536
  return result
538
- return GetIsFlowRunningResultSuccess(is_running=is_running)
537
+ return GetIsFlowRunningResultSuccess(
538
+ is_running=is_running, result_details=f"Successfully checked if flow is running: {is_running}"
539
+ )
539
540
 
540
541
  def on_list_nodes_in_flow_request(self, request: ListNodesInFlowRequest) -> ResultPayload:
541
542
  flow_name = request.flow_name
@@ -544,7 +545,6 @@ class FlowManager:
544
545
  # First check if we have a current flow
545
546
  if not GriptapeNodes.ContextManager().has_current_flow():
546
547
  details = "Attempted to list Nodes in a Flow in the Current Context. Failed because the Current Context was empty."
547
- logger.error(details)
548
548
  result = ListNodesInFlowResultFailure(result_details=details)
549
549
  return result
550
550
  # Get the current flow from context
@@ -558,15 +558,13 @@ class FlowManager:
558
558
  details = (
559
559
  f"Attempted to list Nodes in Flow '{flow_name}'. Failed because no Flow with that name could be found."
560
560
  )
561
- logger.error(details)
562
561
  result = ListNodesInFlowResultFailure(result_details=details)
563
562
  return result
564
563
 
565
564
  ret_list = list(flow.nodes.keys())
566
565
  details = f"Successfully got the list of Nodes within Flow '{flow_name}'."
567
- logger.debug(details)
568
566
 
569
- result = ListNodesInFlowResultSuccess(node_names=ret_list)
567
+ result = ListNodesInFlowResultSuccess(node_names=ret_list, result_details=details)
570
568
  return result
571
569
 
572
570
  def on_list_flows_in_flow_request(self, request: ListFlowsInFlowRequest) -> ResultPayload:
@@ -576,7 +574,6 @@ class FlowManager:
576
574
  flow = obj_mgr.attempt_get_object_by_name_as_type(request.parent_flow_name, ControlFlow)
577
575
  if flow is None:
578
576
  details = f"Attempted to list Flows that are children of Flow '{request.parent_flow_name}', but no Flow with that name could be found."
579
- logger.error(details)
580
577
  result = ListFlowsInFlowResultFailure(result_details=details)
581
578
  return result
582
579
 
@@ -587,9 +584,8 @@ class FlowManager:
587
584
  ret_list.append(flow_name)
588
585
 
589
586
  details = f"Successfully got the list of Flows that are direct children of Flow '{request.parent_flow_name}'."
590
- logger.debug(details)
591
587
 
592
- result = ListFlowsInFlowResultSuccess(flow_names=ret_list)
588
+ result = ListFlowsInFlowResultSuccess(flow_names=ret_list, result_details=details)
593
589
  return result
594
590
 
595
591
  def get_flow_by_name(self, flow_name: str) -> ControlFlow:
@@ -623,7 +619,6 @@ class FlowManager:
623
619
  # First check if we have a current node
624
620
  if not GriptapeNodes.ContextManager().has_current_node():
625
621
  details = "Attempted to create a Connection with a source node from the Current Context. Failed because the Current Context was empty."
626
- logger.error(details)
627
622
  return CreateConnectionResultFailure(result_details=details)
628
623
 
629
624
  # Get the current node from context
@@ -634,7 +629,6 @@ class FlowManager:
634
629
  source_node = GriptapeNodes.NodeManager().get_node_by_name(source_node_name)
635
630
  except ValueError as err:
636
631
  details = f'Connection failed: "{source_node_name}" does not exist. Error: {err}.'
637
- logger.error(details)
638
632
 
639
633
  return CreateConnectionResultFailure(result_details=details)
640
634
 
@@ -644,7 +638,6 @@ class FlowManager:
644
638
  # First check if we have a current node
645
639
  if not GriptapeNodes.ContextManager().has_current_node():
646
640
  details = "Attempted to create a Connection with the target node from the Current Context. Failed because the Current Context was empty."
647
- logger.error(details)
648
641
  return CreateConnectionResultFailure(result_details=details)
649
642
 
650
643
  # Get the current node from context
@@ -655,7 +648,6 @@ class FlowManager:
655
648
  target_node = GriptapeNodes.NodeManager().get_node_by_name(target_node_name)
656
649
  except ValueError as err:
657
650
  details = f'Connection failed: "{target_node_name}" does not exist. Error: {err}.'
658
- logger.error(details)
659
651
  return CreateConnectionResultFailure(result_details=details)
660
652
 
661
653
  # The two nodes exist.
@@ -666,7 +658,6 @@ class FlowManager:
666
658
  self.get_flow_by_name(flow_name=source_flow_name)
667
659
  except KeyError as err:
668
660
  details = f'Connection "{source_node_name}.{request.source_parameter_name}" to "{target_node_name}.{request.target_parameter_name}" failed: {err}.'
669
- logger.error(details)
670
661
  return CreateConnectionResultFailure(result_details=details)
671
662
 
672
663
  target_flow_name = None
@@ -675,7 +666,6 @@ class FlowManager:
675
666
  self.get_flow_by_name(flow_name=target_flow_name)
676
667
  except KeyError as err:
677
668
  details = f'Connection "{source_node_name}.{request.source_parameter_name}" to "{target_node_name}.{request.target_parameter_name}" failed: {err}.'
678
- logger.error(details)
679
669
  return CreateConnectionResultFailure(result_details=details)
680
670
 
681
671
  # Cross-flow connections are now supported via global connection storage
@@ -696,14 +686,12 @@ class FlowManager:
696
686
  source_param = source_node.get_parameter_by_name(request.source_parameter_name)
697
687
  if source_param is None:
698
688
  details = f'Connection failed: "{source_node_name}.{request.source_parameter_name}" not found'
699
- logger.error(details)
700
689
  return CreateConnectionResultFailure(result_details=details)
701
690
 
702
691
  target_param = target_node.get_parameter_by_name(request.target_parameter_name)
703
692
  if target_param is None:
704
693
  # TODO: https://github.com/griptape-ai/griptape-nodes/issues/860
705
694
  details = f'Connection failed: "{target_node_name}.{request.target_parameter_name}" not found'
706
- logger.error(details)
707
695
  return CreateConnectionResultFailure(result_details=details)
708
696
  # Validate parameter modes accept this type of connection.
709
697
  source_modes_allowed = source_param.allowed_modes
@@ -711,19 +699,16 @@ class FlowManager:
711
699
  details = (
712
700
  f'Connection failed: "{source_node_name}.{request.source_parameter_name}" is not an allowed OUTPUT'
713
701
  )
714
- logger.error(details)
715
702
  return CreateConnectionResultFailure(result_details=details)
716
703
 
717
704
  target_modes_allowed = target_param.allowed_modes
718
705
  if ParameterMode.INPUT not in target_modes_allowed:
719
706
  details = f'Connection failed: "{target_node_name}.{request.target_parameter_name}" is not an allowed INPUT'
720
- logger.error(details)
721
707
  return CreateConnectionResultFailure(result_details=details)
722
708
 
723
709
  # Validate that the data type from the source is allowed by the target.
724
710
  if not target_param.is_incoming_type_allowed(source_param.output_type):
725
711
  details = f'Connection failed on type mismatch "{source_node_name}.{request.source_parameter_name}" type({source_param.output_type}) to "{target_node_name}.{request.target_parameter_name}" types({target_param.input_types}) '
726
- logger.error(details)
727
712
  return CreateConnectionResultFailure(result_details=details)
728
713
 
729
714
  # Ask each node involved to bless this union.
@@ -735,7 +720,6 @@ class FlowManager:
735
720
  details = (
736
721
  f'Connection failed : "{source_node_name}.{request.source_parameter_name}" rejected the connection '
737
722
  )
738
- logger.error(details)
739
723
  return CreateConnectionResultFailure(result_details=details)
740
724
 
741
725
  if not target_node.allow_incoming_connection(
@@ -746,7 +730,6 @@ class FlowManager:
746
730
  details = (
747
731
  f'Connection failed : "{target_node_name}.{request.target_parameter_name}" rejected the connection '
748
732
  )
749
- logger.error(details)
750
733
  return CreateConnectionResultFailure(result_details=details)
751
734
 
752
735
  # Based on user feedback, if a connection already exists in a scenario where only ONE such connection can exist
@@ -786,11 +769,9 @@ class FlowManager:
786
769
  delete_old_result = GriptapeNodes.handle_request(delete_old_request)
787
770
  if delete_old_result.failed():
788
771
  details = f"Attempted to connect '{source_node_name}.{request.source_parameter_name}'. Failed because there was a previous connection from '{old_source_node_name}.{old_source_param_name}' to '{old_target_node_name}.{old_target_param_name}' that could not be deleted."
789
- logger.error(details)
790
772
  return CreateConnectionResultFailure(result_details=details)
791
773
 
792
774
  details = f"Deleted the previous connection from '{old_source_node_name}.{old_source_param_name}' to '{old_target_node_name}.{old_target_param_name}' to make room for the new connection."
793
- logger.debug(details)
794
775
  try:
795
776
  # Actually create the Connection.
796
777
  self._connections.add_connection(
@@ -801,7 +782,6 @@ class FlowManager:
801
782
  )
802
783
  except ValueError as e:
803
784
  details = f'Connection failed: "{e}"'
804
- logger.error(details)
805
785
 
806
786
  # Attempt to restore any old connection that may have been present.
807
787
  if (
@@ -820,7 +800,6 @@ class FlowManager:
820
800
  create_old_connection_result = GriptapeNodes.handle_request(create_old_connection_request)
821
801
  if create_old_connection_result.failed():
822
802
  details = "Failed attempting to restore the old Connection after failing the replacement. A thousand pardons."
823
- logger.error(details)
824
803
  return CreateConnectionResultFailure(result_details=details)
825
804
 
826
805
  # Let the source make any internal handling decisions now that the Connection has been made.
@@ -836,7 +815,6 @@ class FlowManager:
836
815
  )
837
816
 
838
817
  details = f'Connected "{source_node_name}.{request.source_parameter_name}" to "{target_node_name}.{request.target_parameter_name}"'
839
- logger.debug(details)
840
818
 
841
819
  # Now update the parameter values if it exists.
842
820
  # check if it's been resolved/has a value in parameter_output_values
@@ -879,7 +857,7 @@ class FlowManager:
879
857
  if isinstance(target_node, ErrorProxyNode):
880
858
  target_node.set_post_init_connections_modified()
881
859
 
882
- result = CreateConnectionResultSuccess()
860
+ result = CreateConnectionResultSuccess(result_details=details)
883
861
 
884
862
  return result
885
863
 
@@ -893,7 +871,6 @@ class FlowManager:
893
871
  # First check if we have a current node
894
872
  if not GriptapeNodes.ContextManager().has_current_node():
895
873
  details = "Attempted to delete a Connection with a source node from the Current Context. Failed because the Current Context was empty."
896
- logger.error(details)
897
874
  return DeleteConnectionResultFailure(result_details=details)
898
875
 
899
876
  # Get the current node from context
@@ -904,7 +881,6 @@ class FlowManager:
904
881
  source_node = GriptapeNodes.NodeManager().get_node_by_name(source_node_name)
905
882
  except ValueError as err:
906
883
  details = f'Connection not deleted "{source_node_name}.{request.source_parameter_name}" to "{target_node_name}.{request.target_parameter_name}". Error: {err}'
907
- logger.error(details)
908
884
 
909
885
  return DeleteConnectionResultFailure(result_details=details)
910
886
 
@@ -913,7 +889,6 @@ class FlowManager:
913
889
  # First check if we have a current node
914
890
  if not GriptapeNodes.ContextManager().has_current_node():
915
891
  details = "Attempted to delete a Connection with a target node from the Current Context. Failed because the Current Context was empty."
916
- logger.error(details)
917
892
  return DeleteConnectionResultFailure(result_details=details)
918
893
 
919
894
  # Get the current node from context
@@ -924,7 +899,6 @@ class FlowManager:
924
899
  target_node = GriptapeNodes.NodeManager().get_node_by_name(target_node_name)
925
900
  except ValueError as err:
926
901
  details = f'Connection not deleted "{source_node_name}.{request.source_parameter_name}" to "{target_node_name}.{request.target_parameter_name}". Error: {err}'
927
- logger.error(details)
928
902
 
929
903
  return DeleteConnectionResultFailure(result_details=details)
930
904
 
@@ -936,7 +910,6 @@ class FlowManager:
936
910
  self.get_flow_by_name(flow_name=source_flow_name)
937
911
  except KeyError as err:
938
912
  details = f'Connection not deleted "{source_node_name}.{request.source_parameter_name}" to "{target_node_name}.{request.target_parameter_name}". Error: {err}'
939
- logger.error(details)
940
913
 
941
914
  return DeleteConnectionResultFailure(result_details=details)
942
915
 
@@ -946,7 +919,6 @@ class FlowManager:
946
919
  self.get_flow_by_name(flow_name=target_flow_name)
947
920
  except KeyError as err:
948
921
  details = f'Connection not deleted "{source_node_name}.{request.source_parameter_name}" to "{target_node_name}.{request.target_parameter_name}". Error: {err}'
949
- logger.error(details)
950
922
 
951
923
  return DeleteConnectionResultFailure(result_details=details)
952
924
 
@@ -956,14 +928,12 @@ class FlowManager:
956
928
  source_param = source_node.get_parameter_by_name(request.source_parameter_name)
957
929
  if source_param is None:
958
930
  details = f'Connection not deleted "{source_node_name}.{request.source_parameter_name}" Not found.'
959
- logger.error(details)
960
931
 
961
932
  return DeleteConnectionResultFailure(result_details=details)
962
933
 
963
934
  target_param = target_node.get_parameter_by_name(request.target_parameter_name)
964
935
  if target_param is None:
965
936
  details = f'Connection not deleted "{target_node_name}.{request.target_parameter_name}" Not found.'
966
- logger.error(details)
967
937
 
968
938
  return DeleteConnectionResultFailure(result_details=details)
969
939
 
@@ -975,7 +945,6 @@ class FlowManager:
975
945
  target_parameter=target_param,
976
946
  ):
977
947
  details = f'Connection does not exist: "{source_node_name}.{request.source_parameter_name}" to "{target_node_name}.{request.target_parameter_name}"'
978
- logger.error(details)
979
948
 
980
949
  return DeleteConnectionResultFailure(result_details=details)
981
950
 
@@ -987,7 +956,6 @@ class FlowManager:
987
956
  target_parameter=target_param.name,
988
957
  ):
989
958
  details = f'Connection not deleted "{source_node_name}.{request.source_parameter_name}" to "{target_node_name}.{request.target_parameter_name}". Unknown failure.'
990
- logger.error(details)
991
959
 
992
960
  return DeleteConnectionResultFailure(result_details=details)
993
961
 
@@ -1020,7 +988,6 @@ class FlowManager:
1020
988
  )
1021
989
 
1022
990
  details = f'Connection "{source_node_name}.{request.source_parameter_name}" to "{target_node_name}.{request.target_parameter_name}" deleted.'
1023
- logger.debug(details)
1024
991
 
1025
992
  # Check if either node is ErrorProxyNode and mark connection modification (deletes are always user-initiated)
1026
993
  if isinstance(source_node, ErrorProxyNode):
@@ -1028,16 +995,14 @@ class FlowManager:
1028
995
  if isinstance(target_node, ErrorProxyNode):
1029
996
  target_node.set_post_init_connections_modified()
1030
997
 
1031
- result = DeleteConnectionResultSuccess()
998
+ result = DeleteConnectionResultSuccess(result_details=details)
1032
999
  return result
1033
1000
 
1034
1001
  async def on_start_flow_request(self, request: StartFlowRequest) -> ResultPayload: # noqa: C901, PLR0911, PLR0912
1035
1002
  # which flow
1036
1003
  flow_name = request.flow_name
1037
- debug_mode = request.debug_mode
1038
1004
  if not flow_name:
1039
1005
  details = "Must provide flow name to start a flow."
1040
- logger.error(details)
1041
1006
 
1042
1007
  return StartFlowResultFailure(validation_exceptions=[], result_details=details)
1043
1008
  # get the flow by ID
@@ -1045,12 +1010,10 @@ class FlowManager:
1045
1010
  flow = self.get_flow_by_name(flow_name)
1046
1011
  except KeyError as err:
1047
1012
  details = f"Cannot start flow. Error: {err}"
1048
- logger.error(details)
1049
1013
  return StartFlowResultFailure(validation_exceptions=[err], result_details=details)
1050
1014
  # Check to see if the flow is already running.
1051
1015
  if self.check_for_existing_running_flow():
1052
1016
  details = "Cannot start flow. Flow is already running."
1053
- logger.error(details)
1054
1017
  return StartFlowResultFailure(validation_exceptions=[], result_details=details)
1055
1018
  # A node has been provided to either start or to run up to.
1056
1019
  if request.flow_node_name:
@@ -1058,14 +1021,12 @@ class FlowManager:
1058
1021
  flow_node = GriptapeNodes.ObjectManager().attempt_get_object_by_name_as_type(flow_node_name, BaseNode)
1059
1022
  if not flow_node:
1060
1023
  details = f"Provided node with name {flow_node_name} does not exist"
1061
- logger.error(details)
1062
1024
  return StartFlowResultFailure(validation_exceptions=[], result_details=details)
1063
1025
  # lets get the first control node in the flow!
1064
1026
  start_node = self.get_start_node_from_node(flow, flow_node)
1065
1027
  # if the start is not the node provided, set a breakpoint at the stop (we're running up until there)
1066
1028
  if not start_node:
1067
1029
  details = f"Start node for node with name {flow_node_name} does not exist"
1068
- logger.error(details)
1069
1030
  return StartFlowResultFailure(validation_exceptions=[], result_details=details)
1070
1031
  if start_node != flow_node:
1071
1032
  flow_node.stop_flow = True
@@ -1081,8 +1042,7 @@ class FlowManager:
1081
1042
  try:
1082
1043
  if not result.succeeded():
1083
1044
  details = f"Couldn't start flow with name {flow_name}. Flow Validation Failed"
1084
- logger.error(details)
1085
- return StartFlowResultFailure(validation_exceptions=[])
1045
+ return StartFlowResultFailure(validation_exceptions=[], result_details=details)
1086
1046
  result = cast("ValidateFlowDependenciesResultSuccess", result)
1087
1047
 
1088
1048
  if not result.validation_succeeded:
@@ -1090,36 +1050,30 @@ class FlowManager:
1090
1050
  if len(result.exceptions) > 0:
1091
1051
  for exception in result.exceptions:
1092
1052
  details = f"{details}\n\t{exception}"
1093
- logger.error(details)
1094
1053
  return StartFlowResultFailure(validation_exceptions=result.exceptions, result_details=details)
1095
1054
  except Exception as e:
1096
1055
  details = f"Couldn't start flow with name {flow_name}. Flow Validation Failed: {e}"
1097
- logger.error(details)
1098
1056
  return StartFlowResultFailure(validation_exceptions=[e], result_details=details)
1099
1057
  # By now, it has been validated with no exceptions.
1100
1058
  try:
1101
- await self.start_flow(flow, start_node, debug_mode)
1059
+ await self.start_flow(flow, start_node, debug_mode=request.debug_mode)
1102
1060
  except Exception as e:
1103
1061
  details = f"Failed to kick off flow with name {flow_name}. Exception occurred: {e} "
1104
- logger.error(details)
1105
1062
  return StartFlowResultFailure(validation_exceptions=[e], result_details=details)
1106
1063
 
1107
1064
  details = f"Successfully kicked off flow with name {flow_name}"
1108
- logger.debug(details)
1109
1065
 
1110
- return StartFlowResultSuccess()
1066
+ return StartFlowResultSuccess(result_details=details)
1111
1067
 
1112
1068
  def on_get_flow_state_request(self, event: GetFlowStateRequest) -> ResultPayload:
1113
1069
  flow_name = event.flow_name
1114
1070
  if not flow_name:
1115
1071
  details = "Could not get flow state. No flow name was provided."
1116
- logger.error(details)
1117
1072
  return GetFlowStateResultFailure(result_details=details)
1118
1073
  try:
1119
1074
  flow = self.get_flow_by_name(flow_name)
1120
1075
  except KeyError as err:
1121
1076
  details = f"Could not get flow state. Error: {err}"
1122
- logger.error(details)
1123
1077
  return GetFlowStateResultFailure(result_details=details)
1124
1078
  try:
1125
1079
  control_node, resolving_node = self.flow_state(flow)
@@ -1128,47 +1082,42 @@ class FlowManager:
1128
1082
  logger.exception(details)
1129
1083
  return GetFlowStateResultFailure(result_details=details)
1130
1084
  details = f"Successfully got flow state for flow with name {flow_name}."
1131
- logger.debug(details)
1132
- return GetFlowStateResultSuccess(control_node=control_node, resolving_node=resolving_node)
1085
+ return GetFlowStateResultSuccess(
1086
+ control_node=control_node, resolving_node=resolving_node, result_details=details
1087
+ )
1133
1088
 
1134
1089
  def on_cancel_flow_request(self, request: CancelFlowRequest) -> ResultPayload:
1135
1090
  flow_name = request.flow_name
1136
1091
  if not flow_name:
1137
1092
  details = "Could not cancel flow execution. No flow name was provided."
1138
- logger.error(details)
1139
1093
 
1140
1094
  return CancelFlowResultFailure(result_details=details)
1141
1095
  try:
1142
1096
  self.get_flow_by_name(flow_name)
1143
1097
  except KeyError as err:
1144
1098
  details = f"Could not cancel flow execution. Error: {err}"
1145
- logger.error(details)
1146
1099
 
1147
1100
  return CancelFlowResultFailure(result_details=details)
1148
1101
  try:
1149
1102
  self.cancel_flow_run()
1150
1103
  except Exception as e:
1151
1104
  details = f"Could not cancel flow execution. Exception: {e}"
1152
- logger.error(details)
1153
1105
 
1154
1106
  return CancelFlowResultFailure(result_details=details)
1155
1107
  details = f"Successfully cancelled flow execution with name {flow_name}"
1156
- logger.debug(details)
1157
1108
 
1158
- return CancelFlowResultSuccess()
1109
+ return CancelFlowResultSuccess(result_details=details)
1159
1110
 
1160
1111
  async def on_single_node_step_request(self, request: SingleNodeStepRequest) -> ResultPayload:
1161
1112
  flow_name = request.flow_name
1162
1113
  if not flow_name:
1163
1114
  details = "Could not advance to the next step of a running workflow. No flow name was provided."
1164
- logger.error(details)
1165
1115
 
1166
1116
  return SingleNodeStepResultFailure(validation_exceptions=[], result_details=details)
1167
1117
  try:
1168
1118
  self.get_flow_by_name(flow_name)
1169
1119
  except KeyError as err:
1170
1120
  details = f"Could not advance to the next step of a running workflow. No flow with name {flow_name} exists. Error: {err}"
1171
- logger.error(details)
1172
1121
 
1173
1122
  return SingleNodeStepResultFailure(validation_exceptions=[err], result_details=details)
1174
1123
  try:
@@ -1176,27 +1125,23 @@ class FlowManager:
1176
1125
  await self.single_node_step(flow)
1177
1126
  except Exception as e:
1178
1127
  details = f"Could not advance to the next step of a running workflow. Exception: {e}"
1179
- logger.error(details)
1180
1128
  return SingleNodeStepResultFailure(validation_exceptions=[], result_details=details)
1181
1129
 
1182
1130
  # All completed happily
1183
1131
  details = f"Successfully advanced to the next step of a running workflow with name {flow_name}"
1184
- logger.debug(details)
1185
1132
 
1186
- return SingleNodeStepResultSuccess()
1133
+ return SingleNodeStepResultSuccess(result_details=details)
1187
1134
 
1188
1135
  async def on_single_execution_step_request(self, request: SingleExecutionStepRequest) -> ResultPayload:
1189
1136
  flow_name = request.flow_name
1190
1137
  if not flow_name:
1191
1138
  details = "Could not advance to the next step of a running workflow. No flow name was provided."
1192
- logger.error(details)
1193
1139
 
1194
1140
  return SingleExecutionStepResultFailure(result_details=details)
1195
1141
  try:
1196
1142
  flow = self.get_flow_by_name(flow_name)
1197
1143
  except KeyError as err:
1198
1144
  details = f"Could not advance to the next step of a running workflow. Error: {err}."
1199
- logger.error(details)
1200
1145
 
1201
1146
  return SingleExecutionStepResultFailure(result_details=details)
1202
1147
  change_debug_mode = request.request_id is not None
@@ -1209,61 +1154,50 @@ class FlowManager:
1209
1154
  self.cancel_flow_run()
1210
1155
  except Exception as e_inner:
1211
1156
  details = f"Could not cancel flow execution. Exception: {e_inner}"
1212
- logger.error(details)
1213
1157
 
1214
1158
  details = f"Could not advance to the next step of a running workflow. Exception: {e}"
1215
- logger.error(details)
1216
1159
  return SingleNodeStepResultFailure(validation_exceptions=[e], result_details=details)
1217
1160
  details = f"Successfully advanced to the next step of a running workflow with name {flow_name}"
1218
- logger.debug(details)
1219
1161
 
1220
- return SingleExecutionStepResultSuccess()
1162
+ return SingleExecutionStepResultSuccess(result_details=details)
1221
1163
 
1222
1164
  async def on_continue_execution_step_request(self, request: ContinueExecutionStepRequest) -> ResultPayload:
1223
1165
  flow_name = request.flow_name
1224
1166
  if not flow_name:
1225
1167
  details = "Failed to continue execution step because no flow name was provided"
1226
- logger.error(details)
1227
1168
 
1228
1169
  return ContinueExecutionStepResultFailure(result_details=details)
1229
1170
  try:
1230
1171
  flow = self.get_flow_by_name(flow_name)
1231
1172
  except KeyError as err:
1232
1173
  details = f"Failed to continue execution step. Error: {err}"
1233
- logger.error(details)
1234
1174
 
1235
1175
  return ContinueExecutionStepResultFailure(result_details=details)
1236
1176
  try:
1237
1177
  await self.continue_executing(flow)
1238
1178
  except Exception as e:
1239
1179
  details = f"Failed to continue execution step. An exception occurred: {e}."
1240
- logger.error(details)
1241
1180
  return ContinueExecutionStepResultFailure(result_details=details)
1242
1181
  details = f"Successfully continued flow with name {flow_name}"
1243
- logger.debug(details)
1244
- return ContinueExecutionStepResultSuccess()
1182
+ return ContinueExecutionStepResultSuccess(result_details=details)
1245
1183
 
1246
1184
  def on_unresolve_flow_request(self, request: UnresolveFlowRequest) -> ResultPayload:
1247
1185
  flow_name = request.flow_name
1248
1186
  if not flow_name:
1249
1187
  details = "Failed to unresolve flow because no flow name was provided"
1250
- logger.error(details)
1251
1188
  return UnresolveFlowResultFailure(result_details=details)
1252
1189
  try:
1253
1190
  flow = self.get_flow_by_name(flow_name)
1254
1191
  except KeyError as err:
1255
1192
  details = f"Failed to unresolve flow. Error: {err}"
1256
- logger.error(details)
1257
1193
  return UnresolveFlowResultFailure(result_details=details)
1258
1194
  try:
1259
1195
  self.unresolve_whole_flow(flow)
1260
1196
  except Exception as e:
1261
1197
  details = f"Failed to unresolve flow. An exception occurred: {e}."
1262
- logger.error(details)
1263
1198
  return UnresolveFlowResultFailure(result_details=details)
1264
1199
  details = f"Unresolved flow with name {flow_name}"
1265
- logger.debug(details)
1266
- return UnresolveFlowResultSuccess()
1200
+ return UnresolveFlowResultSuccess(result_details=details)
1267
1201
 
1268
1202
  async def on_validate_flow_dependencies_request(self, request: ValidateFlowDependenciesRequest) -> ResultPayload:
1269
1203
  flow_name = request.flow_name
@@ -1272,14 +1206,12 @@ class FlowManager:
1272
1206
  flow = self.get_flow_by_name(flow_name)
1273
1207
  except KeyError as err:
1274
1208
  details = f"Failed to validate flow. Error: {err}"
1275
- logger.error(details)
1276
1209
  return ValidateFlowDependenciesResultFailure(result_details=details)
1277
1210
  if request.flow_node_name:
1278
1211
  flow_node_name = request.flow_node_name
1279
1212
  flow_node = GriptapeNodes.ObjectManager().attempt_get_object_by_name_as_type(flow_node_name, BaseNode)
1280
1213
  if not flow_node:
1281
1214
  details = f"Provided node with name {flow_node_name} does not exist"
1282
- logger.error(details)
1283
1215
  return ValidateFlowDependenciesResultFailure(result_details=details)
1284
1216
  # Gets all nodes in that connected group to be ran
1285
1217
  nodes = flow.get_all_connected_nodes(flow_node)
@@ -1292,13 +1224,14 @@ class FlowManager:
1292
1224
  if exceptions:
1293
1225
  all_exceptions = all_exceptions + exceptions
1294
1226
  return ValidateFlowDependenciesResultSuccess(
1295
- validation_succeeded=len(all_exceptions) == 0, exceptions=all_exceptions
1227
+ validation_succeeded=len(all_exceptions) == 0,
1228
+ exceptions=all_exceptions,
1229
+ result_details=f"Validated flow dependencies: {len(all_exceptions)} exceptions found",
1296
1230
  )
1297
1231
 
1298
1232
  def on_list_flows_in_current_context_request(self, request: ListFlowsInCurrentContextRequest) -> ResultPayload: # noqa: ARG002 (request isn't actually used)
1299
1233
  if not GriptapeNodes.ContextManager().has_current_flow():
1300
1234
  details = "Attempted to list Flows in the Current Context. Failed because the Current Context was empty."
1301
- logger.error(details)
1302
1235
  return ListFlowsInCurrentContextResultFailure(result_details=details)
1303
1236
 
1304
1237
  parent_flow = GriptapeNodes.ContextManager().get_current_flow()
@@ -1311,9 +1244,8 @@ class FlowManager:
1311
1244
  ret_list.append(flow_name)
1312
1245
 
1313
1246
  details = f"Successfully got the list of Flows in the Current Context (Flow '{parent_flow_name}')."
1314
- logger.debug(details)
1315
1247
 
1316
- return ListFlowsInCurrentContextResultSuccess(flow_names=ret_list)
1248
+ return ListFlowsInCurrentContextResultSuccess(flow_names=ret_list, result_details=details)
1317
1249
 
1318
1250
  # TODO: https://github.com/griptape-ai/griptape-nodes/issues/861
1319
1251
  # similar manager refactors: https://github.com/griptape-ai/griptape-nodes/issues/806
@@ -1326,7 +1258,6 @@ class FlowManager:
1326
1258
  flow_name = flow.name
1327
1259
  else:
1328
1260
  details = "Attempted to serialize a Flow to commands from the Current Context. Failed because the Current Context was empty."
1329
- logger.error(details)
1330
1261
  return SerializeFlowToCommandsResultFailure(result_details=details)
1331
1262
  if flow is None:
1332
1263
  # Does this flow exist?
@@ -1335,7 +1266,6 @@ class FlowManager:
1335
1266
  details = (
1336
1267
  f"Attempted to serialize Flow '{flow_name}' to commands, but no Flow with that name could be found."
1337
1268
  )
1338
- logger.error(details)
1339
1269
  return SerializeFlowToCommandsResultFailure(result_details=details)
1340
1270
 
1341
1271
  # Track all node libraries that were in use by these Nodes
@@ -1381,7 +1311,6 @@ class FlowManager:
1381
1311
  details = (
1382
1312
  f"Attempted to serialize Flow '{flow_name}'. Failed while attempting to list Nodes in the Flow."
1383
1313
  )
1384
- logger.error(details)
1385
1314
  return SerializeFlowToCommandsResultFailure(result_details=details)
1386
1315
 
1387
1316
  # Serialize each node
@@ -1389,7 +1318,6 @@ class FlowManager:
1389
1318
  node = GriptapeNodes.ObjectManager().attempt_get_object_by_name_as_type(node_name, BaseNode)
1390
1319
  if node is None:
1391
1320
  details = f"Attempted to serialize Flow '{flow_name}'. Failed while attempting to serialize Node '{node_name}' within the Flow."
1392
- logger.error(details)
1393
1321
  return SerializeFlowToCommandsResultFailure(result_details=details)
1394
1322
  with GriptapeNodes.ContextManager().node(node):
1395
1323
  # Note: the parameter value stuff is pass-by-reference, and we expect the values to be modified in place.
@@ -1401,7 +1329,6 @@ class FlowManager:
1401
1329
  serialize_node_result = GriptapeNodes.handle_request(serialize_node_request)
1402
1330
  if not isinstance(serialize_node_result, SerializeNodeToCommandsResultSuccess):
1403
1331
  details = f"Attempted to serialize Flow '{flow_name}'. Failed while attempting to serialize Node '{node_name}' within the Flow."
1404
- logger.error(details)
1405
1332
  return SerializeFlowToCommandsResultFailure(result_details=details)
1406
1333
 
1407
1334
  serialized_node = serialize_node_result.serialized_node_commands
@@ -1441,7 +1368,6 @@ class FlowManager:
1441
1368
  flows_in_flow_result = GriptapeNodes().handle_request(flows_in_flow_request)
1442
1369
  if not isinstance(flows_in_flow_result, ListFlowsInFlowResultSuccess):
1443
1370
  details = f"Attempted to serialize Flow '{flow_name}'. Failed while attempting to list child Flows in the Flow."
1444
- logger.error(details)
1445
1371
  return SerializeFlowToCommandsResultFailure(result_details=details)
1446
1372
 
1447
1373
  sub_flow_commands = []
@@ -1449,7 +1375,6 @@ class FlowManager:
1449
1375
  flow = GriptapeNodes.ObjectManager().attempt_get_object_by_name_as_type(child_flow, ControlFlow)
1450
1376
  if flow is None:
1451
1377
  details = f"Attempted to serialize Flow '{flow_name}', but no Flow with that name could be found."
1452
- logger.error(details)
1453
1378
  return SerializeFlowToCommandsResultFailure(result_details=details)
1454
1379
 
1455
1380
  # Check if this is a referenced workflow
@@ -1482,8 +1407,7 @@ class FlowManager:
1482
1407
  child_flow_result = GriptapeNodes().handle_request(child_flow_request)
1483
1408
  if not isinstance(child_flow_result, SerializeFlowToCommandsResultSuccess):
1484
1409
  details = f"Attempted to serialize parent flow '{flow_name}'. Failed while serializing child flow '{child_flow}'."
1485
- logger.error(details)
1486
- return SerializeFlowToCommandsResultFailure()
1410
+ return SerializeFlowToCommandsResultFailure(result_details=details)
1487
1411
  serialized_flow = child_flow_result.serialized_flow_commands
1488
1412
  sub_flow_commands.append(serialized_flow)
1489
1413
 
@@ -1505,7 +1429,7 @@ class FlowManager:
1505
1429
  referenced_workflows=referenced_workflows_in_use,
1506
1430
  )
1507
1431
  details = f"Successfully serialized Flow '{flow_name}' into commands."
1508
- result = SerializeFlowToCommandsResultSuccess(serialized_flow_commands=serialized_flow)
1432
+ result = SerializeFlowToCommandsResultSuccess(serialized_flow_commands=serialized_flow, result_details=details)
1509
1433
  return result
1510
1434
 
1511
1435
  def on_deserialize_flow_from_commands(self, request: DeserializeFlowFromCommandsRequest) -> ResultPayload: # noqa: C901, PLR0911, PLR0912, PLR0915 (I am big and complicated and have a lot of negative edge-cases)
@@ -1516,7 +1440,6 @@ class FlowManager:
1516
1440
  flow_name = flow.name
1517
1441
  else:
1518
1442
  details = "Attempted to deserialize a set of Flow Creation commands into the Current Context. Failed because the Current Context was empty."
1519
- logger.error(details)
1520
1443
  return DeserializeFlowFromCommandsResultFailure(result_details=details)
1521
1444
  else:
1522
1445
  # Issue the creation command first.
@@ -1528,25 +1451,21 @@ class FlowManager:
1528
1451
  case CreateFlowRequest():
1529
1452
  if not isinstance(flow_initialization_result, CreateFlowResultSuccess):
1530
1453
  details = f"Attempted to deserialize a serialized set of Flow Creation commands. Failed to create flow '{flow_initialization_command.flow_name}'."
1531
- logger.error(details)
1532
1454
  return DeserializeFlowFromCommandsResultFailure(result_details=details)
1533
1455
  flow_name = flow_initialization_result.flow_name
1534
1456
  case ImportWorkflowAsReferencedSubFlowRequest():
1535
1457
  if not isinstance(flow_initialization_result, ImportWorkflowAsReferencedSubFlowResultSuccess):
1536
1458
  details = f"Attempted to deserialize a serialized set of Flow Creation commands. Failed to import workflow '{flow_initialization_command.workflow_name}'."
1537
- logger.error(details)
1538
1459
  return DeserializeFlowFromCommandsResultFailure(result_details=details)
1539
1460
  flow_name = flow_initialization_result.created_flow_name
1540
1461
  case _:
1541
1462
  details = f"Attempted to deserialize Flow Creation commands with unknown command type: {type(flow_initialization_command).__name__}."
1542
- logger.error(details)
1543
1463
  return DeserializeFlowFromCommandsResultFailure(result_details=details)
1544
1464
 
1545
1465
  # Adopt the newly-created flow as our current context.
1546
1466
  flow = GriptapeNodes.ObjectManager().attempt_get_object_by_name_as_type(flow_name, ControlFlow)
1547
1467
  if flow is None:
1548
1468
  details = f"Attempted to deserialize a serialized set of Flow Creation commands. Failed to find created flow '{flow_name}'."
1549
- logger.error(details)
1550
1469
  return DeserializeFlowFromCommandsResultFailure(result_details=details)
1551
1470
  GriptapeNodes.ContextManager().push_flow(flow=flow)
1552
1471
 
@@ -1562,7 +1481,6 @@ class FlowManager:
1562
1481
  details = (
1563
1482
  f"Attempted to deserialize a Flow '{flow_name}'. Failed while deserializing a node within the flow."
1564
1483
  )
1565
- logger.error(details)
1566
1484
  return DeserializeFlowFromCommandsResultFailure(result_details=details)
1567
1485
  node_uuid_to_deserialized_node_result[serialized_node.node_uuid] = deserialized_node_result
1568
1486
 
@@ -1574,12 +1492,10 @@ class FlowManager:
1574
1492
  source_node_uuid = indirect_connection.source_node_uuid
1575
1493
  if source_node_uuid not in node_uuid_to_deserialized_node_result:
1576
1494
  details = f"Attempted to deserialize a Flow '{flow_name}'. Failed while attempting to create a Connection for a source node that did not exist within the flow."
1577
- logger.error(details)
1578
1495
  return DeserializeFlowFromCommandsResultFailure(result_details=details)
1579
1496
  target_node_uuid = indirect_connection.target_node_uuid
1580
1497
  if target_node_uuid not in node_uuid_to_deserialized_node_result:
1581
1498
  details = f"Attempted to deserialize a Flow '{flow_name}'. Failed while attempting to create a Connection for a target node that did not exist within the flow."
1582
- logger.error(details)
1583
1499
  return DeserializeFlowFromCommandsResultFailure(result_details=details)
1584
1500
 
1585
1501
  source_node_result = node_uuid_to_deserialized_node_result[source_node_uuid]
@@ -1596,7 +1512,6 @@ class FlowManager:
1596
1512
  create_connection_result = GriptapeNodes.handle_request(create_connection_request)
1597
1513
  if create_connection_result.failed():
1598
1514
  details = f"Attempted to deserialize a Flow '{flow_name}'. Failed while deserializing a Connection from '{source_node_name}.{indirect_connection.source_parameter_name}' to '{target_node_name}.{indirect_connection.target_parameter_name}' within the flow."
1599
- logger.error(details)
1600
1515
  return DeserializeFlowFromCommandsResultFailure(result_details=details)
1601
1516
 
1602
1517
  # Now assign the values.
@@ -1610,7 +1525,6 @@ class FlowManager:
1610
1525
  node = GriptapeNodes.ObjectManager().attempt_get_object_by_name_as_type(node_name, BaseNode)
1611
1526
  if node is None:
1612
1527
  details = f"Attempted to deserialize a Flow '{flow_name}'. Failed while deserializing a value assignment for node '{node_name}'."
1613
- logger.error(details)
1614
1528
  return DeserializeFlowFromCommandsResultFailure(result_details=details)
1615
1529
  with GriptapeNodes.ContextManager().node(node=node):
1616
1530
  # Iterate through each set value command in the list for this node.
@@ -1621,7 +1535,6 @@ class FlowManager:
1621
1535
  value = request.serialized_flow_commands.unique_parameter_uuid_to_values[unique_value_uuid]
1622
1536
  except IndexError as err:
1623
1537
  details = f"Attempted to deserialize a Flow '{flow_name}'. Failed while deserializing a value assignment for node '{node.name}.{parameter_name}': {err}"
1624
- logger.error(details)
1625
1538
  return DeserializeFlowFromCommandsResultFailure(result_details=details)
1626
1539
 
1627
1540
  # Call the SetParameterValueRequest, subbing in the value from our unique value list.
@@ -1631,7 +1544,6 @@ class FlowManager:
1631
1544
  )
1632
1545
  if set_parameter_value_result.failed():
1633
1546
  details = f"Attempted to deserialize a Flow '{flow_name}'. Failed while deserializing a value assignment for node '{node.name}.{parameter_name}'."
1634
- logger.error(details)
1635
1547
  return DeserializeFlowFromCommandsResultFailure(result_details=details)
1636
1548
 
1637
1549
  # Now the child flows.
@@ -1640,12 +1552,10 @@ class FlowManager:
1640
1552
  sub_flow_result = GriptapeNodes.handle_request(sub_flow_request)
1641
1553
  if sub_flow_result.failed():
1642
1554
  details = f"Attempted to deserialize a Flow '{flow_name}'. Failed while deserializing a sub-flow within the Flow."
1643
- logger.error(details)
1644
1555
  return DeserializeFlowFromCommandsResultFailure(result_details=details)
1645
1556
 
1646
1557
  details = f"Successfully deserialized Flow '{flow_name}'."
1647
- logger.debug(details)
1648
- return DeserializeFlowFromCommandsResultSuccess(flow_name=flow_name)
1558
+ return DeserializeFlowFromCommandsResultSuccess(flow_name=flow_name, result_details=details)
1649
1559
 
1650
1560
  def on_flush_request(self, request: FlushParameterChangesRequest) -> ResultPayload: # noqa: ARG002
1651
1561
  obj_manager = GriptapeNodes.ObjectManager()
@@ -1656,9 +1566,15 @@ class FlowManager:
1656
1566
  # Only flush if there are actually tracked parameters
1657
1567
  if node._tracked_parameters:
1658
1568
  node.emit_parameter_changes()
1659
- return FlushParameterChangesResultSuccess()
1569
+ return FlushParameterChangesResultSuccess(result_details="Parameter changes flushed successfully.")
1660
1570
 
1661
- async def start_flow(self, flow: ControlFlow, start_node: BaseNode | None = None, debug_mode: bool = False) -> None: # noqa: FBT001, FBT002, ARG002
1571
+ async def start_flow(
1572
+ self,
1573
+ flow: ControlFlow,
1574
+ start_node: BaseNode | None = None,
1575
+ *,
1576
+ debug_mode: bool = False,
1577
+ ) -> None:
1662
1578
  if self.check_for_existing_running_flow():
1663
1579
  # If flow already exists, throw an error
1664
1580
  errormsg = "This workflow is already in progress. Please wait for the current process to finish before starting again."
@@ -1668,13 +1584,12 @@ class FlowManager:
1668
1584
  if self._global_flow_queue.empty():
1669
1585
  errormsg = "No Flow exists. You must create at least one control connection."
1670
1586
  raise RuntimeError(errormsg)
1671
- start_node = self._global_flow_queue.get()
1587
+ queue_item = self._global_flow_queue.get()
1588
+ start_node = queue_item.node
1672
1589
  self._global_flow_queue.task_done()
1673
1590
 
1674
1591
  # Initialize global control flow machine if needed
1675
- if self._global_control_flow_machine is None:
1676
- self._global_control_flow_machine = ControlFlowMachine()
1677
-
1592
+ self._global_control_flow_machine = ControlFlowMachine(flow.name)
1678
1593
  try:
1679
1594
  await self._global_control_flow_machine.start_flow(start_node, debug_mode)
1680
1595
  except Exception:
@@ -1685,15 +1600,13 @@ class FlowManager:
1685
1600
  def check_for_existing_running_flow(self) -> bool:
1686
1601
  if self._global_control_flow_machine is None:
1687
1602
  return False
1688
- if (
1689
- self._global_control_flow_machine._current_state is not CompleteState
1690
- and self._global_control_flow_machine._current_state
1691
- ):
1603
+ current_state = self._global_control_flow_machine.current_state
1604
+ if current_state and current_state is not CompleteState:
1692
1605
  # Flow already exists in progress
1693
1606
  return True
1694
1607
  return bool(
1695
- not self._global_control_flow_machine._context.resolution_machine.is_complete()
1696
- and self._global_control_flow_machine._context.resolution_machine.is_started()
1608
+ not self._global_control_flow_machine.context.resolution_machine.is_complete()
1609
+ and self._global_control_flow_machine.context.resolution_machine.is_started()
1697
1610
  )
1698
1611
 
1699
1612
  def cancel_flow_run(self) -> None:
@@ -1701,9 +1614,9 @@ class FlowManager:
1701
1614
  errormsg = "Flow has not yet been started. Cannot cancel flow that hasn't begun."
1702
1615
  raise RuntimeError(errormsg)
1703
1616
  self._global_flow_queue.queue.clear()
1704
- if self._global_control_flow_machine is not None:
1705
- self._global_control_flow_machine.reset_machine()
1706
1617
  # Reset control flow machine
1618
+ if self._global_control_flow_machine is not None:
1619
+ self._global_control_flow_machine.reset_machine(cancel=True)
1707
1620
  self._global_single_node_resolution = False
1708
1621
  logger.debug("Cancelling flow run")
1709
1622
 
@@ -1716,7 +1629,7 @@ class FlowManager:
1716
1629
  self._global_flow_queue.queue.clear()
1717
1630
  if self._global_control_flow_machine is not None:
1718
1631
  self._global_control_flow_machine.reset_machine()
1719
- self._global_control_flow_machine = None
1632
+ # Reset control flow machine
1720
1633
  self._global_single_node_resolution = False
1721
1634
 
1722
1635
  # Clear all connections to prevent memory leaks and stale references
@@ -1735,9 +1648,9 @@ class FlowManager:
1735
1648
  """Get the next node from the global execution queue, or None if empty."""
1736
1649
  if self._global_flow_queue.empty():
1737
1650
  return None
1738
- node = self._global_flow_queue.get()
1651
+ queue_item = self._global_flow_queue.get()
1739
1652
  self._global_flow_queue.task_done()
1740
- return node
1653
+ return queue_item.node
1741
1654
 
1742
1655
  def clear_execution_queue(self) -> None:
1743
1656
  """Clear all nodes from the global execution queue."""
@@ -1756,7 +1669,7 @@ class FlowManager:
1756
1669
  # Internal execution queue helper methods to consolidate redundant operations
1757
1670
  async def _handle_flow_start_if_not_running(
1758
1671
  self,
1759
- flow: ControlFlow, # noqa: ARG002
1672
+ flow: ControlFlow,
1760
1673
  *,
1761
1674
  debug_mode: bool,
1762
1675
  error_message: str,
@@ -1765,42 +1678,43 @@ class FlowManager:
1765
1678
  if not self.check_for_existing_running_flow():
1766
1679
  if self._global_flow_queue.empty():
1767
1680
  raise RuntimeError(error_message)
1768
- start_node = self._global_flow_queue.get()
1681
+ queue_item = self._global_flow_queue.get()
1682
+ start_node = queue_item.node
1769
1683
  self._global_flow_queue.task_done()
1684
+ # Get or create machine
1770
1685
  if self._global_control_flow_machine is None:
1771
- self._global_control_flow_machine = ControlFlowMachine()
1686
+ self._global_control_flow_machine = ControlFlowMachine(flow.name)
1772
1687
  await self._global_control_flow_machine.start_flow(start_node, debug_mode)
1773
1688
 
1774
1689
  async def _handle_post_execution_queue_processing(self, *, debug_mode: bool) -> None:
1775
1690
  """Handle execution queue processing after execution completes."""
1776
1691
  if not self.check_for_existing_running_flow() and not self._global_flow_queue.empty():
1777
- start_node = self._global_flow_queue.get()
1692
+ queue_item = self._global_flow_queue.get()
1693
+ start_node = queue_item.node
1778
1694
  self._global_flow_queue.task_done()
1779
- if self._global_control_flow_machine is not None:
1780
- await self._global_control_flow_machine.start_flow(start_node, debug_mode)
1695
+ machine = self._global_control_flow_machine
1696
+ if machine is not None:
1697
+ await machine.start_flow(start_node, debug_mode)
1781
1698
 
1782
- async def resolve_singular_node(self, flow: ControlFlow, node: BaseNode, debug_mode: bool = False) -> None: # noqa: FBT001, FBT002, ARG002
1699
+ async def resolve_singular_node(self, flow: ControlFlow, node: BaseNode, *, debug_mode: bool = False) -> None:
1783
1700
  # Set that we are only working on one node right now! no other stepping allowed
1784
1701
  if self.check_for_existing_running_flow():
1785
1702
  # If flow already exists, throw an error
1786
1703
  errormsg = f"This workflow is already in progress. Please wait for the current process to finish before starting {node.name} again."
1787
1704
  raise RuntimeError(errormsg)
1788
1705
  self._global_single_node_resolution = True
1789
- # Initialize global control flow machine if needed
1790
- if self._global_control_flow_machine is None:
1791
- self._global_control_flow_machine = ControlFlowMachine()
1792
- # Get the node resolution machine for the current flow!
1793
- self._global_control_flow_machine._context.current_node = node
1794
- resolution_machine = self._global_control_flow_machine._context.resolution_machine
1795
- # Set debug mode
1796
- resolution_machine.change_debug_mode(debug_mode)
1797
- # Resolve the node.
1706
+
1707
+ # Get or create machine
1708
+ self._global_control_flow_machine = ControlFlowMachine(flow.name)
1709
+ self._global_control_flow_machine.context.current_node = node
1710
+ resolution_machine = self._global_control_flow_machine.resolution_machine
1711
+ resolution_machine.change_debug_mode(debug_mode=debug_mode)
1798
1712
  node.state = NodeResolutionState.UNRESOLVED
1713
+ # Resolve the node
1799
1714
  await resolution_machine.resolve_node(node)
1800
- # decide if we can change it back to normal flow mode!
1801
1715
  if resolution_machine.is_complete():
1802
1716
  self._global_single_node_resolution = False
1803
- self._global_control_flow_machine._context.current_node = None
1717
+ self._global_control_flow_machine.context.current_node = None
1804
1718
 
1805
1719
  async def single_execution_step(self, flow: ControlFlow, change_debug_mode: bool) -> None: # noqa: FBT001
1806
1720
  # do a granular step
@@ -1811,11 +1725,11 @@ class FlowManager:
1811
1725
  return
1812
1726
  if self._global_control_flow_machine is not None:
1813
1727
  await self._global_control_flow_machine.granular_step(change_debug_mode)
1814
- resolution_machine = self._global_control_flow_machine._context.resolution_machine
1728
+ resolution_machine = self._global_control_flow_machine.resolution_machine
1815
1729
  if self._global_single_node_resolution:
1816
- resolution_machine = self._global_control_flow_machine._context.resolution_machine
1817
- if resolution_machine.is_complete():
1818
- self._global_single_node_resolution = False
1730
+ resolution_machine = self._global_control_flow_machine.resolution_machine
1731
+ if resolution_machine.is_complete():
1732
+ self._global_single_node_resolution = False
1819
1733
 
1820
1734
  async def single_node_step(self, flow: ControlFlow) -> None:
1821
1735
  # It won't call single_node_step without an existing flow running from US.
@@ -1840,13 +1754,13 @@ class FlowManager:
1840
1754
  if not self.check_for_existing_running_flow():
1841
1755
  return
1842
1756
  # Turn all debugging to false and continue on
1843
- if self._global_control_flow_machine is not None:
1757
+ if self._global_control_flow_machine is not None and self._global_control_flow_machine is not None:
1844
1758
  self._global_control_flow_machine.change_debug_mode(False)
1845
1759
  if self._global_single_node_resolution:
1846
- if self._global_control_flow_machine._context.resolution_machine.is_complete():
1760
+ if self._global_control_flow_machine.resolution_machine.is_complete():
1847
1761
  self._global_single_node_resolution = False
1848
1762
  else:
1849
- await self._global_control_flow_machine._context.resolution_machine.update()
1763
+ await self._global_control_flow_machine.resolution_machine.update()
1850
1764
  else:
1851
1765
  await self._global_control_flow_machine.node_step()
1852
1766
  # Now it is done executing. make sure it's actually done?
@@ -1864,12 +1778,11 @@ class FlowManager:
1864
1778
  raise RuntimeError(msg)
1865
1779
  if self._global_control_flow_machine is None:
1866
1780
  return None, None
1781
+ control_flow_context = self._global_control_flow_machine.context
1867
1782
  current_control_node = (
1868
- self._global_control_flow_machine._context.current_node.name
1869
- if self._global_control_flow_machine._context.current_node is not None
1870
- else None
1783
+ control_flow_context.current_node.name if control_flow_context.current_node is not None else None
1871
1784
  )
1872
- focus_stack_for_node = self._global_control_flow_machine._context.resolution_machine._context.focus_stack
1785
+ focus_stack_for_node = self._global_control_flow_machine.resolution_machine.context.focus_stack
1873
1786
  current_resolving_node = focus_stack_for_node[-1].node.name if len(focus_stack_for_node) else None
1874
1787
  return current_control_node, current_resolving_node
1875
1788
 
@@ -1984,13 +1897,13 @@ class FlowManager:
1984
1897
  # check if it has an outgoing connection. We don't want it to (that means we get the most resolution)
1985
1898
  if node.name not in cn_mgr.outgoing_index:
1986
1899
  valid_data_nodes.append(node)
1987
- # ok now - populate the global flow queue
1900
+ # ok now - populate the global flow queue with node type information
1988
1901
  for node in start_nodes:
1989
- self._global_flow_queue.put(node)
1902
+ self._global_flow_queue.put(QueueItem(node=node, dag_execution_type=DagExecutionType.START_NODE))
1990
1903
  for node in control_nodes:
1991
- self._global_flow_queue.put(node)
1904
+ self._global_flow_queue.put(QueueItem(node=node, dag_execution_type=DagExecutionType.CONTROL_NODE))
1992
1905
  for node in valid_data_nodes:
1993
- self._global_flow_queue.put(node)
1906
+ self._global_flow_queue.put(QueueItem(node=node, dag_execution_type=DagExecutionType.DATA_NODE))
1994
1907
 
1995
1908
  return self._global_flow_queue
1996
1909