griptape-nodes 0.52.1__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.
- griptape_nodes/__init__.py +6 -943
- griptape_nodes/__main__.py +6 -0
- griptape_nodes/app/app.py +45 -61
- griptape_nodes/cli/__init__.py +1 -0
- griptape_nodes/cli/commands/__init__.py +1 -0
- griptape_nodes/cli/commands/config.py +71 -0
- griptape_nodes/cli/commands/engine.py +80 -0
- griptape_nodes/cli/commands/init.py +548 -0
- griptape_nodes/cli/commands/libraries.py +90 -0
- griptape_nodes/cli/commands/self.py +117 -0
- griptape_nodes/cli/main.py +46 -0
- griptape_nodes/cli/shared.py +84 -0
- griptape_nodes/common/__init__.py +1 -0
- griptape_nodes/common/directed_graph.py +55 -0
- griptape_nodes/drivers/storage/local_storage_driver.py +7 -2
- griptape_nodes/exe_types/core_types.py +60 -2
- griptape_nodes/exe_types/node_types.py +38 -24
- griptape_nodes/machines/control_flow.py +86 -22
- griptape_nodes/machines/fsm.py +10 -1
- griptape_nodes/machines/parallel_resolution.py +570 -0
- griptape_nodes/machines/{node_resolution.py → sequential_resolution.py} +22 -51
- griptape_nodes/retained_mode/events/base_events.py +2 -2
- griptape_nodes/retained_mode/events/node_events.py +4 -3
- griptape_nodes/retained_mode/griptape_nodes.py +25 -12
- griptape_nodes/retained_mode/managers/agent_manager.py +9 -5
- griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py +3 -1
- griptape_nodes/retained_mode/managers/context_manager.py +6 -5
- griptape_nodes/retained_mode/managers/flow_manager.py +117 -204
- griptape_nodes/retained_mode/managers/library_lifecycle/library_directory.py +1 -1
- griptape_nodes/retained_mode/managers/library_manager.py +35 -25
- griptape_nodes/retained_mode/managers/node_manager.py +81 -199
- griptape_nodes/retained_mode/managers/object_manager.py +11 -5
- griptape_nodes/retained_mode/managers/os_manager.py +24 -9
- griptape_nodes/retained_mode/managers/secrets_manager.py +8 -4
- griptape_nodes/retained_mode/managers/settings.py +32 -1
- griptape_nodes/retained_mode/managers/static_files_manager.py +8 -3
- griptape_nodes/retained_mode/managers/sync_manager.py +8 -5
- griptape_nodes/retained_mode/managers/workflow_manager.py +110 -122
- griptape_nodes/traits/add_param_button.py +1 -1
- griptape_nodes/traits/button.py +216 -6
- griptape_nodes/traits/color_picker.py +66 -0
- griptape_nodes/traits/traits.json +4 -0
- {griptape_nodes-0.52.1.dist-info → griptape_nodes-0.53.0.dist-info}/METADATA +2 -1
- {griptape_nodes-0.52.1.dist-info → griptape_nodes-0.53.0.dist-info}/RECORD +46 -32
- {griptape_nodes-0.52.1.dist-info → griptape_nodes-0.53.0.dist-info}/WHEEL +0 -0
- {griptape_nodes-0.52.1.dist-info → griptape_nodes-0.53.0.dist-info}/entry_points.txt +0 -0
|
@@ -29,6 +29,9 @@ from griptape_nodes.retained_mode.events.app_events import (
|
|
|
29
29
|
GetEngineVersionRequest,
|
|
30
30
|
GetEngineVersionResultSuccess,
|
|
31
31
|
)
|
|
32
|
+
|
|
33
|
+
# Runtime imports for ResultDetails since it's used at runtime
|
|
34
|
+
from griptape_nodes.retained_mode.events.base_events import ResultDetail, ResultDetails
|
|
32
35
|
from griptape_nodes.retained_mode.events.flow_events import (
|
|
33
36
|
CreateFlowRequest,
|
|
34
37
|
GetTopLevelFlowRequest,
|
|
@@ -535,7 +538,6 @@ class WorkflowManager:
|
|
|
535
538
|
complete_file_path = WorkflowRegistry.get_complete_file_path(relative_file_path=relative_file_path)
|
|
536
539
|
if not Path(complete_file_path).is_file():
|
|
537
540
|
details = f"Failed to find file. Path '{complete_file_path}' doesn't exist."
|
|
538
|
-
logger.error(details)
|
|
539
541
|
return RunWorkflowFromScratchResultFailure(result_details=details)
|
|
540
542
|
|
|
541
543
|
# Start with a clean slate.
|
|
@@ -543,14 +545,12 @@ class WorkflowManager:
|
|
|
543
545
|
clear_all_result = GriptapeNodes.handle_request(clear_all_request)
|
|
544
546
|
if not clear_all_result.succeeded():
|
|
545
547
|
details = f"Failed to clear the existing object state when trying to run '{complete_file_path}'."
|
|
546
|
-
logger.error(details)
|
|
547
548
|
return RunWorkflowFromScratchResultFailure(result_details=details)
|
|
548
549
|
|
|
549
550
|
# Run the file, goddamn it
|
|
550
551
|
execution_result = self.run_workflow(relative_file_path=relative_file_path)
|
|
551
552
|
if execution_result.execution_successful:
|
|
552
|
-
|
|
553
|
-
return RunWorkflowFromScratchResultSuccess()
|
|
553
|
+
return RunWorkflowFromScratchResultSuccess(result_details=execution_result.execution_details)
|
|
554
554
|
|
|
555
555
|
logger.error(execution_result.execution_details)
|
|
556
556
|
return RunWorkflowFromScratchResultFailure(result_details=execution_result.execution_details)
|
|
@@ -560,13 +560,11 @@ class WorkflowManager:
|
|
|
560
560
|
complete_file_path = WorkflowRegistry.get_complete_file_path(relative_file_path=relative_file_path)
|
|
561
561
|
if not Path(complete_file_path).is_file():
|
|
562
562
|
details = f"Failed to find file. Path '{complete_file_path}' doesn't exist."
|
|
563
|
-
logger.error(details)
|
|
564
563
|
return RunWorkflowWithCurrentStateResultFailure(result_details=details)
|
|
565
564
|
execution_result = self.run_workflow(relative_file_path=relative_file_path)
|
|
566
565
|
|
|
567
566
|
if execution_result.execution_successful:
|
|
568
|
-
|
|
569
|
-
return RunWorkflowWithCurrentStateResultSuccess()
|
|
567
|
+
return RunWorkflowWithCurrentStateResultSuccess(result_details=execution_result.execution_details)
|
|
570
568
|
logger.error(execution_result.execution_details)
|
|
571
569
|
return RunWorkflowWithCurrentStateResultFailure(result_details=execution_result.execution_details)
|
|
572
570
|
|
|
@@ -576,13 +574,12 @@ class WorkflowManager:
|
|
|
576
574
|
workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
577
575
|
except KeyError:
|
|
578
576
|
details = f"Failed to get workflow '{request.workflow_name}' from registry."
|
|
579
|
-
logger.error(details)
|
|
580
577
|
return RunWorkflowFromRegistryResultFailure(result_details=details)
|
|
581
578
|
|
|
582
579
|
# Update current context for workflow.
|
|
580
|
+
context_warning = None
|
|
583
581
|
if GriptapeNodes.ContextManager().has_current_workflow():
|
|
584
|
-
|
|
585
|
-
logger.warning(details)
|
|
582
|
+
context_warning = f"Started a new workflow '{request.workflow_name}' but a workflow '{GriptapeNodes.ContextManager().get_current_workflow_name()}' was already in the Current Context. Replacing the old with the new."
|
|
586
583
|
|
|
587
584
|
# get file_path from workflow
|
|
588
585
|
relative_file_path = workflow.file_path
|
|
@@ -595,7 +592,6 @@ class WorkflowManager:
|
|
|
595
592
|
clear_all_result = GriptapeNodes.handle_request(clear_all_request)
|
|
596
593
|
if not clear_all_result.succeeded():
|
|
597
594
|
details = f"Failed to clear the existing object state when preparing to run workflow '{request.workflow_name}'."
|
|
598
|
-
logger.error(details)
|
|
599
595
|
return RunWorkflowFromRegistryResultFailure(result_details=details)
|
|
600
596
|
|
|
601
597
|
# Let's run under the assumption that this Workflow will become our Current Context; if we fail, it will revert.
|
|
@@ -604,18 +600,24 @@ class WorkflowManager:
|
|
|
604
600
|
execution_result = self.run_workflow(relative_file_path=relative_file_path)
|
|
605
601
|
|
|
606
602
|
if not execution_result.execution_successful:
|
|
607
|
-
|
|
603
|
+
result_messages = []
|
|
604
|
+
if context_warning:
|
|
605
|
+
result_messages.append(ResultDetail(message=context_warning, level="WARNING"))
|
|
606
|
+
result_messages.append(ResultDetail(message=execution_result.execution_details, level="ERROR"))
|
|
608
607
|
|
|
609
608
|
# Attempt to clear everything out, as we modified the engine state getting here.
|
|
610
609
|
clear_all_request = ClearAllObjectStateRequest(i_know_what_im_doing=True)
|
|
611
610
|
clear_all_result = GriptapeNodes.handle_request(clear_all_request)
|
|
612
611
|
|
|
613
612
|
# The clear-all above here wipes the ContextManager, so no need to do a pop_workflow().
|
|
614
|
-
return RunWorkflowFromRegistryResultFailure(result_details=
|
|
613
|
+
return RunWorkflowFromRegistryResultFailure(result_details=ResultDetails(*result_messages))
|
|
615
614
|
|
|
616
615
|
# Success!
|
|
617
|
-
|
|
618
|
-
|
|
616
|
+
result_messages = []
|
|
617
|
+
if context_warning:
|
|
618
|
+
result_messages.append(ResultDetail(message=context_warning, level="WARNING"))
|
|
619
|
+
result_messages.append(ResultDetail(message=execution_result.execution_details, level="DEBUG"))
|
|
620
|
+
return RunWorkflowFromRegistryResultSuccess(result_details=ResultDetails(*result_messages))
|
|
619
621
|
|
|
620
622
|
def on_register_workflow_request(self, request: RegisterWorkflowRequest) -> ResultPayload:
|
|
621
623
|
try:
|
|
@@ -625,9 +627,13 @@ class WorkflowManager:
|
|
|
625
627
|
workflow = WorkflowRegistry.generate_new_workflow(metadata=request.metadata, file_path=request.file_name)
|
|
626
628
|
except Exception as e:
|
|
627
629
|
details = f"Failed to register workflow with name '{request.metadata.name}'. Error: {e}"
|
|
628
|
-
logger.error(details)
|
|
629
630
|
return RegisterWorkflowResultFailure(result_details=details)
|
|
630
|
-
return RegisterWorkflowResultSuccess(
|
|
631
|
+
return RegisterWorkflowResultSuccess(
|
|
632
|
+
workflow_name=workflow.metadata.name,
|
|
633
|
+
result_details=ResultDetails(
|
|
634
|
+
message=f"Successfully registered workflow: {workflow.metadata.name}", level="INFO"
|
|
635
|
+
),
|
|
636
|
+
)
|
|
631
637
|
|
|
632
638
|
def on_import_workflow_request(self, request: ImportWorkflowRequest) -> ResultPayload:
|
|
633
639
|
# First, attempt to load metadata from the file
|
|
@@ -641,7 +647,10 @@ class WorkflowManager:
|
|
|
641
647
|
workflow_name = load_metadata_result.metadata.name
|
|
642
648
|
if WorkflowRegistry.has_workflow_with_name(workflow_name):
|
|
643
649
|
# Workflow already exists - no need to re-register
|
|
644
|
-
return ImportWorkflowResultSuccess(
|
|
650
|
+
return ImportWorkflowResultSuccess(
|
|
651
|
+
workflow_name=workflow_name,
|
|
652
|
+
result_details=f"Workflow '{workflow_name}' already exists - no need to re-import.",
|
|
653
|
+
)
|
|
645
654
|
|
|
646
655
|
# Now register the workflow with the extracted metadata
|
|
647
656
|
register_request = RegisterWorkflowRequest(metadata=load_metadata_result.metadata, file_name=request.file_path)
|
|
@@ -659,30 +668,34 @@ class WorkflowManager:
|
|
|
659
668
|
|
|
660
669
|
return ImportWorkflowResultFailure(result_details=details)
|
|
661
670
|
|
|
662
|
-
return ImportWorkflowResultSuccess(
|
|
671
|
+
return ImportWorkflowResultSuccess(
|
|
672
|
+
workflow_name=register_result.workflow_name,
|
|
673
|
+
result_details=ResultDetails(
|
|
674
|
+
message=f"Successfully imported workflow: {register_result.workflow_name}", level="INFO"
|
|
675
|
+
),
|
|
676
|
+
)
|
|
663
677
|
|
|
664
678
|
def on_list_all_workflows_request(self, _request: ListAllWorkflowsRequest) -> ResultPayload:
|
|
665
679
|
try:
|
|
666
680
|
workflows = WorkflowRegistry.list_workflows()
|
|
667
681
|
except Exception:
|
|
668
682
|
details = "Failed to list all workflows."
|
|
669
|
-
logger.error(details)
|
|
670
683
|
return ListAllWorkflowsResultFailure(result_details=details)
|
|
671
|
-
return ListAllWorkflowsResultSuccess(
|
|
684
|
+
return ListAllWorkflowsResultSuccess(
|
|
685
|
+
workflows=workflows, result_details=f"Successfully retrieved {len(workflows)} workflows."
|
|
686
|
+
)
|
|
672
687
|
|
|
673
688
|
def on_delete_workflows_request(self, request: DeleteWorkflowRequest) -> ResultPayload:
|
|
674
689
|
try:
|
|
675
690
|
workflow = WorkflowRegistry.delete_workflow_by_name(request.name)
|
|
676
691
|
except Exception as e:
|
|
677
692
|
details = f"Failed to remove workflow from registry with name '{request.name}'. Exception: {e}"
|
|
678
|
-
logger.error(details)
|
|
679
693
|
return DeleteWorkflowResultFailure(result_details=details)
|
|
680
694
|
config_manager = GriptapeNodes.ConfigManager()
|
|
681
695
|
try:
|
|
682
696
|
config_manager.delete_user_workflow(workflow.file_path)
|
|
683
697
|
except Exception as e:
|
|
684
698
|
details = f"Failed to remove workflow from user config with name '{request.name}'. Exception: {e}"
|
|
685
|
-
logger.error(details)
|
|
686
699
|
return DeleteWorkflowResultFailure(result_details=details)
|
|
687
700
|
# delete the actual file
|
|
688
701
|
full_path = config_manager.workspace_path.joinpath(workflow.file_path)
|
|
@@ -690,25 +703,28 @@ class WorkflowManager:
|
|
|
690
703
|
full_path.unlink()
|
|
691
704
|
except Exception as e:
|
|
692
705
|
details = f"Failed to delete workflow file with path '{workflow.file_path}'. Exception: {e}"
|
|
693
|
-
logger.error(details)
|
|
694
706
|
return DeleteWorkflowResultFailure(result_details=details)
|
|
695
|
-
return DeleteWorkflowResultSuccess(
|
|
707
|
+
return DeleteWorkflowResultSuccess(
|
|
708
|
+
result_details=ResultDetails(message=f"Successfully deleted workflow: {request.name}", level="INFO")
|
|
709
|
+
)
|
|
696
710
|
|
|
697
711
|
def on_rename_workflow_request(self, request: RenameWorkflowRequest) -> ResultPayload:
|
|
698
712
|
save_workflow_request = GriptapeNodes.handle_request(SaveWorkflowRequest(file_name=request.requested_name))
|
|
699
713
|
|
|
700
714
|
if isinstance(save_workflow_request, SaveWorkflowResultFailure):
|
|
701
715
|
details = f"Attempted to rename workflow '{request.workflow_name}' to '{request.requested_name}'. Failed while attempting to save."
|
|
702
|
-
logger.error(details)
|
|
703
716
|
return RenameWorkflowResultFailure(result_details=details)
|
|
704
717
|
|
|
705
718
|
delete_workflow_result = GriptapeNodes.handle_request(DeleteWorkflowRequest(name=request.workflow_name))
|
|
706
719
|
if isinstance(delete_workflow_result, DeleteWorkflowResultFailure):
|
|
707
720
|
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."
|
|
708
|
-
logger.error(details)
|
|
709
721
|
return RenameWorkflowResultFailure(result_details=details)
|
|
710
722
|
|
|
711
|
-
return RenameWorkflowResultSuccess(
|
|
723
|
+
return RenameWorkflowResultSuccess(
|
|
724
|
+
result_details=ResultDetails(
|
|
725
|
+
message=f"Successfully renamed workflow to: {request.requested_name}", level="INFO"
|
|
726
|
+
)
|
|
727
|
+
)
|
|
712
728
|
|
|
713
729
|
def on_move_workflow_request(self, request: MoveWorkflowRequest) -> ResultPayload: # noqa: PLR0911
|
|
714
730
|
try:
|
|
@@ -716,7 +732,6 @@ class WorkflowManager:
|
|
|
716
732
|
workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
717
733
|
except KeyError:
|
|
718
734
|
details = f"Failed to move workflow '{request.workflow_name}' because it does not exist."
|
|
719
|
-
logger.error(details)
|
|
720
735
|
return MoveWorkflowResultFailure(result_details=details)
|
|
721
736
|
|
|
722
737
|
config_manager = GriptapeNodes.ConfigManager()
|
|
@@ -727,7 +742,6 @@ class WorkflowManager:
|
|
|
727
742
|
details = (
|
|
728
743
|
f"Failed to move workflow '{request.workflow_name}': File path '{current_file_path}' does not exist."
|
|
729
744
|
)
|
|
730
|
-
logger.error(details)
|
|
731
745
|
return MoveWorkflowResultFailure(result_details=details)
|
|
732
746
|
|
|
733
747
|
# Clean and validate target directory
|
|
@@ -742,7 +756,6 @@ class WorkflowManager:
|
|
|
742
756
|
target_dir_path.mkdir(parents=True, exist_ok=True)
|
|
743
757
|
except OSError as e:
|
|
744
758
|
details = f"Failed to create target directory '{target_dir_path}': {e!s}"
|
|
745
|
-
logger.error(details)
|
|
746
759
|
return MoveWorkflowResultFailure(result_details=details)
|
|
747
760
|
|
|
748
761
|
# Create new file path
|
|
@@ -755,7 +768,6 @@ class WorkflowManager:
|
|
|
755
768
|
details = (
|
|
756
769
|
f"Failed to move workflow '{request.workflow_name}': Target file '{new_absolute_path}' already exists."
|
|
757
770
|
)
|
|
758
|
-
logger.error(details)
|
|
759
771
|
return MoveWorkflowResultFailure(result_details=details)
|
|
760
772
|
|
|
761
773
|
try:
|
|
@@ -770,28 +782,29 @@ class WorkflowManager:
|
|
|
770
782
|
config_manager.save_user_workflow_json(str(new_absolute_path))
|
|
771
783
|
|
|
772
784
|
except OSError as e:
|
|
773
|
-
|
|
774
|
-
|
|
785
|
+
error_messages = []
|
|
786
|
+
main_error = f"Failed to move workflow file '{current_file_path}' to '{new_absolute_path}': {e!s}"
|
|
787
|
+
error_messages.append(ResultDetail(message=main_error, level="ERROR"))
|
|
775
788
|
|
|
776
789
|
# Attempt to rollback if file was moved but registry update failed
|
|
777
790
|
if new_absolute_path.exists() and not Path(current_file_path).exists():
|
|
778
791
|
try:
|
|
779
792
|
new_absolute_path.rename(current_file_path)
|
|
780
|
-
|
|
781
|
-
|
|
793
|
+
rollback_message = f"Rolled back file move for workflow '{request.workflow_name}'"
|
|
794
|
+
error_messages.append(ResultDetail(message=rollback_message, level="INFO"))
|
|
782
795
|
except OSError:
|
|
783
|
-
|
|
784
|
-
|
|
796
|
+
rollback_failure = f"Failed to rollback file move for workflow '{request.workflow_name}'"
|
|
797
|
+
error_messages.append(ResultDetail(message=rollback_failure, level="ERROR"))
|
|
785
798
|
|
|
786
|
-
return MoveWorkflowResultFailure(result_details=
|
|
799
|
+
return MoveWorkflowResultFailure(result_details=ResultDetails(*error_messages))
|
|
787
800
|
except Exception as e:
|
|
788
801
|
details = f"Failed to move workflow '{request.workflow_name}': {e!s}"
|
|
789
|
-
logger.error(details)
|
|
790
802
|
return MoveWorkflowResultFailure(result_details=details)
|
|
791
803
|
else:
|
|
792
804
|
details = f"Successfully moved workflow '{request.workflow_name}' to '{new_relative_path}'"
|
|
793
|
-
|
|
794
|
-
|
|
805
|
+
return MoveWorkflowResultSuccess(
|
|
806
|
+
moved_file_path=new_relative_path, result_details=ResultDetails(message=details, level="INFO")
|
|
807
|
+
)
|
|
795
808
|
|
|
796
809
|
def on_load_workflow_metadata_request( # noqa: C901, PLR0912, PLR0915
|
|
797
810
|
self, request: LoadWorkflowMetadata
|
|
@@ -810,7 +823,6 @@ class WorkflowManager:
|
|
|
810
823
|
],
|
|
811
824
|
)
|
|
812
825
|
details = f"Attempted to load workflow metadata for a file at '{complete_file_path}. Failed because no file could be found at that path."
|
|
813
|
-
logger.error(details)
|
|
814
826
|
return LoadWorkflowMetadataResultFailure(result_details=details)
|
|
815
827
|
|
|
816
828
|
# Find the metadata block.
|
|
@@ -827,7 +839,6 @@ class WorkflowManager:
|
|
|
827
839
|
],
|
|
828
840
|
)
|
|
829
841
|
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."
|
|
830
|
-
logger.error(details)
|
|
831
842
|
return LoadWorkflowMetadataResultFailure(result_details=details)
|
|
832
843
|
|
|
833
844
|
# Now attempt to parse out the metadata section, stripped of comment prefixes.
|
|
@@ -847,7 +858,6 @@ class WorkflowManager:
|
|
|
847
858
|
problems=[f"Failed because the metadata was not valid TOML: {err}"],
|
|
848
859
|
)
|
|
849
860
|
details = f"Attempted to load workflow metadata for a file at '{complete_file_path}'. Failed because the metadata was not valid TOML: {err}"
|
|
850
|
-
logger.error(details)
|
|
851
861
|
return LoadWorkflowMetadataResultFailure(result_details=details)
|
|
852
862
|
|
|
853
863
|
tool_header = "tool"
|
|
@@ -863,7 +873,6 @@ class WorkflowManager:
|
|
|
863
873
|
problems=[f"Failed because the '[{tool_header}.{griptape_nodes_header}]' section could not be found."],
|
|
864
874
|
)
|
|
865
875
|
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}"
|
|
866
|
-
logger.error(details)
|
|
867
876
|
return LoadWorkflowMetadataResultFailure(result_details=details)
|
|
868
877
|
|
|
869
878
|
try:
|
|
@@ -881,7 +890,6 @@ class WorkflowManager:
|
|
|
881
890
|
],
|
|
882
891
|
)
|
|
883
892
|
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}"
|
|
884
|
-
logger.error(details)
|
|
885
893
|
return LoadWorkflowMetadataResultFailure(result_details=details)
|
|
886
894
|
|
|
887
895
|
# We have valid dependencies, etc.
|
|
@@ -1037,7 +1045,9 @@ class WorkflowManager:
|
|
|
1037
1045
|
workflow_dependencies=dependency_infos,
|
|
1038
1046
|
problems=problems,
|
|
1039
1047
|
)
|
|
1040
|
-
return LoadWorkflowMetadataResultSuccess(
|
|
1048
|
+
return LoadWorkflowMetadataResultSuccess(
|
|
1049
|
+
metadata=workflow_metadata, result_details="Workflow metadata loaded successfully."
|
|
1050
|
+
)
|
|
1041
1051
|
|
|
1042
1052
|
def register_workflows_from_config(self, config_section: str) -> None:
|
|
1043
1053
|
workflows_to_register = GriptapeNodes.ConfigManager().get_config_value(config_section)
|
|
@@ -1159,7 +1169,6 @@ class WorkflowManager:
|
|
|
1159
1169
|
engine_version_result = GriptapeNodes.handle_request(request=engine_version_request)
|
|
1160
1170
|
if not isinstance(engine_version_result, GetEngineVersionResultSuccess):
|
|
1161
1171
|
details = f"Failed getting the engine version for workflow '{file_name}'."
|
|
1162
|
-
logger.error(details)
|
|
1163
1172
|
raise TypeError(details)
|
|
1164
1173
|
try:
|
|
1165
1174
|
engine_version_success = cast("GetEngineVersionResultSuccess", engine_version_result)
|
|
@@ -1168,7 +1177,6 @@ class WorkflowManager:
|
|
|
1168
1177
|
)
|
|
1169
1178
|
except Exception as err:
|
|
1170
1179
|
details = f"Failed getting the engine version for workflow '{file_name}': {err}"
|
|
1171
|
-
logger.error(details)
|
|
1172
1180
|
raise ValueError(details) from err
|
|
1173
1181
|
|
|
1174
1182
|
# Keep track of all of the nodes we create and the generated variable names for them.
|
|
@@ -1182,7 +1190,6 @@ class WorkflowManager:
|
|
|
1182
1190
|
top_level_flow_result = GriptapeNodes.handle_request(top_level_flow_request)
|
|
1183
1191
|
if not isinstance(top_level_flow_result, GetTopLevelFlowResultSuccess):
|
|
1184
1192
|
details = f"Failed when requesting to get top level flow for workflow '{file_name}'."
|
|
1185
|
-
logger.error(details)
|
|
1186
1193
|
raise TypeError(details)
|
|
1187
1194
|
top_level_flow_name = top_level_flow_result.flow_name
|
|
1188
1195
|
serialized_flow_request = SerializeFlowToCommandsRequest(
|
|
@@ -1191,7 +1198,6 @@ class WorkflowManager:
|
|
|
1191
1198
|
serialized_flow_result = GriptapeNodes.handle_request(serialized_flow_request)
|
|
1192
1199
|
if not isinstance(serialized_flow_result, SerializeFlowToCommandsResultSuccess):
|
|
1193
1200
|
details = f"Failed when serializing flow for workflow '{file_name}'."
|
|
1194
|
-
logger.error(details)
|
|
1195
1201
|
raise TypeError(details)
|
|
1196
1202
|
serialized_flow_commands = serialized_flow_result.serialized_flow_commands
|
|
1197
1203
|
|
|
@@ -1214,7 +1220,6 @@ class WorkflowManager:
|
|
|
1214
1220
|
)
|
|
1215
1221
|
if workflow_metadata is None:
|
|
1216
1222
|
details = f"Failed to generate metadata for workflow '{file_name}'."
|
|
1217
|
-
logger.error(details)
|
|
1218
1223
|
raise ValueError(details)
|
|
1219
1224
|
|
|
1220
1225
|
# Set the image if provided
|
|
@@ -1224,7 +1229,6 @@ class WorkflowManager:
|
|
|
1224
1229
|
metadata_block = self._generate_workflow_metadata_header(workflow_metadata=workflow_metadata)
|
|
1225
1230
|
if metadata_block is None:
|
|
1226
1231
|
details = f"Failed to generate metadata block for workflow '{file_name}'."
|
|
1227
|
-
logger.error(details)
|
|
1228
1232
|
raise ValueError(details)
|
|
1229
1233
|
|
|
1230
1234
|
import_recorder = ImportRecorder()
|
|
@@ -1423,7 +1427,6 @@ class WorkflowManager:
|
|
|
1423
1427
|
)
|
|
1424
1428
|
except Exception as err:
|
|
1425
1429
|
details = f"Attempted to save workflow '{relative_file_path}', but {err}"
|
|
1426
|
-
logger.error(details)
|
|
1427
1430
|
return SaveWorkflowResultFailure(result_details=details)
|
|
1428
1431
|
|
|
1429
1432
|
# Create the pathing and write the file
|
|
@@ -1431,7 +1434,6 @@ class WorkflowManager:
|
|
|
1431
1434
|
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1432
1435
|
except OSError as e:
|
|
1433
1436
|
details = f"Attempted to save workflow '{file_name}'. Failed when creating directory: {e}"
|
|
1434
|
-
logger.error(details)
|
|
1435
1437
|
return SaveWorkflowResultFailure(result_details=details)
|
|
1436
1438
|
|
|
1437
1439
|
# Check disk space before writing
|
|
@@ -1440,7 +1442,6 @@ class WorkflowManager:
|
|
|
1440
1442
|
if not OSManager.check_available_disk_space(file_path.parent, min_space_gb):
|
|
1441
1443
|
error_msg = OSManager.format_disk_space_error(file_path.parent)
|
|
1442
1444
|
details = f"Attempted to save workflow '{file_name}' (requires {min_space_gb:.1f} GB). Failed: {error_msg}"
|
|
1443
|
-
logger.error(details)
|
|
1444
1445
|
return SaveWorkflowResultFailure(result_details=details)
|
|
1445
1446
|
|
|
1446
1447
|
try:
|
|
@@ -1448,7 +1449,6 @@ class WorkflowManager:
|
|
|
1448
1449
|
file.write(final_code_output)
|
|
1449
1450
|
except OSError as e:
|
|
1450
1451
|
details = f"Attempted to save workflow '{file_name}'. Failed when writing file: {e}"
|
|
1451
|
-
logger.error(details)
|
|
1452
1452
|
return SaveWorkflowResultFailure(result_details=details)
|
|
1453
1453
|
|
|
1454
1454
|
# save the created workflow as an entry in the JSON config file.
|
|
@@ -1460,15 +1460,15 @@ class WorkflowManager:
|
|
|
1460
1460
|
GriptapeNodes.ConfigManager().save_user_workflow_json(str(file_path))
|
|
1461
1461
|
except OSError as e:
|
|
1462
1462
|
details = f"Attempted to save workflow '{file_name}'. Failed when saving configuration: {e}"
|
|
1463
|
-
logger.error(details)
|
|
1464
1463
|
return SaveWorkflowResultFailure(result_details=details)
|
|
1465
1464
|
WorkflowRegistry.generate_new_workflow(metadata=workflow_metadata, file_path=relative_file_path)
|
|
1466
1465
|
# Update existing workflow's metadata in the registry
|
|
1467
1466
|
existing_workflow = WorkflowRegistry.get_workflow_by_name(file_name)
|
|
1468
1467
|
existing_workflow.metadata = workflow_metadata
|
|
1469
1468
|
details = f"Successfully saved workflow to: {file_path}"
|
|
1470
|
-
|
|
1471
|
-
|
|
1469
|
+
return SaveWorkflowResultSuccess(
|
|
1470
|
+
file_path=str(file_path), result_details=ResultDetails(message=details, level="INFO")
|
|
1471
|
+
)
|
|
1472
1472
|
|
|
1473
1473
|
def _generate_workflow_metadata( # noqa: PLR0913
|
|
1474
1474
|
self,
|
|
@@ -3122,12 +3122,10 @@ class WorkflowManager:
|
|
|
3122
3122
|
result = flow_manager.on_get_top_level_flow_request(GetTopLevelFlowRequest())
|
|
3123
3123
|
if result.failed():
|
|
3124
3124
|
details = f"Workflow '{workflow_name}' does not have a top-level flow."
|
|
3125
|
-
logger.error(details)
|
|
3126
3125
|
raise ValueError(details)
|
|
3127
3126
|
flow_name = cast("GetTopLevelFlowResultSuccess", result).flow_name
|
|
3128
3127
|
if flow_name is None:
|
|
3129
3128
|
details = f"Workflow '{workflow_name}' does not have a top-level flow."
|
|
3130
|
-
logger.error(details)
|
|
3131
3129
|
raise ValueError(details)
|
|
3132
3130
|
|
|
3133
3131
|
control_flow = flow_manager.get_flow_by_name(flow_name)
|
|
@@ -3195,22 +3193,21 @@ class WorkflowManager:
|
|
|
3195
3193
|
file_name=workflow_file.name,
|
|
3196
3194
|
)
|
|
3197
3195
|
)
|
|
3196
|
+
result_messages = []
|
|
3198
3197
|
if isinstance(register_workflow_result, RegisterWorkflowResultSuccess):
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
workflow_file.name,
|
|
3202
|
-
)
|
|
3198
|
+
success_message = f"Successfully registered new workflow with file '{workflow_file.name}'."
|
|
3199
|
+
result_messages.append(ResultDetail(message=success_message, level="INFO"))
|
|
3203
3200
|
else:
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
workflow_file.name,
|
|
3207
|
-
cast("RegisterWorkflowResultFailure", register_workflow_result).exception,
|
|
3208
|
-
)
|
|
3201
|
+
failure_message = f"Failed to register workflow with file '{workflow_file.name}': {cast('RegisterWorkflowResultFailure', register_workflow_result).exception}"
|
|
3202
|
+
result_messages.append(ResultDetail(message=failure_message, level="WARNING"))
|
|
3209
3203
|
else:
|
|
3210
|
-
|
|
3211
|
-
"Failed to load metadata for workflow file '
|
|
3212
|
-
workflow_file.name,
|
|
3204
|
+
metadata_failure_message = (
|
|
3205
|
+
f"Failed to load metadata for workflow file '{workflow_file.name}'. Not registering workflow."
|
|
3213
3206
|
)
|
|
3207
|
+
result_messages = [ResultDetail(message=metadata_failure_message, level="WARNING")]
|
|
3208
|
+
|
|
3209
|
+
# Log all messages through consolidated ResultDetails
|
|
3210
|
+
ResultDetails(*result_messages)
|
|
3214
3211
|
|
|
3215
3212
|
def on_import_workflow_as_referenced_sub_flow_request(
|
|
3216
3213
|
self, request: ImportWorkflowAsReferencedSubFlowRequest
|
|
@@ -3240,7 +3237,6 @@ class WorkflowManager:
|
|
|
3240
3237
|
workflow = self._get_workflow_by_name(request.workflow_name)
|
|
3241
3238
|
except KeyError:
|
|
3242
3239
|
details = f"Attempted to import workflow '{request.workflow_name}' as referenced sub flow. Failed because workflow is not registered"
|
|
3243
|
-
logger.error(details)
|
|
3244
3240
|
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3245
3241
|
|
|
3246
3242
|
# Check workflow version - Schema version 0.6.0+ required for referenced workflow imports
|
|
@@ -3249,7 +3245,6 @@ class WorkflowManager:
|
|
|
3249
3245
|
workflow_version = Version.from_string(workflow.metadata.schema_version)
|
|
3250
3246
|
if workflow_version is None or workflow_version < required_version:
|
|
3251
3247
|
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."
|
|
3252
|
-
logger.error(details)
|
|
3253
3248
|
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3254
3249
|
|
|
3255
3250
|
# Check target flow
|
|
@@ -3257,7 +3252,6 @@ class WorkflowManager:
|
|
|
3257
3252
|
if flow_name is None:
|
|
3258
3253
|
if not GriptapeNodes.ContextManager().has_current_flow():
|
|
3259
3254
|
details = f"Attempted to import workflow '{request.workflow_name}' into Current Context. Failed because Current Context was empty"
|
|
3260
|
-
logger.error(details)
|
|
3261
3255
|
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3262
3256
|
else:
|
|
3263
3257
|
# Validate that the specified flow exists
|
|
@@ -3266,7 +3260,6 @@ class WorkflowManager:
|
|
|
3266
3260
|
flow_manager.get_flow_by_name(flow_name)
|
|
3267
3261
|
except KeyError:
|
|
3268
3262
|
details = f"Attempted to import workflow '{request.workflow_name}' into flow '{flow_name}'. Failed because target flow does not exist"
|
|
3269
|
-
logger.error(details)
|
|
3270
3263
|
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3271
3264
|
|
|
3272
3265
|
return None
|
|
@@ -3290,7 +3283,6 @@ class WorkflowManager:
|
|
|
3290
3283
|
|
|
3291
3284
|
if not workflow_result.execution_successful:
|
|
3292
3285
|
details = f"Attempted to import workflow '{request.workflow_name}' as referenced sub flow. Failed because workflow execution failed: {workflow_result.execution_details}"
|
|
3293
|
-
logger.error(details)
|
|
3294
3286
|
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3295
3287
|
|
|
3296
3288
|
# Get flows after importing to find the new referenced sub flow
|
|
@@ -3299,7 +3291,6 @@ class WorkflowManager:
|
|
|
3299
3291
|
|
|
3300
3292
|
if not new_flows:
|
|
3301
3293
|
details = f"Attempted to import workflow '{request.workflow_name}' as referenced sub flow. Failed because no new flow was created"
|
|
3302
|
-
logger.error(details)
|
|
3303
3294
|
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3304
3295
|
|
|
3305
3296
|
# For now, use the first created flow as the main imported flow
|
|
@@ -3323,17 +3314,18 @@ class WorkflowManager:
|
|
|
3323
3314
|
|
|
3324
3315
|
if not isinstance(set_metadata_result, SetFlowMetadataResultSuccess):
|
|
3325
3316
|
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}'"
|
|
3326
|
-
logger.error(details)
|
|
3327
3317
|
return ImportWorkflowAsReferencedSubFlowResultFailure(result_details=details)
|
|
3328
3318
|
|
|
3329
3319
|
logger.debug(
|
|
3330
3320
|
"Applied imported flow metadata to '%s': %s", created_flow_name, request.imported_flow_metadata
|
|
3331
3321
|
)
|
|
3332
3322
|
|
|
3333
|
-
|
|
3334
|
-
"Successfully imported workflow '
|
|
3323
|
+
details = (
|
|
3324
|
+
f"Successfully imported workflow '{request.workflow_name}' as referenced sub flow '{created_flow_name}'"
|
|
3325
|
+
)
|
|
3326
|
+
return ImportWorkflowAsReferencedSubFlowResultSuccess(
|
|
3327
|
+
created_flow_name=created_flow_name, result_details=details
|
|
3335
3328
|
)
|
|
3336
|
-
return ImportWorkflowAsReferencedSubFlowResultSuccess(created_flow_name=created_flow_name)
|
|
3337
3329
|
|
|
3338
3330
|
def on_branch_workflow_request(self, request: BranchWorkflowRequest) -> ResultPayload:
|
|
3339
3331
|
"""Create a branch (copy) of an existing workflow with branch tracking."""
|
|
@@ -3342,7 +3334,6 @@ class WorkflowManager:
|
|
|
3342
3334
|
source_workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
3343
3335
|
except KeyError:
|
|
3344
3336
|
details = f"Failed to branch workflow '{request.workflow_name}' because it does not exist"
|
|
3345
|
-
logger.error(details)
|
|
3346
3337
|
return BranchWorkflowResultFailure(result_details=details)
|
|
3347
3338
|
|
|
3348
3339
|
# Generate branch name if not provided
|
|
@@ -3358,7 +3349,6 @@ class WorkflowManager:
|
|
|
3358
3349
|
# Check if branch name already exists
|
|
3359
3350
|
if WorkflowRegistry.has_workflow_with_name(branch_name):
|
|
3360
3351
|
details = f"Failed to branch workflow '{request.workflow_name}' because branch name '{branch_name}' already exists"
|
|
3361
|
-
logger.error(details)
|
|
3362
3352
|
return BranchWorkflowResultFailure(result_details=details)
|
|
3363
3353
|
|
|
3364
3354
|
try:
|
|
@@ -3387,7 +3377,6 @@ class WorkflowManager:
|
|
|
3387
3377
|
source_file_path = WorkflowRegistry.get_complete_file_path(source_workflow.file_path)
|
|
3388
3378
|
if not Path(source_file_path).exists():
|
|
3389
3379
|
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."
|
|
3390
|
-
logger.error(details)
|
|
3391
3380
|
return BranchWorkflowResultFailure(result_details=details)
|
|
3392
3381
|
|
|
3393
3382
|
source_content = Path(source_file_path).read_text(encoding="utf-8")
|
|
@@ -3396,7 +3385,6 @@ class WorkflowManager:
|
|
|
3396
3385
|
branch_content = self._replace_workflow_metadata_header(source_content, branch_metadata)
|
|
3397
3386
|
if branch_content is None:
|
|
3398
3387
|
details = f"Failed to replace metadata header for branch workflow '{branch_name}'"
|
|
3399
|
-
logger.error(details)
|
|
3400
3388
|
return BranchWorkflowResultFailure(result_details=details)
|
|
3401
3389
|
|
|
3402
3390
|
# Write branch workflow file to disk BEFORE registering in registry
|
|
@@ -3410,14 +3398,15 @@ class WorkflowManager:
|
|
|
3410
3398
|
config_manager = GriptapeNodes.ConfigManager()
|
|
3411
3399
|
config_manager.save_user_workflow_json(branch_full_path)
|
|
3412
3400
|
|
|
3413
|
-
|
|
3401
|
+
details = f"Successfully branched workflow '{request.workflow_name}' as '{branch_name}'"
|
|
3414
3402
|
return BranchWorkflowResultSuccess(
|
|
3415
|
-
branched_workflow_name=branch_name,
|
|
3403
|
+
branched_workflow_name=branch_name,
|
|
3404
|
+
original_workflow_name=request.workflow_name,
|
|
3405
|
+
result_details=ResultDetails(message=details, level="INFO"),
|
|
3416
3406
|
)
|
|
3417
3407
|
|
|
3418
3408
|
except Exception as e:
|
|
3419
3409
|
details = f"Failed to branch workflow '{request.workflow_name}': {e!s}"
|
|
3420
|
-
logger.error(details)
|
|
3421
3410
|
import traceback
|
|
3422
3411
|
|
|
3423
3412
|
traceback.print_exc()
|
|
@@ -3430,14 +3419,12 @@ class WorkflowManager:
|
|
|
3430
3419
|
branch_workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
3431
3420
|
except KeyError as e:
|
|
3432
3421
|
details = f"Failed to merge workflow branch because it does not exist: {e!s}"
|
|
3433
|
-
logger.error(details)
|
|
3434
3422
|
return MergeWorkflowBranchResultFailure(result_details=details)
|
|
3435
3423
|
|
|
3436
3424
|
# Get source workflow name from branch metadata
|
|
3437
3425
|
source_workflow_name = branch_workflow.metadata.branched_from
|
|
3438
3426
|
if not source_workflow_name:
|
|
3439
3427
|
details = f"Failed to merge workflow branch '{request.workflow_name}' because it has no source workflow"
|
|
3440
|
-
logger.error(details)
|
|
3441
3428
|
return MergeWorkflowBranchResultFailure(result_details=details)
|
|
3442
3429
|
|
|
3443
3430
|
# Validate source workflow exists
|
|
@@ -3445,7 +3432,6 @@ class WorkflowManager:
|
|
|
3445
3432
|
source_workflow = WorkflowRegistry.get_workflow_by_name(source_workflow_name)
|
|
3446
3433
|
except KeyError:
|
|
3447
3434
|
details = f"Failed to merge workflow branch '{request.workflow_name}' because source workflow '{source_workflow_name}' does not exist"
|
|
3448
|
-
logger.error(details)
|
|
3449
3435
|
return MergeWorkflowBranchResultFailure(result_details=details)
|
|
3450
3436
|
|
|
3451
3437
|
try:
|
|
@@ -3475,7 +3461,6 @@ class WorkflowManager:
|
|
|
3475
3461
|
merged_content = self._replace_workflow_metadata_header(branch_content, merged_metadata)
|
|
3476
3462
|
if merged_content is None:
|
|
3477
3463
|
details = f"Failed to replace metadata header for merged workflow '{source_workflow_name}'"
|
|
3478
|
-
logger.error(details)
|
|
3479
3464
|
return MergeWorkflowBranchResultFailure(result_details=details)
|
|
3480
3465
|
|
|
3481
3466
|
# Write the updated content to the source workflow file
|
|
@@ -3486,28 +3471,28 @@ class WorkflowManager:
|
|
|
3486
3471
|
source_workflow.metadata = merged_metadata
|
|
3487
3472
|
|
|
3488
3473
|
# Remove the branch workflow from registry and delete file
|
|
3474
|
+
result_messages = []
|
|
3489
3475
|
try:
|
|
3490
3476
|
WorkflowRegistry.delete_workflow_by_name(request.workflow_name)
|
|
3491
3477
|
Path(branch_content_file_path).unlink()
|
|
3492
|
-
|
|
3478
|
+
cleanup_message = f"Deleted branch workflow file and registry entry for '{request.workflow_name}'"
|
|
3479
|
+
result_messages.append(ResultDetail(message=cleanup_message, level="INFO"))
|
|
3493
3480
|
except Exception as delete_error:
|
|
3494
|
-
|
|
3495
|
-
"Failed to fully clean up branch workflow '
|
|
3496
|
-
request.workflow_name,
|
|
3497
|
-
str(delete_error),
|
|
3481
|
+
warning_message = (
|
|
3482
|
+
f"Failed to fully clean up branch workflow '{request.workflow_name}': {delete_error!s}"
|
|
3498
3483
|
)
|
|
3484
|
+
result_messages.append(ResultDetail(message=warning_message, level="WARNING"))
|
|
3499
3485
|
# Continue anyway - the merge was successful even if cleanup failed
|
|
3500
3486
|
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3487
|
+
success_message = f"Successfully merged branch workflow '{request.workflow_name}' into source workflow '{source_workflow_name}'"
|
|
3488
|
+
result_messages.append(ResultDetail(message=success_message, level="INFO"))
|
|
3489
|
+
|
|
3490
|
+
return MergeWorkflowBranchResultSuccess(
|
|
3491
|
+
merged_workflow_name=source_workflow_name, result_details=ResultDetails(*result_messages)
|
|
3505
3492
|
)
|
|
3506
|
-
return MergeWorkflowBranchResultSuccess(merged_workflow_name=source_workflow_name)
|
|
3507
3493
|
|
|
3508
3494
|
except Exception as e:
|
|
3509
3495
|
details = f"Failed to merge branch workflow '{request.workflow_name}' into source workflow '{source_workflow_name}': {e!s}"
|
|
3510
|
-
logger.error(details)
|
|
3511
3496
|
return MergeWorkflowBranchResultFailure(result_details=details)
|
|
3512
3497
|
|
|
3513
3498
|
def on_reset_workflow_branch_request(self, request: ResetWorkflowBranchRequest) -> ResultPayload:
|
|
@@ -3517,14 +3502,12 @@ class WorkflowManager:
|
|
|
3517
3502
|
branch_workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
3518
3503
|
except KeyError as e:
|
|
3519
3504
|
details = f"Failed to reset workflow branch because it does not exist: {e!s}"
|
|
3520
|
-
logger.error(details)
|
|
3521
3505
|
return ResetWorkflowBranchResultFailure(result_details=details)
|
|
3522
3506
|
|
|
3523
3507
|
# Get source workflow name from branch metadata
|
|
3524
3508
|
source_workflow_name = branch_workflow.metadata.branched_from
|
|
3525
3509
|
if not source_workflow_name:
|
|
3526
3510
|
details = f"Failed to reset workflow branch '{request.workflow_name}' because it has no source workflow"
|
|
3527
|
-
logger.error(details)
|
|
3528
3511
|
return ResetWorkflowBranchResultFailure(result_details=details)
|
|
3529
3512
|
|
|
3530
3513
|
# Validate source workflow exists
|
|
@@ -3532,7 +3515,6 @@ class WorkflowManager:
|
|
|
3532
3515
|
source_workflow = WorkflowRegistry.get_workflow_by_name(source_workflow_name)
|
|
3533
3516
|
except KeyError:
|
|
3534
3517
|
details = f"Failed to reset workflow branch '{request.workflow_name}' because source workflow '{source_workflow_name}' does not exist"
|
|
3535
|
-
logger.error(details)
|
|
3536
3518
|
return ResetWorkflowBranchResultFailure(result_details=details)
|
|
3537
3519
|
|
|
3538
3520
|
try:
|
|
@@ -3562,7 +3544,6 @@ class WorkflowManager:
|
|
|
3562
3544
|
reset_content = self._replace_workflow_metadata_header(source_content, reset_metadata)
|
|
3563
3545
|
if reset_content is None:
|
|
3564
3546
|
details = f"Failed to replace metadata header for reset branch workflow '{request.workflow_name}'"
|
|
3565
|
-
logger.error(details)
|
|
3566
3547
|
return ResetWorkflowBranchResultFailure(result_details=details)
|
|
3567
3548
|
|
|
3568
3549
|
# Write the updated content to the branch workflow file
|
|
@@ -3574,15 +3555,12 @@ class WorkflowManager:
|
|
|
3574
3555
|
|
|
3575
3556
|
except Exception as e:
|
|
3576
3557
|
details = f"Failed to reset branch workflow '{request.workflow_name}' to source workflow '{source_workflow_name}': {e!s}"
|
|
3577
|
-
logger.error(details)
|
|
3578
3558
|
return ResetWorkflowBranchResultFailure(result_details=details)
|
|
3579
3559
|
else:
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
request.workflow_name,
|
|
3583
|
-
source_workflow_name,
|
|
3560
|
+
details = f"Successfully reset branch workflow '{request.workflow_name}' to match source workflow '{source_workflow_name}'"
|
|
3561
|
+
return ResetWorkflowBranchResultSuccess(
|
|
3562
|
+
reset_workflow_name=request.workflow_name, result_details=ResultDetails(message=details, level="INFO")
|
|
3584
3563
|
)
|
|
3585
|
-
return ResetWorkflowBranchResultSuccess(reset_workflow_name=request.workflow_name)
|
|
3586
3564
|
|
|
3587
3565
|
def on_compare_workflows_request(self, request: CompareWorkflowsRequest) -> ResultPayload:
|
|
3588
3566
|
"""Compare two workflows to determine if one is ahead, behind, or up-to-date relative to the other."""
|
|
@@ -3591,7 +3569,6 @@ class WorkflowManager:
|
|
|
3591
3569
|
workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
3592
3570
|
except KeyError:
|
|
3593
3571
|
details = f"Failed to compare workflow '{request.workflow_name}' because it does not exist"
|
|
3594
|
-
logger.error(details)
|
|
3595
3572
|
return CompareWorkflowsResultFailure(result_details=details)
|
|
3596
3573
|
|
|
3597
3574
|
# Use the provided compare_workflow_name
|
|
@@ -3612,6 +3589,7 @@ class WorkflowManager:
|
|
|
3612
3589
|
else None,
|
|
3613
3590
|
source_last_modified=None,
|
|
3614
3591
|
details=details,
|
|
3592
|
+
result_details="Workflow comparison completed successfully.",
|
|
3615
3593
|
)
|
|
3616
3594
|
|
|
3617
3595
|
# Compare last modified dates
|
|
@@ -3629,6 +3607,7 @@ class WorkflowManager:
|
|
|
3629
3607
|
workflow_last_modified=workflow_last_modified.isoformat() if workflow_last_modified else None,
|
|
3630
3608
|
source_last_modified=source_last_modified.isoformat() if source_last_modified else None,
|
|
3631
3609
|
details=details,
|
|
3610
|
+
result_details="Workflow comparison completed successfully.",
|
|
3632
3611
|
)
|
|
3633
3612
|
|
|
3634
3613
|
# Compare timestamps to determine status
|
|
@@ -3651,6 +3630,7 @@ class WorkflowManager:
|
|
|
3651
3630
|
workflow_last_modified=workflow_last_modified.isoformat(),
|
|
3652
3631
|
source_last_modified=source_last_modified.isoformat(),
|
|
3653
3632
|
details=details,
|
|
3633
|
+
result_details="Workflow comparison completed successfully.",
|
|
3654
3634
|
)
|
|
3655
3635
|
|
|
3656
3636
|
def _walk_object_tree(
|
|
@@ -3810,18 +3790,26 @@ class WorkflowManager:
|
|
|
3810
3790
|
try:
|
|
3811
3791
|
workflows_to_register = GriptapeNodes.ConfigManager().get_config_value(request.config_section)
|
|
3812
3792
|
if not workflows_to_register:
|
|
3813
|
-
|
|
3814
|
-
return RegisterWorkflowsFromConfigResultSuccess(
|
|
3793
|
+
details = f"No workflows found in configuration section '{request.config_section}'"
|
|
3794
|
+
return RegisterWorkflowsFromConfigResultSuccess(
|
|
3795
|
+
succeeded_workflows=[], failed_workflows=[], result_details=details
|
|
3796
|
+
)
|
|
3815
3797
|
|
|
3816
3798
|
# Process all workflows and track results
|
|
3817
3799
|
succeeded, failed = self._process_workflows_for_registration(workflows_to_register)
|
|
3818
3800
|
|
|
3819
3801
|
except Exception as e:
|
|
3820
3802
|
details = f"Failed to register workflows from configuration section '{request.config_section}': {e!s}"
|
|
3821
|
-
logger.error(details)
|
|
3822
3803
|
return RegisterWorkflowsFromConfigResultFailure(result_details=details)
|
|
3823
3804
|
else:
|
|
3824
|
-
return RegisterWorkflowsFromConfigResultSuccess(
|
|
3805
|
+
return RegisterWorkflowsFromConfigResultSuccess(
|
|
3806
|
+
succeeded_workflows=succeeded,
|
|
3807
|
+
failed_workflows=failed,
|
|
3808
|
+
result_details=ResultDetails(
|
|
3809
|
+
message=f"Successfully processed workflows: {len(succeeded)} succeeded, {len(failed)} failed.",
|
|
3810
|
+
level="INFO",
|
|
3811
|
+
),
|
|
3812
|
+
)
|
|
3825
3813
|
|
|
3826
3814
|
def _process_workflows_for_registration(self, workflows_to_register: list[str]) -> WorkflowRegistrationResult:
|
|
3827
3815
|
"""Process a list of workflow paths for registration.
|