griptape-nodes 0.46.0__py3-none-any.whl → 0.47.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/exe_types/core_types.py +65 -10
- griptape_nodes/exe_types/node_types.py +10 -0
- griptape_nodes/machines/node_resolution.py +10 -8
- griptape_nodes/retained_mode/events/base_events.py +74 -1
- griptape_nodes/retained_mode/events/secrets_events.py +2 -0
- griptape_nodes/retained_mode/griptape_nodes.py +17 -13
- griptape_nodes/retained_mode/managers/agent_manager.py +8 -6
- griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py +1 -1
- griptape_nodes/retained_mode/managers/config_manager.py +36 -45
- griptape_nodes/retained_mode/managers/flow_manager.py +98 -98
- griptape_nodes/retained_mode/managers/library_manager.py +51 -51
- griptape_nodes/retained_mode/managers/node_manager.py +121 -124
- griptape_nodes/retained_mode/managers/object_manager.py +9 -10
- griptape_nodes/retained_mode/managers/os_manager.py +31 -31
- griptape_nodes/retained_mode/managers/secrets_manager.py +5 -5
- griptape_nodes/retained_mode/managers/static_files_manager.py +18 -17
- griptape_nodes/retained_mode/managers/sync_manager.py +3 -2
- griptape_nodes/retained_mode/managers/workflow_manager.py +134 -160
- griptape_nodes/retained_mode/retained_mode.py +22 -44
- {griptape_nodes-0.46.0.dist-info → griptape_nodes-0.47.0.dist-info}/METADATA +1 -1
- {griptape_nodes-0.46.0.dist-info → griptape_nodes-0.47.0.dist-info}/RECORD +23 -23
- {griptape_nodes-0.46.0.dist-info → griptape_nodes-0.47.0.dist-info}/WHEEL +1 -1
- {griptape_nodes-0.46.0.dist-info → griptape_nodes-0.47.0.dist-info}/entry_points.txt +0 -0
|
@@ -528,7 +528,7 @@ class WorkflowManager:
|
|
|
528
528
|
if not Path(complete_file_path).is_file():
|
|
529
529
|
details = f"Failed to find file. Path '{complete_file_path}' doesn't exist."
|
|
530
530
|
logger.error(details)
|
|
531
|
-
return RunWorkflowFromScratchResultFailure()
|
|
531
|
+
return RunWorkflowFromScratchResultFailure(result_details=details)
|
|
532
532
|
|
|
533
533
|
# Start with a clean slate.
|
|
534
534
|
clear_all_request = ClearAllObjectStateRequest(i_know_what_im_doing=True)
|
|
@@ -536,7 +536,7 @@ class WorkflowManager:
|
|
|
536
536
|
if not clear_all_result.succeeded():
|
|
537
537
|
details = f"Failed to clear the existing object state when trying to run '{complete_file_path}'."
|
|
538
538
|
logger.error(details)
|
|
539
|
-
return RunWorkflowFromScratchResultFailure()
|
|
539
|
+
return RunWorkflowFromScratchResultFailure(result_details=details)
|
|
540
540
|
|
|
541
541
|
# Run the file, goddamn it
|
|
542
542
|
execution_result = self.run_workflow(relative_file_path=relative_file_path)
|
|
@@ -545,7 +545,7 @@ class WorkflowManager:
|
|
|
545
545
|
return RunWorkflowFromScratchResultSuccess()
|
|
546
546
|
|
|
547
547
|
logger.error(execution_result.execution_details)
|
|
548
|
-
return RunWorkflowFromScratchResultFailure()
|
|
548
|
+
return RunWorkflowFromScratchResultFailure(result_details=execution_result.execution_details)
|
|
549
549
|
|
|
550
550
|
def on_run_workflow_with_current_state_request(self, request: RunWorkflowWithCurrentStateRequest) -> ResultPayload:
|
|
551
551
|
relative_file_path = request.file_path
|
|
@@ -553,22 +553,23 @@ class WorkflowManager:
|
|
|
553
553
|
if not Path(complete_file_path).is_file():
|
|
554
554
|
details = f"Failed to find file. Path '{complete_file_path}' doesn't exist."
|
|
555
555
|
logger.error(details)
|
|
556
|
-
return RunWorkflowWithCurrentStateResultFailure()
|
|
556
|
+
return RunWorkflowWithCurrentStateResultFailure(result_details=details)
|
|
557
557
|
execution_result = self.run_workflow(relative_file_path=relative_file_path)
|
|
558
558
|
|
|
559
559
|
if execution_result.execution_successful:
|
|
560
560
|
logger.debug(execution_result.execution_details)
|
|
561
561
|
return RunWorkflowWithCurrentStateResultSuccess()
|
|
562
562
|
logger.error(execution_result.execution_details)
|
|
563
|
-
return RunWorkflowWithCurrentStateResultFailure()
|
|
563
|
+
return RunWorkflowWithCurrentStateResultFailure(result_details=execution_result.execution_details)
|
|
564
564
|
|
|
565
565
|
def on_run_workflow_from_registry_request(self, request: RunWorkflowFromRegistryRequest) -> ResultPayload:
|
|
566
566
|
# get workflow from registry
|
|
567
567
|
try:
|
|
568
568
|
workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
569
569
|
except KeyError:
|
|
570
|
-
|
|
571
|
-
|
|
570
|
+
details = f"Failed to get workflow '{request.workflow_name}' from registry."
|
|
571
|
+
logger.error(details)
|
|
572
|
+
return RunWorkflowFromRegistryResultFailure(result_details=details)
|
|
572
573
|
|
|
573
574
|
# Update current context for workflow.
|
|
574
575
|
if GriptapeNodes.ContextManager().has_current_workflow():
|
|
@@ -587,7 +588,7 @@ class WorkflowManager:
|
|
|
587
588
|
if not clear_all_result.succeeded():
|
|
588
589
|
details = f"Failed to clear the existing object state when preparing to run workflow '{request.workflow_name}'."
|
|
589
590
|
logger.error(details)
|
|
590
|
-
return RunWorkflowFromRegistryResultFailure()
|
|
591
|
+
return RunWorkflowFromRegistryResultFailure(result_details=details)
|
|
591
592
|
|
|
592
593
|
# Let's run under the assumption that this Workflow will become our Current Context; if we fail, it will revert.
|
|
593
594
|
GriptapeNodes.ContextManager().push_workflow(request.workflow_name)
|
|
@@ -602,7 +603,7 @@ class WorkflowManager:
|
|
|
602
603
|
clear_all_result = GriptapeNodes.handle_request(clear_all_request)
|
|
603
604
|
|
|
604
605
|
# The clear-all above here wipes the ContextManager, so no need to do a pop_workflow().
|
|
605
|
-
return RunWorkflowFromRegistryResultFailure()
|
|
606
|
+
return RunWorkflowFromRegistryResultFailure(result_details=execution_result.execution_details)
|
|
606
607
|
|
|
607
608
|
# Success!
|
|
608
609
|
logger.debug(execution_result.execution_details)
|
|
@@ -617,7 +618,7 @@ class WorkflowManager:
|
|
|
617
618
|
except Exception as e:
|
|
618
619
|
details = f"Failed to register workflow with name '{request.metadata.name}'. Error: {e}"
|
|
619
620
|
logger.error(details)
|
|
620
|
-
return RegisterWorkflowResultFailure()
|
|
621
|
+
return RegisterWorkflowResultFailure(result_details=details)
|
|
621
622
|
return RegisterWorkflowResultSuccess(workflow_name=workflow.metadata.name)
|
|
622
623
|
|
|
623
624
|
def on_list_all_workflows_request(self, _request: ListAllWorkflowsRequest) -> ResultPayload:
|
|
@@ -626,7 +627,7 @@ class WorkflowManager:
|
|
|
626
627
|
except Exception:
|
|
627
628
|
details = "Failed to list all workflows."
|
|
628
629
|
logger.error(details)
|
|
629
|
-
return ListAllWorkflowsResultFailure()
|
|
630
|
+
return ListAllWorkflowsResultFailure(result_details=details)
|
|
630
631
|
return ListAllWorkflowsResultSuccess(workflows=workflows)
|
|
631
632
|
|
|
632
633
|
def on_delete_workflows_request(self, request: DeleteWorkflowRequest) -> ResultPayload:
|
|
@@ -635,14 +636,14 @@ class WorkflowManager:
|
|
|
635
636
|
except Exception as e:
|
|
636
637
|
details = f"Failed to remove workflow from registry with name '{request.name}'. Exception: {e}"
|
|
637
638
|
logger.error(details)
|
|
638
|
-
return DeleteWorkflowResultFailure()
|
|
639
|
+
return DeleteWorkflowResultFailure(result_details=details)
|
|
639
640
|
config_manager = GriptapeNodes.ConfigManager()
|
|
640
641
|
try:
|
|
641
642
|
config_manager.delete_user_workflow(workflow.file_path)
|
|
642
643
|
except Exception as e:
|
|
643
644
|
details = f"Failed to remove workflow from user config with name '{request.name}'. Exception: {e}"
|
|
644
645
|
logger.error(details)
|
|
645
|
-
return DeleteWorkflowResultFailure()
|
|
646
|
+
return DeleteWorkflowResultFailure(result_details=details)
|
|
646
647
|
# delete the actual file
|
|
647
648
|
full_path = config_manager.workspace_path.joinpath(workflow.file_path)
|
|
648
649
|
try:
|
|
@@ -650,7 +651,7 @@ class WorkflowManager:
|
|
|
650
651
|
except Exception as e:
|
|
651
652
|
details = f"Failed to delete workflow file with path '{workflow.file_path}'. Exception: {e}"
|
|
652
653
|
logger.error(details)
|
|
653
|
-
return DeleteWorkflowResultFailure()
|
|
654
|
+
return DeleteWorkflowResultFailure(result_details=details)
|
|
654
655
|
return DeleteWorkflowResultSuccess()
|
|
655
656
|
|
|
656
657
|
def on_rename_workflow_request(self, request: RenameWorkflowRequest) -> ResultPayload:
|
|
@@ -659,13 +660,13 @@ class WorkflowManager:
|
|
|
659
660
|
if isinstance(save_workflow_request, SaveWorkflowResultFailure):
|
|
660
661
|
details = f"Attempted to rename workflow '{request.workflow_name}' to '{request.requested_name}'. Failed while attempting to save."
|
|
661
662
|
logger.error(details)
|
|
662
|
-
return RenameWorkflowResultFailure()
|
|
663
|
+
return RenameWorkflowResultFailure(result_details=details)
|
|
663
664
|
|
|
664
665
|
delete_workflow_result = GriptapeNodes.handle_request(DeleteWorkflowRequest(name=request.workflow_name))
|
|
665
666
|
if isinstance(delete_workflow_result, DeleteWorkflowResultFailure):
|
|
666
667
|
details = f"Attempted to rename workflow '{request.workflow_name}' to '{request.requested_name}'. Failed while attempting to remove the original file name from the registry."
|
|
667
668
|
logger.error(details)
|
|
668
|
-
return RenameWorkflowResultFailure()
|
|
669
|
+
return RenameWorkflowResultFailure(result_details=details)
|
|
669
670
|
|
|
670
671
|
return RenameWorkflowResultSuccess()
|
|
671
672
|
|
|
@@ -674,18 +675,20 @@ class WorkflowManager:
|
|
|
674
675
|
# Validate source workflow exists
|
|
675
676
|
workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
676
677
|
except KeyError:
|
|
677
|
-
|
|
678
|
-
|
|
678
|
+
details = f"Failed to move workflow '{request.workflow_name}' because it does not exist."
|
|
679
|
+
logger.error(details)
|
|
680
|
+
return MoveWorkflowResultFailure(result_details=details)
|
|
679
681
|
|
|
680
682
|
config_manager = GriptapeNodes.ConfigManager()
|
|
681
683
|
|
|
682
684
|
# Get current file path
|
|
683
685
|
current_file_path = WorkflowRegistry.get_complete_file_path(workflow.file_path)
|
|
684
686
|
if not Path(current_file_path).exists():
|
|
685
|
-
|
|
686
|
-
"Failed to move workflow '
|
|
687
|
+
details = (
|
|
688
|
+
f"Failed to move workflow '{request.workflow_name}': File path '{current_file_path}' does not exist."
|
|
687
689
|
)
|
|
688
|
-
|
|
690
|
+
logger.error(details)
|
|
691
|
+
return MoveWorkflowResultFailure(result_details=details)
|
|
689
692
|
|
|
690
693
|
# Clean and validate target directory
|
|
691
694
|
target_directory = request.target_directory.strip().replace("\\", "/")
|
|
@@ -698,8 +701,9 @@ class WorkflowManager:
|
|
|
698
701
|
# Create target directory if it doesn't exist
|
|
699
702
|
target_dir_path.mkdir(parents=True, exist_ok=True)
|
|
700
703
|
except OSError as e:
|
|
701
|
-
|
|
702
|
-
|
|
704
|
+
details = f"Failed to create target directory '{target_dir_path}': {e!s}"
|
|
705
|
+
logger.error(details)
|
|
706
|
+
return MoveWorkflowResultFailure(result_details=details)
|
|
703
707
|
|
|
704
708
|
# Create new file path
|
|
705
709
|
workflow_filename = Path(workflow.file_path).name
|
|
@@ -708,12 +712,11 @@ class WorkflowManager:
|
|
|
708
712
|
|
|
709
713
|
# Check if target file already exists
|
|
710
714
|
if new_absolute_path.exists():
|
|
711
|
-
|
|
712
|
-
"Failed to move workflow '
|
|
713
|
-
request.workflow_name,
|
|
714
|
-
new_absolute_path,
|
|
715
|
+
details = (
|
|
716
|
+
f"Failed to move workflow '{request.workflow_name}': Target file '{new_absolute_path}' already exists."
|
|
715
717
|
)
|
|
716
|
-
|
|
718
|
+
logger.error(details)
|
|
719
|
+
return MoveWorkflowResultFailure(result_details=details)
|
|
717
720
|
|
|
718
721
|
try:
|
|
719
722
|
# Move the file
|
|
@@ -727,22 +730,27 @@ class WorkflowManager:
|
|
|
727
730
|
config_manager.save_user_workflow_json(str(new_absolute_path))
|
|
728
731
|
|
|
729
732
|
except OSError as e:
|
|
730
|
-
|
|
733
|
+
details = f"Failed to move workflow file '{current_file_path}' to '{new_absolute_path}': {e!s}"
|
|
734
|
+
logger.error(details)
|
|
731
735
|
|
|
732
736
|
# Attempt to rollback if file was moved but registry update failed
|
|
733
737
|
if new_absolute_path.exists() and not Path(current_file_path).exists():
|
|
734
738
|
try:
|
|
735
739
|
new_absolute_path.rename(current_file_path)
|
|
736
|
-
|
|
740
|
+
details = f"Rolled back file move for workflow '{request.workflow_name}'"
|
|
741
|
+
logger.info(details)
|
|
737
742
|
except OSError:
|
|
738
|
-
|
|
743
|
+
details = f"Failed to rollback file move for workflow '{request.workflow_name}'"
|
|
744
|
+
logger.error(details)
|
|
739
745
|
|
|
740
|
-
return MoveWorkflowResultFailure()
|
|
746
|
+
return MoveWorkflowResultFailure(result_details=details)
|
|
741
747
|
except Exception as e:
|
|
742
|
-
|
|
743
|
-
|
|
748
|
+
details = f"Failed to move workflow '{request.workflow_name}': {e!s}"
|
|
749
|
+
logger.error(details)
|
|
750
|
+
return MoveWorkflowResultFailure(result_details=details)
|
|
744
751
|
else:
|
|
745
|
-
|
|
752
|
+
details = f"Successfully moved workflow '{request.workflow_name}' to '{new_relative_path}'"
|
|
753
|
+
logger.info(details)
|
|
746
754
|
return MoveWorkflowResultSuccess(moved_file_path=new_relative_path)
|
|
747
755
|
|
|
748
756
|
def on_load_workflow_metadata_request( # noqa: C901, PLR0912, PLR0915
|
|
@@ -763,7 +771,7 @@ class WorkflowManager:
|
|
|
763
771
|
)
|
|
764
772
|
details = f"Attempted to load workflow metadata for a file at '{complete_file_path}. Failed because no file could be found at that path."
|
|
765
773
|
logger.error(details)
|
|
766
|
-
return LoadWorkflowMetadataResultFailure()
|
|
774
|
+
return LoadWorkflowMetadataResultFailure(result_details=details)
|
|
767
775
|
|
|
768
776
|
# Find the metadata block.
|
|
769
777
|
block_name = WorkflowManager.WORKFLOW_METADATA_HEADER
|
|
@@ -780,7 +788,7 @@ class WorkflowManager:
|
|
|
780
788
|
)
|
|
781
789
|
details = f"Attempted to load workflow metadata for a file at '{complete_file_path}'. Failed as it had {len(matches)} sections titled '{block_name}', and we expect exactly 1 such section."
|
|
782
790
|
logger.error(details)
|
|
783
|
-
return LoadWorkflowMetadataResultFailure()
|
|
791
|
+
return LoadWorkflowMetadataResultFailure(result_details=details)
|
|
784
792
|
|
|
785
793
|
# Now attempt to parse out the metadata section, stripped of comment prefixes.
|
|
786
794
|
metadata_content_toml = "".join(
|
|
@@ -800,7 +808,7 @@ class WorkflowManager:
|
|
|
800
808
|
)
|
|
801
809
|
details = f"Attempted to load workflow metadata for a file at '{complete_file_path}'. Failed because the metadata was not valid TOML: {err}"
|
|
802
810
|
logger.error(details)
|
|
803
|
-
return LoadWorkflowMetadataResultFailure()
|
|
811
|
+
return LoadWorkflowMetadataResultFailure(result_details=details)
|
|
804
812
|
|
|
805
813
|
tool_header = "tool"
|
|
806
814
|
griptape_nodes_header = "griptape-nodes"
|
|
@@ -816,7 +824,7 @@ class WorkflowManager:
|
|
|
816
824
|
)
|
|
817
825
|
details = f"Attempted to load workflow metadata for a file at '{complete_file_path}'. Failed because the '[{tool_header}.{griptape_nodes_header}]' section could not be found: {err}"
|
|
818
826
|
logger.error(details)
|
|
819
|
-
return LoadWorkflowMetadataResultFailure()
|
|
827
|
+
return LoadWorkflowMetadataResultFailure(result_details=details)
|
|
820
828
|
|
|
821
829
|
try:
|
|
822
830
|
# Is it kosher?
|
|
@@ -834,7 +842,7 @@ class WorkflowManager:
|
|
|
834
842
|
)
|
|
835
843
|
details = f"Attempted to load workflow metadata for a file at '{complete_file_path}'. Failed because the metadata in the '[{tool_header}.{griptape_nodes_header}]' section did not match the requisite schema with error: {err}"
|
|
836
844
|
logger.error(details)
|
|
837
|
-
return LoadWorkflowMetadataResultFailure()
|
|
845
|
+
return LoadWorkflowMetadataResultFailure(result_details=details)
|
|
838
846
|
|
|
839
847
|
# We have valid dependencies, etc.
|
|
840
848
|
# TODO: validate schema versions, engine versions: https://github.com/griptape-ai/griptape-nodes/issues/617
|
|
@@ -1361,14 +1369,15 @@ class WorkflowManager:
|
|
|
1361
1369
|
except Exception as err:
|
|
1362
1370
|
details = f"Attempted to save workflow '{relative_file_path}', but {err}"
|
|
1363
1371
|
logger.error(details)
|
|
1364
|
-
return SaveWorkflowResultFailure()
|
|
1372
|
+
return SaveWorkflowResultFailure(result_details=details)
|
|
1365
1373
|
|
|
1366
1374
|
# Create the pathing and write the file
|
|
1367
1375
|
try:
|
|
1368
1376
|
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1369
1377
|
except OSError as e:
|
|
1370
|
-
|
|
1371
|
-
|
|
1378
|
+
details = f"Attempted to save workflow '{file_name}'. Failed when creating directory: {e}"
|
|
1379
|
+
logger.error(details)
|
|
1380
|
+
return SaveWorkflowResultFailure(result_details=details)
|
|
1372
1381
|
|
|
1373
1382
|
relative_serialized_file_path = f"{file_name}.py"
|
|
1374
1383
|
serialized_file_path = GriptapeNodes.ConfigManager().workspace_path.joinpath(relative_serialized_file_path)
|
|
@@ -1378,17 +1387,17 @@ class WorkflowManager:
|
|
|
1378
1387
|
min_space_gb = config_manager.get_config_value("minimum_disk_space_gb_workflows")
|
|
1379
1388
|
if not OSManager.check_available_disk_space(serialized_file_path.parent, min_space_gb):
|
|
1380
1389
|
error_msg = OSManager.format_disk_space_error(serialized_file_path.parent)
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
)
|
|
1384
|
-
return SaveWorkflowResultFailure()
|
|
1390
|
+
details = f"Attempted to save workflow '{file_name}' (requires {min_space_gb:.1f} GB). Failed: {error_msg}"
|
|
1391
|
+
logger.error(details)
|
|
1392
|
+
return SaveWorkflowResultFailure(result_details=details)
|
|
1385
1393
|
|
|
1386
1394
|
try:
|
|
1387
1395
|
with serialized_file_path.open("w", encoding="utf-8") as file:
|
|
1388
1396
|
file.write(final_code_output)
|
|
1389
1397
|
except OSError as e:
|
|
1390
|
-
|
|
1391
|
-
|
|
1398
|
+
details = f"Attempted to save workflow '{file_name}'. Failed when writing file: {e}"
|
|
1399
|
+
logger.error(details)
|
|
1400
|
+
return SaveWorkflowResultFailure(result_details=details)
|
|
1392
1401
|
|
|
1393
1402
|
# save the created workflow as an entry in the JSON config file.
|
|
1394
1403
|
registered_workflows = WorkflowRegistry.list_workflows()
|
|
@@ -1396,8 +1405,9 @@ class WorkflowManager:
|
|
|
1396
1405
|
try:
|
|
1397
1406
|
GriptapeNodes.ConfigManager().save_user_workflow_json(str(file_path))
|
|
1398
1407
|
except OSError as e:
|
|
1399
|
-
|
|
1400
|
-
|
|
1408
|
+
details = f"Attempted to save workflow '{file_name}'. Failed when saving configuration: {e}"
|
|
1409
|
+
logger.error(details)
|
|
1410
|
+
return SaveWorkflowResultFailure(result_details=details)
|
|
1401
1411
|
WorkflowRegistry.generate_new_workflow(metadata=workflow_metadata, file_path=relative_file_path)
|
|
1402
1412
|
# Update existing workflow's metadata in the registry
|
|
1403
1413
|
existing_workflow = WorkflowRegistry.get_workflow_by_name(file_name)
|
|
@@ -3058,7 +3068,7 @@ class WorkflowManager:
|
|
|
3058
3068
|
except Exception as e:
|
|
3059
3069
|
details = f"Failed to publish workflow '{request.workflow_name}': {e!s}"
|
|
3060
3070
|
logger.exception(details)
|
|
3061
|
-
return PublishWorkflowResultFailure(exception=e)
|
|
3071
|
+
return PublishWorkflowResultFailure(exception=e, result_details=details)
|
|
3062
3072
|
|
|
3063
3073
|
def _register_published_workflow_file(self, workflow_file: Path) -> None:
|
|
3064
3074
|
"""Register a published workflow file in the workflow registry."""
|
|
@@ -3118,45 +3128,35 @@ class WorkflowManager:
|
|
|
3118
3128
|
try:
|
|
3119
3129
|
workflow = self._get_workflow_by_name(request.workflow_name)
|
|
3120
3130
|
except KeyError:
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
)
|
|
3125
|
-
return ImportWorkflowAsReferencedSubFlowResultFailure()
|
|
3131
|
+
details = f"Attempted to import workflow '{request.workflow_name}' as referenced sub flow. Failed because workflow is not registered"
|
|
3132
|
+
logger.error(details)
|
|
3133
|
+
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3126
3134
|
|
|
3127
3135
|
# Check workflow version - Schema version 0.6.0+ required for referenced workflow imports
|
|
3128
3136
|
# (workflow schema was fixed in 0.6.0 to support importing workflows)
|
|
3129
3137
|
required_version = Version(major=0, minor=6, patch=0)
|
|
3130
3138
|
workflow_version = Version.from_string(workflow.metadata.schema_version)
|
|
3131
3139
|
if workflow_version is None or workflow_version < required_version:
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
workflow.metadata.schema_version,
|
|
3136
|
-
)
|
|
3137
|
-
return ImportWorkflowAsReferencedSubFlowResultFailure()
|
|
3140
|
+
details = f"Attempted to import workflow '{request.workflow_name}' as referenced sub flow. Failed because workflow version '{workflow.metadata.schema_version}' is less than required version '0.6.0'. To remedy, open the workflow you are attempting to import and save it again to upgrade it to the latest version."
|
|
3141
|
+
logger.error(details)
|
|
3142
|
+
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3138
3143
|
|
|
3139
3144
|
# Check target flow
|
|
3140
3145
|
flow_name = request.flow_name
|
|
3141
3146
|
if flow_name is None:
|
|
3142
3147
|
if not GriptapeNodes.ContextManager().has_current_flow():
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
)
|
|
3147
|
-
return ImportWorkflowAsReferencedSubFlowResultFailure()
|
|
3148
|
+
details = f"Attempted to import workflow '{request.workflow_name}' into Current Context. Failed because Current Context was empty"
|
|
3149
|
+
logger.error(details)
|
|
3150
|
+
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3148
3151
|
else:
|
|
3149
3152
|
# Validate that the specified flow exists
|
|
3150
3153
|
flow_manager = GriptapeNodes.FlowManager()
|
|
3151
3154
|
try:
|
|
3152
3155
|
flow_manager.get_flow_by_name(flow_name)
|
|
3153
3156
|
except KeyError:
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
flow_name,
|
|
3158
|
-
)
|
|
3159
|
-
return ImportWorkflowAsReferencedSubFlowResultFailure()
|
|
3157
|
+
details = f"Attempted to import workflow '{request.workflow_name}' into flow '{flow_name}'. Failed because target flow does not exist"
|
|
3158
|
+
logger.error(details)
|
|
3159
|
+
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3160
3160
|
|
|
3161
3161
|
return None
|
|
3162
3162
|
|
|
@@ -3178,23 +3178,18 @@ class WorkflowManager:
|
|
|
3178
3178
|
workflow_result = self.run_workflow(workflow.file_path)
|
|
3179
3179
|
|
|
3180
3180
|
if not workflow_result.execution_successful:
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
workflow_result.execution_details,
|
|
3185
|
-
)
|
|
3186
|
-
return ImportWorkflowAsReferencedSubFlowResultFailure()
|
|
3181
|
+
details = f"Attempted to import workflow '{request.workflow_name}' as referenced sub flow. Failed because workflow execution failed: {workflow_result.execution_details}"
|
|
3182
|
+
logger.error(details)
|
|
3183
|
+
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3187
3184
|
|
|
3188
3185
|
# Get flows after importing to find the new referenced sub flow
|
|
3189
3186
|
flows_after = set(obj_manager.get_filtered_subset(type=ControlFlow).keys())
|
|
3190
3187
|
new_flows = flows_after - flows_before
|
|
3191
3188
|
|
|
3192
3189
|
if not new_flows:
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
)
|
|
3197
|
-
return ImportWorkflowAsReferencedSubFlowResultFailure()
|
|
3190
|
+
details = f"Attempted to import workflow '{request.workflow_name}' as referenced sub flow. Failed because no new flow was created"
|
|
3191
|
+
logger.error(details)
|
|
3192
|
+
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3198
3193
|
|
|
3199
3194
|
# For now, use the first created flow as the main imported flow
|
|
3200
3195
|
# This handles nested workflows correctly since sub-flows are expected
|
|
@@ -3216,12 +3211,9 @@ class WorkflowManager:
|
|
|
3216
3211
|
set_metadata_result = GriptapeNodes.handle_request(set_metadata_request)
|
|
3217
3212
|
|
|
3218
3213
|
if not isinstance(set_metadata_result, SetFlowMetadataResultSuccess):
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
created_flow_name,
|
|
3223
|
-
)
|
|
3224
|
-
return ImportWorkflowAsReferencedSubFlowResultFailure()
|
|
3214
|
+
details = f"Attempted to import workflow '{request.workflow_name}' as referenced sub flow. Failed because metadata could not be applied to created flow '{created_flow_name}'"
|
|
3215
|
+
logger.error(details)
|
|
3216
|
+
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3225
3217
|
|
|
3226
3218
|
logger.debug(
|
|
3227
3219
|
"Applied imported flow metadata to '%s': %s", created_flow_name, request.imported_flow_metadata
|
|
@@ -3238,8 +3230,9 @@ class WorkflowManager:
|
|
|
3238
3230
|
# Validate source workflow exists
|
|
3239
3231
|
source_workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
3240
3232
|
except KeyError:
|
|
3241
|
-
|
|
3242
|
-
|
|
3233
|
+
details = f"Failed to branch workflow '{request.workflow_name}' because it does not exist"
|
|
3234
|
+
logger.error(details)
|
|
3235
|
+
return BranchWorkflowResultFailure(result_details=details)
|
|
3243
3236
|
|
|
3244
3237
|
# Generate branch name if not provided
|
|
3245
3238
|
branch_name = request.branched_workflow_name
|
|
@@ -3253,12 +3246,9 @@ class WorkflowManager:
|
|
|
3253
3246
|
|
|
3254
3247
|
# Check if branch name already exists
|
|
3255
3248
|
if WorkflowRegistry.has_workflow_with_name(branch_name):
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
branch_name,
|
|
3260
|
-
)
|
|
3261
|
-
return BranchWorkflowResultFailure()
|
|
3249
|
+
details = f"Failed to branch workflow '{request.workflow_name}' because branch name '{branch_name}' already exists"
|
|
3250
|
+
logger.error(details)
|
|
3251
|
+
return BranchWorkflowResultFailure(result_details=details)
|
|
3262
3252
|
|
|
3263
3253
|
try:
|
|
3264
3254
|
# Create branch metadata by copying source metadata
|
|
@@ -3285,21 +3275,18 @@ class WorkflowManager:
|
|
|
3285
3275
|
# Read source workflow content and replace metadata header
|
|
3286
3276
|
source_file_path = WorkflowRegistry.get_complete_file_path(source_workflow.file_path)
|
|
3287
3277
|
if not Path(source_file_path).exists():
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
request.workflow_name,
|
|
3292
|
-
source_file_path,
|
|
3293
|
-
)
|
|
3294
|
-
return BranchWorkflowResultFailure()
|
|
3278
|
+
details = f"Failed to branch workflow '{request.workflow_name}': File path '{source_file_path}' does not exist. The workflow may have been moved or the workspace configuration may have changed."
|
|
3279
|
+
logger.error(details)
|
|
3280
|
+
return BranchWorkflowResultFailure(result_details=details)
|
|
3295
3281
|
|
|
3296
3282
|
source_content = Path(source_file_path).read_text(encoding="utf-8")
|
|
3297
3283
|
|
|
3298
3284
|
# Replace the metadata header with branch metadata
|
|
3299
3285
|
branch_content = self._replace_workflow_metadata_header(source_content, branch_metadata)
|
|
3300
3286
|
if branch_content is None:
|
|
3301
|
-
|
|
3302
|
-
|
|
3287
|
+
details = f"Failed to replace metadata header for branch workflow '{branch_name}'"
|
|
3288
|
+
logger.error(details)
|
|
3289
|
+
return BranchWorkflowResultFailure(result_details=details)
|
|
3303
3290
|
|
|
3304
3291
|
# Write branch workflow file to disk BEFORE registering in registry
|
|
3305
3292
|
branch_full_path = WorkflowRegistry.get_complete_file_path(branch_file_path)
|
|
@@ -3318,11 +3305,12 @@ class WorkflowManager:
|
|
|
3318
3305
|
)
|
|
3319
3306
|
|
|
3320
3307
|
except Exception as e:
|
|
3321
|
-
|
|
3308
|
+
details = f"Failed to branch workflow '{request.workflow_name}': {e!s}"
|
|
3309
|
+
logger.error(details)
|
|
3322
3310
|
import traceback
|
|
3323
3311
|
|
|
3324
3312
|
traceback.print_exc()
|
|
3325
|
-
return BranchWorkflowResultFailure()
|
|
3313
|
+
return BranchWorkflowResultFailure(result_details=details)
|
|
3326
3314
|
|
|
3327
3315
|
def on_merge_workflow_branch_request(self, request: MergeWorkflowBranchRequest) -> ResultPayload:
|
|
3328
3316
|
"""Merge a branch back into its source workflow, removing the branch when complete."""
|
|
@@ -3330,28 +3318,24 @@ class WorkflowManager:
|
|
|
3330
3318
|
# Validate branch workflow exists
|
|
3331
3319
|
branch_workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
3332
3320
|
except KeyError as e:
|
|
3333
|
-
|
|
3334
|
-
|
|
3321
|
+
details = f"Failed to merge workflow branch because it does not exist: {e!s}"
|
|
3322
|
+
logger.error(details)
|
|
3323
|
+
return MergeWorkflowBranchResultFailure(result_details=details)
|
|
3335
3324
|
|
|
3336
3325
|
# Get source workflow name from branch metadata
|
|
3337
3326
|
source_workflow_name = branch_workflow.metadata.branched_from
|
|
3338
3327
|
if not source_workflow_name:
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
)
|
|
3343
|
-
return MergeWorkflowBranchResultFailure()
|
|
3328
|
+
details = f"Failed to merge workflow branch '{request.workflow_name}' because it has no source workflow"
|
|
3329
|
+
logger.error(details)
|
|
3330
|
+
return MergeWorkflowBranchResultFailure(result_details=details)
|
|
3344
3331
|
|
|
3345
3332
|
# Validate source workflow exists
|
|
3346
3333
|
try:
|
|
3347
3334
|
source_workflow = WorkflowRegistry.get_workflow_by_name(source_workflow_name)
|
|
3348
3335
|
except KeyError:
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
source_workflow_name,
|
|
3353
|
-
)
|
|
3354
|
-
return MergeWorkflowBranchResultFailure()
|
|
3336
|
+
details = f"Failed to merge workflow branch '{request.workflow_name}' because source workflow '{source_workflow_name}' does not exist"
|
|
3337
|
+
logger.error(details)
|
|
3338
|
+
return MergeWorkflowBranchResultFailure(result_details=details)
|
|
3355
3339
|
|
|
3356
3340
|
try:
|
|
3357
3341
|
# Create updated metadata for source workflow - update timestamp
|
|
@@ -3379,8 +3363,9 @@ class WorkflowManager:
|
|
|
3379
3363
|
# Replace the metadata header with merged metadata
|
|
3380
3364
|
merged_content = self._replace_workflow_metadata_header(branch_content, merged_metadata)
|
|
3381
3365
|
if merged_content is None:
|
|
3382
|
-
|
|
3383
|
-
|
|
3366
|
+
details = f"Failed to replace metadata header for merged workflow '{source_workflow_name}'"
|
|
3367
|
+
logger.error(details)
|
|
3368
|
+
return MergeWorkflowBranchResultFailure(result_details=details)
|
|
3384
3369
|
|
|
3385
3370
|
# Write the updated content to the source workflow file
|
|
3386
3371
|
source_file_path = WorkflowRegistry.get_complete_file_path(source_workflow.file_path)
|
|
@@ -3410,13 +3395,9 @@ class WorkflowManager:
|
|
|
3410
3395
|
return MergeWorkflowBranchResultSuccess(merged_workflow_name=source_workflow_name)
|
|
3411
3396
|
|
|
3412
3397
|
except Exception as e:
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
source_workflow_name,
|
|
3417
|
-
str(e),
|
|
3418
|
-
)
|
|
3419
|
-
return MergeWorkflowBranchResultFailure()
|
|
3398
|
+
details = f"Failed to merge branch workflow '{request.workflow_name}' into source workflow '{source_workflow_name}': {e!s}"
|
|
3399
|
+
logger.error(details)
|
|
3400
|
+
return MergeWorkflowBranchResultFailure(result_details=details)
|
|
3420
3401
|
|
|
3421
3402
|
def on_reset_workflow_branch_request(self, request: ResetWorkflowBranchRequest) -> ResultPayload:
|
|
3422
3403
|
"""Reset a branch to match its source workflow, discarding branch changes."""
|
|
@@ -3424,28 +3405,24 @@ class WorkflowManager:
|
|
|
3424
3405
|
# Validate branch workflow exists
|
|
3425
3406
|
branch_workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
3426
3407
|
except KeyError as e:
|
|
3427
|
-
|
|
3428
|
-
|
|
3408
|
+
details = f"Failed to reset workflow branch because it does not exist: {e!s}"
|
|
3409
|
+
logger.error(details)
|
|
3410
|
+
return ResetWorkflowBranchResultFailure(result_details=details)
|
|
3429
3411
|
|
|
3430
3412
|
# Get source workflow name from branch metadata
|
|
3431
3413
|
source_workflow_name = branch_workflow.metadata.branched_from
|
|
3432
3414
|
if not source_workflow_name:
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
)
|
|
3437
|
-
return ResetWorkflowBranchResultFailure()
|
|
3415
|
+
details = f"Failed to reset workflow branch '{request.workflow_name}' because it has no source workflow"
|
|
3416
|
+
logger.error(details)
|
|
3417
|
+
return ResetWorkflowBranchResultFailure(result_details=details)
|
|
3438
3418
|
|
|
3439
3419
|
# Validate source workflow exists
|
|
3440
3420
|
try:
|
|
3441
3421
|
source_workflow = WorkflowRegistry.get_workflow_by_name(source_workflow_name)
|
|
3442
3422
|
except KeyError:
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
source_workflow_name,
|
|
3447
|
-
)
|
|
3448
|
-
return ResetWorkflowBranchResultFailure()
|
|
3423
|
+
details = f"Failed to reset workflow branch '{request.workflow_name}' because source workflow '{source_workflow_name}' does not exist"
|
|
3424
|
+
logger.error(details)
|
|
3425
|
+
return ResetWorkflowBranchResultFailure(result_details=details)
|
|
3449
3426
|
|
|
3450
3427
|
try:
|
|
3451
3428
|
# Read content from the source workflow (what we're resetting the branch to)
|
|
@@ -3473,8 +3450,9 @@ class WorkflowManager:
|
|
|
3473
3450
|
# Replace the metadata header with reset metadata
|
|
3474
3451
|
reset_content = self._replace_workflow_metadata_header(source_content, reset_metadata)
|
|
3475
3452
|
if reset_content is None:
|
|
3476
|
-
|
|
3477
|
-
|
|
3453
|
+
details = f"Failed to replace metadata header for reset branch workflow '{request.workflow_name}'"
|
|
3454
|
+
logger.error(details)
|
|
3455
|
+
return ResetWorkflowBranchResultFailure(result_details=details)
|
|
3478
3456
|
|
|
3479
3457
|
# Write the updated content to the branch workflow file
|
|
3480
3458
|
branch_content_file_path = WorkflowRegistry.get_complete_file_path(branch_workflow.file_path)
|
|
@@ -3484,13 +3462,9 @@ class WorkflowManager:
|
|
|
3484
3462
|
branch_workflow.metadata = reset_metadata
|
|
3485
3463
|
|
|
3486
3464
|
except Exception as e:
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
source_workflow_name,
|
|
3491
|
-
str(e),
|
|
3492
|
-
)
|
|
3493
|
-
return ResetWorkflowBranchResultFailure()
|
|
3465
|
+
details = f"Failed to reset branch workflow '{request.workflow_name}' to source workflow '{source_workflow_name}': {e!s}"
|
|
3466
|
+
logger.error(details)
|
|
3467
|
+
return ResetWorkflowBranchResultFailure(result_details=details)
|
|
3494
3468
|
else:
|
|
3495
3469
|
logger.info(
|
|
3496
3470
|
"Successfully reset branch workflow '%s' to match source workflow '%s'",
|
|
@@ -3505,8 +3479,9 @@ class WorkflowManager:
|
|
|
3505
3479
|
# Get the workflow to evaluate
|
|
3506
3480
|
workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
3507
3481
|
except KeyError:
|
|
3508
|
-
|
|
3509
|
-
|
|
3482
|
+
details = f"Failed to compare workflow '{request.workflow_name}' because it does not exist"
|
|
3483
|
+
logger.error(details)
|
|
3484
|
+
return CompareWorkflowsResultFailure(result_details=details)
|
|
3510
3485
|
|
|
3511
3486
|
# Use the provided compare_workflow_name
|
|
3512
3487
|
compare_workflow_name = request.compare_workflow_name
|
|
@@ -3731,10 +3706,9 @@ class WorkflowManager:
|
|
|
3731
3706
|
succeeded, failed = self._process_workflows_for_registration(workflows_to_register)
|
|
3732
3707
|
|
|
3733
3708
|
except Exception as e:
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
)
|
|
3737
|
-
return RegisterWorkflowsFromConfigResultFailure()
|
|
3709
|
+
details = f"Failed to register workflows from configuration section '{request.config_section}': {e!s}"
|
|
3710
|
+
logger.error(details)
|
|
3711
|
+
return RegisterWorkflowsFromConfigResultFailure(result_details=details)
|
|
3738
3712
|
else:
|
|
3739
3713
|
return RegisterWorkflowsFromConfigResultSuccess(succeeded_workflows=succeeded, failed_workflows=failed)
|
|
3740
3714
|
|