griptape-nodes 0.45.1__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/__init__.py +51 -14
- 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/node_library/workflow_registry.py +1 -1
- griptape_nodes/retained_mode/events/base_events.py +74 -1
- griptape_nodes/retained_mode/events/secrets_events.py +2 -0
- griptape_nodes/retained_mode/events/workflow_events.py +4 -2
- 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 +122 -129
- 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/version_compatibility_manager.py +84 -1
- griptape_nodes/retained_mode/managers/workflow_manager.py +221 -163
- griptape_nodes/retained_mode/retained_mode.py +22 -44
- griptape_nodes/version_compatibility/workflow_versions/__init__.py +1 -0
- griptape_nodes/version_compatibility/workflow_versions/v0_7_0/__init__.py +1 -0
- griptape_nodes/version_compatibility/workflow_versions/v0_7_0/local_executor_argument_addition.py +42 -0
- {griptape_nodes-0.45.1.dist-info → griptape_nodes-0.47.0.dist-info}/METADATA +1 -1
- {griptape_nodes-0.45.1.dist-info → griptape_nodes-0.47.0.dist-info}/RECORD +30 -27
- {griptape_nodes-0.45.1.dist-info → griptape_nodes-0.47.0.dist-info}/WHEEL +1 -1
- {griptape_nodes-0.45.1.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
|
|
@@ -959,6 +967,16 @@ class WorkflowManager:
|
|
|
959
967
|
status=status,
|
|
960
968
|
)
|
|
961
969
|
)
|
|
970
|
+
|
|
971
|
+
# Check for workflow version-based compatibility issues and add to problems
|
|
972
|
+
workflow_version_issues = GriptapeNodes.VersionCompatibilityManager().check_workflow_version_compatibility(
|
|
973
|
+
workflow_metadata
|
|
974
|
+
)
|
|
975
|
+
for issue in workflow_version_issues:
|
|
976
|
+
problems.append(issue.message)
|
|
977
|
+
if issue.severity == WorkflowManager.WorkflowStatus.UNUSABLE:
|
|
978
|
+
had_critical_error = True
|
|
979
|
+
|
|
962
980
|
# OK, we have all of our dependencies together. Let's look at the overall scenario.
|
|
963
981
|
if had_critical_error:
|
|
964
982
|
overall_status = WorkflowManager.WorkflowStatus.UNUSABLE
|
|
@@ -1351,14 +1369,15 @@ class WorkflowManager:
|
|
|
1351
1369
|
except Exception as err:
|
|
1352
1370
|
details = f"Attempted to save workflow '{relative_file_path}', but {err}"
|
|
1353
1371
|
logger.error(details)
|
|
1354
|
-
return SaveWorkflowResultFailure()
|
|
1372
|
+
return SaveWorkflowResultFailure(result_details=details)
|
|
1355
1373
|
|
|
1356
1374
|
# Create the pathing and write the file
|
|
1357
1375
|
try:
|
|
1358
1376
|
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1359
1377
|
except OSError as e:
|
|
1360
|
-
|
|
1361
|
-
|
|
1378
|
+
details = f"Attempted to save workflow '{file_name}'. Failed when creating directory: {e}"
|
|
1379
|
+
logger.error(details)
|
|
1380
|
+
return SaveWorkflowResultFailure(result_details=details)
|
|
1362
1381
|
|
|
1363
1382
|
relative_serialized_file_path = f"{file_name}.py"
|
|
1364
1383
|
serialized_file_path = GriptapeNodes.ConfigManager().workspace_path.joinpath(relative_serialized_file_path)
|
|
@@ -1368,17 +1387,17 @@ class WorkflowManager:
|
|
|
1368
1387
|
min_space_gb = config_manager.get_config_value("minimum_disk_space_gb_workflows")
|
|
1369
1388
|
if not OSManager.check_available_disk_space(serialized_file_path.parent, min_space_gb):
|
|
1370
1389
|
error_msg = OSManager.format_disk_space_error(serialized_file_path.parent)
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
)
|
|
1374
|
-
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)
|
|
1375
1393
|
|
|
1376
1394
|
try:
|
|
1377
1395
|
with serialized_file_path.open("w", encoding="utf-8") as file:
|
|
1378
1396
|
file.write(final_code_output)
|
|
1379
1397
|
except OSError as e:
|
|
1380
|
-
|
|
1381
|
-
|
|
1398
|
+
details = f"Attempted to save workflow '{file_name}'. Failed when writing file: {e}"
|
|
1399
|
+
logger.error(details)
|
|
1400
|
+
return SaveWorkflowResultFailure(result_details=details)
|
|
1382
1401
|
|
|
1383
1402
|
# save the created workflow as an entry in the JSON config file.
|
|
1384
1403
|
registered_workflows = WorkflowRegistry.list_workflows()
|
|
@@ -1386,8 +1405,9 @@ class WorkflowManager:
|
|
|
1386
1405
|
try:
|
|
1387
1406
|
GriptapeNodes.ConfigManager().save_user_workflow_json(str(file_path))
|
|
1388
1407
|
except OSError as e:
|
|
1389
|
-
|
|
1390
|
-
|
|
1408
|
+
details = f"Attempted to save workflow '{file_name}'. Failed when saving configuration: {e}"
|
|
1409
|
+
logger.error(details)
|
|
1410
|
+
return SaveWorkflowResultFailure(result_details=details)
|
|
1391
1411
|
WorkflowRegistry.generate_new_workflow(metadata=workflow_metadata, file_path=relative_file_path)
|
|
1392
1412
|
# Update existing workflow's metadata in the registry
|
|
1393
1413
|
existing_workflow = WorkflowRegistry.get_workflow_by_name(file_name)
|
|
@@ -1490,6 +1510,7 @@ class WorkflowManager:
|
|
|
1490
1510
|
|
|
1491
1511
|
# === imports ===
|
|
1492
1512
|
import_recorder.add_import("argparse")
|
|
1513
|
+
import_recorder.add_import("json")
|
|
1493
1514
|
import_recorder.add_from_import(
|
|
1494
1515
|
"griptape_nodes.bootstrap.workflow_executors.local_workflow_executor", "LocalWorkflowExecutor"
|
|
1495
1516
|
)
|
|
@@ -1629,6 +1650,29 @@ class WorkflowManager:
|
|
|
1629
1650
|
)
|
|
1630
1651
|
)
|
|
1631
1652
|
|
|
1653
|
+
# Add json input argument
|
|
1654
|
+
add_arg_calls.append(
|
|
1655
|
+
ast.Expr(
|
|
1656
|
+
value=ast.Call(
|
|
1657
|
+
func=ast.Attribute(
|
|
1658
|
+
value=ast.Name(id="parser", ctx=ast.Load()),
|
|
1659
|
+
attr="add_argument",
|
|
1660
|
+
ctx=ast.Load(),
|
|
1661
|
+
),
|
|
1662
|
+
args=[ast.Constant("--json-input")],
|
|
1663
|
+
keywords=[
|
|
1664
|
+
ast.keyword(arg="default", value=ast.Constant(None)),
|
|
1665
|
+
ast.keyword(
|
|
1666
|
+
arg="help",
|
|
1667
|
+
value=ast.Constant(
|
|
1668
|
+
"JSON string containing parameter values. Takes precedence over individual parameter arguments if provided."
|
|
1669
|
+
),
|
|
1670
|
+
),
|
|
1671
|
+
],
|
|
1672
|
+
)
|
|
1673
|
+
)
|
|
1674
|
+
)
|
|
1675
|
+
|
|
1632
1676
|
# Generate individual arguments for each parameter in workflow_shape["input"]
|
|
1633
1677
|
if "input" in workflow_shape:
|
|
1634
1678
|
for node_name, node_params in workflow_shape["input"].items():
|
|
@@ -1670,13 +1714,47 @@ class WorkflowManager:
|
|
|
1670
1714
|
),
|
|
1671
1715
|
)
|
|
1672
1716
|
|
|
1673
|
-
# Build flow_input dictionary from individual CLI arguments
|
|
1717
|
+
# Build flow_input dictionary from JSON input or individual CLI arguments
|
|
1674
1718
|
flow_input_init = ast.Assign(
|
|
1675
1719
|
targets=[ast.Name(id="flow_input", ctx=ast.Store())],
|
|
1676
1720
|
value=ast.Dict(keys=[], values=[]),
|
|
1677
1721
|
)
|
|
1678
1722
|
|
|
1679
|
-
#
|
|
1723
|
+
# Check if json_input is provided and parse it
|
|
1724
|
+
json_input_if = ast.If(
|
|
1725
|
+
test=ast.Compare(
|
|
1726
|
+
left=ast.Attribute(
|
|
1727
|
+
value=ast.Name(id="args", ctx=ast.Load()),
|
|
1728
|
+
attr="json_input",
|
|
1729
|
+
ctx=ast.Load(),
|
|
1730
|
+
),
|
|
1731
|
+
ops=[ast.IsNot()],
|
|
1732
|
+
comparators=[ast.Constant(value=None)],
|
|
1733
|
+
),
|
|
1734
|
+
body=[
|
|
1735
|
+
ast.Assign(
|
|
1736
|
+
targets=[ast.Name(id="flow_input", ctx=ast.Store())],
|
|
1737
|
+
value=ast.Call(
|
|
1738
|
+
func=ast.Attribute(
|
|
1739
|
+
value=ast.Name(id="json", ctx=ast.Load()),
|
|
1740
|
+
attr="loads",
|
|
1741
|
+
ctx=ast.Load(),
|
|
1742
|
+
),
|
|
1743
|
+
args=[
|
|
1744
|
+
ast.Attribute(
|
|
1745
|
+
value=ast.Name(id="args", ctx=ast.Load()),
|
|
1746
|
+
attr="json_input",
|
|
1747
|
+
ctx=ast.Load(),
|
|
1748
|
+
)
|
|
1749
|
+
],
|
|
1750
|
+
keywords=[],
|
|
1751
|
+
),
|
|
1752
|
+
)
|
|
1753
|
+
],
|
|
1754
|
+
orelse=[],
|
|
1755
|
+
)
|
|
1756
|
+
|
|
1757
|
+
# Build the flow_input dict structure from individual arguments (fallback when no JSON input)
|
|
1680
1758
|
build_flow_input_stmts = []
|
|
1681
1759
|
|
|
1682
1760
|
# For each node, ensure it exists in flow_input
|
|
@@ -1747,6 +1825,21 @@ class WorkflowManager:
|
|
|
1747
1825
|
]
|
|
1748
1826
|
)
|
|
1749
1827
|
|
|
1828
|
+
# Wrap the individual argument processing in an else clause
|
|
1829
|
+
individual_args_else = ast.If(
|
|
1830
|
+
test=ast.Compare(
|
|
1831
|
+
left=ast.Attribute(
|
|
1832
|
+
value=ast.Name(id="args", ctx=ast.Load()),
|
|
1833
|
+
attr="json_input",
|
|
1834
|
+
ctx=ast.Load(),
|
|
1835
|
+
),
|
|
1836
|
+
ops=[ast.Is()],
|
|
1837
|
+
comparators=[ast.Constant(value=None)],
|
|
1838
|
+
),
|
|
1839
|
+
body=build_flow_input_stmts,
|
|
1840
|
+
orelse=[],
|
|
1841
|
+
)
|
|
1842
|
+
|
|
1750
1843
|
workflow_output = ast.Assign(
|
|
1751
1844
|
targets=[ast.Name(id="workflow_output", ctx=ast.Store())],
|
|
1752
1845
|
value=ast.Call(
|
|
@@ -1780,7 +1873,8 @@ class WorkflowManager:
|
|
|
1780
1873
|
*add_arg_calls,
|
|
1781
1874
|
parse_args,
|
|
1782
1875
|
flow_input_init,
|
|
1783
|
-
|
|
1876
|
+
json_input_if,
|
|
1877
|
+
individual_args_else,
|
|
1784
1878
|
workflow_output,
|
|
1785
1879
|
print_output,
|
|
1786
1880
|
],
|
|
@@ -2974,7 +3068,7 @@ class WorkflowManager:
|
|
|
2974
3068
|
except Exception as e:
|
|
2975
3069
|
details = f"Failed to publish workflow '{request.workflow_name}': {e!s}"
|
|
2976
3070
|
logger.exception(details)
|
|
2977
|
-
return PublishWorkflowResultFailure(exception=e)
|
|
3071
|
+
return PublishWorkflowResultFailure(exception=e, result_details=details)
|
|
2978
3072
|
|
|
2979
3073
|
def _register_published_workflow_file(self, workflow_file: Path) -> None:
|
|
2980
3074
|
"""Register a published workflow file in the workflow registry."""
|
|
@@ -3034,45 +3128,35 @@ class WorkflowManager:
|
|
|
3034
3128
|
try:
|
|
3035
3129
|
workflow = self._get_workflow_by_name(request.workflow_name)
|
|
3036
3130
|
except KeyError:
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
)
|
|
3041
|
-
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)
|
|
3042
3134
|
|
|
3043
3135
|
# Check workflow version - Schema version 0.6.0+ required for referenced workflow imports
|
|
3044
3136
|
# (workflow schema was fixed in 0.6.0 to support importing workflows)
|
|
3045
3137
|
required_version = Version(major=0, minor=6, patch=0)
|
|
3046
3138
|
workflow_version = Version.from_string(workflow.metadata.schema_version)
|
|
3047
3139
|
if workflow_version is None or workflow_version < required_version:
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
workflow.metadata.schema_version,
|
|
3052
|
-
)
|
|
3053
|
-
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)
|
|
3054
3143
|
|
|
3055
3144
|
# Check target flow
|
|
3056
3145
|
flow_name = request.flow_name
|
|
3057
3146
|
if flow_name is None:
|
|
3058
3147
|
if not GriptapeNodes.ContextManager().has_current_flow():
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
)
|
|
3063
|
-
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)
|
|
3064
3151
|
else:
|
|
3065
3152
|
# Validate that the specified flow exists
|
|
3066
3153
|
flow_manager = GriptapeNodes.FlowManager()
|
|
3067
3154
|
try:
|
|
3068
3155
|
flow_manager.get_flow_by_name(flow_name)
|
|
3069
3156
|
except KeyError:
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
flow_name,
|
|
3074
|
-
)
|
|
3075
|
-
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)
|
|
3076
3160
|
|
|
3077
3161
|
return None
|
|
3078
3162
|
|
|
@@ -3094,23 +3178,18 @@ class WorkflowManager:
|
|
|
3094
3178
|
workflow_result = self.run_workflow(workflow.file_path)
|
|
3095
3179
|
|
|
3096
3180
|
if not workflow_result.execution_successful:
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
workflow_result.execution_details,
|
|
3101
|
-
)
|
|
3102
|
-
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)
|
|
3103
3184
|
|
|
3104
3185
|
# Get flows after importing to find the new referenced sub flow
|
|
3105
3186
|
flows_after = set(obj_manager.get_filtered_subset(type=ControlFlow).keys())
|
|
3106
3187
|
new_flows = flows_after - flows_before
|
|
3107
3188
|
|
|
3108
3189
|
if not new_flows:
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
)
|
|
3113
|
-
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)
|
|
3114
3193
|
|
|
3115
3194
|
# For now, use the first created flow as the main imported flow
|
|
3116
3195
|
# This handles nested workflows correctly since sub-flows are expected
|
|
@@ -3132,12 +3211,9 @@ class WorkflowManager:
|
|
|
3132
3211
|
set_metadata_result = GriptapeNodes.handle_request(set_metadata_request)
|
|
3133
3212
|
|
|
3134
3213
|
if not isinstance(set_metadata_result, SetFlowMetadataResultSuccess):
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
created_flow_name,
|
|
3139
|
-
)
|
|
3140
|
-
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)
|
|
3141
3217
|
|
|
3142
3218
|
logger.debug(
|
|
3143
3219
|
"Applied imported flow metadata to '%s': %s", created_flow_name, request.imported_flow_metadata
|
|
@@ -3154,8 +3230,9 @@ class WorkflowManager:
|
|
|
3154
3230
|
# Validate source workflow exists
|
|
3155
3231
|
source_workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
3156
3232
|
except KeyError:
|
|
3157
|
-
|
|
3158
|
-
|
|
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)
|
|
3159
3236
|
|
|
3160
3237
|
# Generate branch name if not provided
|
|
3161
3238
|
branch_name = request.branched_workflow_name
|
|
@@ -3169,12 +3246,9 @@ class WorkflowManager:
|
|
|
3169
3246
|
|
|
3170
3247
|
# Check if branch name already exists
|
|
3171
3248
|
if WorkflowRegistry.has_workflow_with_name(branch_name):
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
branch_name,
|
|
3176
|
-
)
|
|
3177
|
-
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)
|
|
3178
3252
|
|
|
3179
3253
|
try:
|
|
3180
3254
|
# Create branch metadata by copying source metadata
|
|
@@ -3201,21 +3275,18 @@ class WorkflowManager:
|
|
|
3201
3275
|
# Read source workflow content and replace metadata header
|
|
3202
3276
|
source_file_path = WorkflowRegistry.get_complete_file_path(source_workflow.file_path)
|
|
3203
3277
|
if not Path(source_file_path).exists():
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
request.workflow_name,
|
|
3208
|
-
source_file_path,
|
|
3209
|
-
)
|
|
3210
|
-
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)
|
|
3211
3281
|
|
|
3212
3282
|
source_content = Path(source_file_path).read_text(encoding="utf-8")
|
|
3213
3283
|
|
|
3214
3284
|
# Replace the metadata header with branch metadata
|
|
3215
3285
|
branch_content = self._replace_workflow_metadata_header(source_content, branch_metadata)
|
|
3216
3286
|
if branch_content is None:
|
|
3217
|
-
|
|
3218
|
-
|
|
3287
|
+
details = f"Failed to replace metadata header for branch workflow '{branch_name}'"
|
|
3288
|
+
logger.error(details)
|
|
3289
|
+
return BranchWorkflowResultFailure(result_details=details)
|
|
3219
3290
|
|
|
3220
3291
|
# Write branch workflow file to disk BEFORE registering in registry
|
|
3221
3292
|
branch_full_path = WorkflowRegistry.get_complete_file_path(branch_file_path)
|
|
@@ -3234,11 +3305,12 @@ class WorkflowManager:
|
|
|
3234
3305
|
)
|
|
3235
3306
|
|
|
3236
3307
|
except Exception as e:
|
|
3237
|
-
|
|
3308
|
+
details = f"Failed to branch workflow '{request.workflow_name}': {e!s}"
|
|
3309
|
+
logger.error(details)
|
|
3238
3310
|
import traceback
|
|
3239
3311
|
|
|
3240
3312
|
traceback.print_exc()
|
|
3241
|
-
return BranchWorkflowResultFailure()
|
|
3313
|
+
return BranchWorkflowResultFailure(result_details=details)
|
|
3242
3314
|
|
|
3243
3315
|
def on_merge_workflow_branch_request(self, request: MergeWorkflowBranchRequest) -> ResultPayload:
|
|
3244
3316
|
"""Merge a branch back into its source workflow, removing the branch when complete."""
|
|
@@ -3246,28 +3318,24 @@ class WorkflowManager:
|
|
|
3246
3318
|
# Validate branch workflow exists
|
|
3247
3319
|
branch_workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
3248
3320
|
except KeyError as e:
|
|
3249
|
-
|
|
3250
|
-
|
|
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)
|
|
3251
3324
|
|
|
3252
3325
|
# Get source workflow name from branch metadata
|
|
3253
3326
|
source_workflow_name = branch_workflow.metadata.branched_from
|
|
3254
3327
|
if not source_workflow_name:
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
)
|
|
3259
|
-
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)
|
|
3260
3331
|
|
|
3261
3332
|
# Validate source workflow exists
|
|
3262
3333
|
try:
|
|
3263
3334
|
source_workflow = WorkflowRegistry.get_workflow_by_name(source_workflow_name)
|
|
3264
3335
|
except KeyError:
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
source_workflow_name,
|
|
3269
|
-
)
|
|
3270
|
-
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)
|
|
3271
3339
|
|
|
3272
3340
|
try:
|
|
3273
3341
|
# Create updated metadata for source workflow - update timestamp
|
|
@@ -3295,8 +3363,9 @@ class WorkflowManager:
|
|
|
3295
3363
|
# Replace the metadata header with merged metadata
|
|
3296
3364
|
merged_content = self._replace_workflow_metadata_header(branch_content, merged_metadata)
|
|
3297
3365
|
if merged_content is None:
|
|
3298
|
-
|
|
3299
|
-
|
|
3366
|
+
details = f"Failed to replace metadata header for merged workflow '{source_workflow_name}'"
|
|
3367
|
+
logger.error(details)
|
|
3368
|
+
return MergeWorkflowBranchResultFailure(result_details=details)
|
|
3300
3369
|
|
|
3301
3370
|
# Write the updated content to the source workflow file
|
|
3302
3371
|
source_file_path = WorkflowRegistry.get_complete_file_path(source_workflow.file_path)
|
|
@@ -3326,13 +3395,9 @@ class WorkflowManager:
|
|
|
3326
3395
|
return MergeWorkflowBranchResultSuccess(merged_workflow_name=source_workflow_name)
|
|
3327
3396
|
|
|
3328
3397
|
except Exception as e:
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
source_workflow_name,
|
|
3333
|
-
str(e),
|
|
3334
|
-
)
|
|
3335
|
-
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)
|
|
3336
3401
|
|
|
3337
3402
|
def on_reset_workflow_branch_request(self, request: ResetWorkflowBranchRequest) -> ResultPayload:
|
|
3338
3403
|
"""Reset a branch to match its source workflow, discarding branch changes."""
|
|
@@ -3340,28 +3405,24 @@ class WorkflowManager:
|
|
|
3340
3405
|
# Validate branch workflow exists
|
|
3341
3406
|
branch_workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
3342
3407
|
except KeyError as e:
|
|
3343
|
-
|
|
3344
|
-
|
|
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)
|
|
3345
3411
|
|
|
3346
3412
|
# Get source workflow name from branch metadata
|
|
3347
3413
|
source_workflow_name = branch_workflow.metadata.branched_from
|
|
3348
3414
|
if not source_workflow_name:
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
)
|
|
3353
|
-
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)
|
|
3354
3418
|
|
|
3355
3419
|
# Validate source workflow exists
|
|
3356
3420
|
try:
|
|
3357
3421
|
source_workflow = WorkflowRegistry.get_workflow_by_name(source_workflow_name)
|
|
3358
3422
|
except KeyError:
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
source_workflow_name,
|
|
3363
|
-
)
|
|
3364
|
-
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)
|
|
3365
3426
|
|
|
3366
3427
|
try:
|
|
3367
3428
|
# Read content from the source workflow (what we're resetting the branch to)
|
|
@@ -3389,8 +3450,9 @@ class WorkflowManager:
|
|
|
3389
3450
|
# Replace the metadata header with reset metadata
|
|
3390
3451
|
reset_content = self._replace_workflow_metadata_header(source_content, reset_metadata)
|
|
3391
3452
|
if reset_content is None:
|
|
3392
|
-
|
|
3393
|
-
|
|
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)
|
|
3394
3456
|
|
|
3395
3457
|
# Write the updated content to the branch workflow file
|
|
3396
3458
|
branch_content_file_path = WorkflowRegistry.get_complete_file_path(branch_workflow.file_path)
|
|
@@ -3400,13 +3462,9 @@ class WorkflowManager:
|
|
|
3400
3462
|
branch_workflow.metadata = reset_metadata
|
|
3401
3463
|
|
|
3402
3464
|
except Exception as e:
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
source_workflow_name,
|
|
3407
|
-
str(e),
|
|
3408
|
-
)
|
|
3409
|
-
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)
|
|
3410
3468
|
else:
|
|
3411
3469
|
logger.info(
|
|
3412
3470
|
"Successfully reset branch workflow '%s' to match source workflow '%s'",
|
|
@@ -3421,8 +3479,9 @@ class WorkflowManager:
|
|
|
3421
3479
|
# Get the workflow to evaluate
|
|
3422
3480
|
workflow = WorkflowRegistry.get_workflow_by_name(request.workflow_name)
|
|
3423
3481
|
except KeyError:
|
|
3424
|
-
|
|
3425
|
-
|
|
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)
|
|
3426
3485
|
|
|
3427
3486
|
# Use the provided compare_workflow_name
|
|
3428
3487
|
compare_workflow_name = request.compare_workflow_name
|
|
@@ -3647,10 +3706,9 @@ class WorkflowManager:
|
|
|
3647
3706
|
succeeded, failed = self._process_workflows_for_registration(workflows_to_register)
|
|
3648
3707
|
|
|
3649
3708
|
except Exception as e:
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
)
|
|
3653
|
-
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)
|
|
3654
3712
|
else:
|
|
3655
3713
|
return RegisterWorkflowsFromConfigResultSuccess(succeeded_workflows=succeeded, failed_workflows=failed)
|
|
3656
3714
|
|