griptape-nodes 0.54.1__tar.gz → 0.55.1__tar.gz
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-0.54.1 → griptape_nodes-0.55.1}/PKG-INFO +1 -1
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/pyproject.toml +1 -1
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/exe_types/core_types.py +104 -18
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/exe_types/node_types.py +5 -2
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/machines/parallel_resolution.py +20 -16
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/node_library/library_registry.py +1 -4
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/execution_events.py +2 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/flow_manager.py +31 -28
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/library_manager.py +51 -22
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/node_manager.py +24 -4
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/workflow_manager.py +36 -9
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/README.md +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/__main__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/app/.python-version +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/app/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/app/app.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/app/watch.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/bootstrap/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/bootstrap/workflow_executors/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/bootstrap/workflow_executors/local_workflow_executor.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/bootstrap/workflow_executors/workflow_executor.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/cli/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/cli/commands/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/cli/commands/config.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/cli/commands/engine.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/cli/commands/init.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/cli/commands/libraries.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/cli/commands/models.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/cli/commands/self.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/cli/main.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/cli/shared.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/common/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/common/directed_graph.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/drivers/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/drivers/storage/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/drivers/storage/base_storage_driver.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/drivers/storage/griptape_cloud_storage_driver.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/drivers/storage/local_storage_driver.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/drivers/storage/storage_backend.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/exe_types/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/exe_types/connections.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/exe_types/flow.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/exe_types/param_components/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/exe_types/param_components/execution_status_component.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/exe_types/type_validator.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/machines/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/machines/control_flow.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/machines/dag_builder.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/machines/fsm.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/machines/sequential_resolution.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/mcp_server/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/node_library/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/node_library/advanced_node_library.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/node_library/workflow_registry.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/py.typed +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/agent_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/app_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/arbitrary_python_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/base_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/config_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/connection_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/context_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/flow_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/generate_request_payload_schemas.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/library_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/logger_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/model_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/node_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/object_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/os_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/parameter_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/payload_registry.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/secrets_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/static_file_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/sync_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/validation_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/variable_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/events/workflow_events.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/griptape_nodes.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/agent_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/config_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/context_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/engine_identity_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/event_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/library_lifecycle/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/library_lifecycle/data_models.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_directory.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_fsm.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/base.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/github.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/local_file.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/package.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/sandbox.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_status.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/model_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/object_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/operation_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/os_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/secrets_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/session_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/settings.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/static_files_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/sync_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/variable_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/managers/version_compatibility_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/retained_mode.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/utils/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/utils/engine_identity.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/utils/name_generator.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/retained_mode/variable_types.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/servers/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/servers/mcp.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/servers/static.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/servers/ws_request_manager.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/add_param_button.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/button.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/clamp.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/color_picker.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/compare.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/compare_images.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/file_system_picker.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/minmax.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/multi_options.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/numbers_selector.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/options.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/slider.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/trait_registry.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/traits/traits.json +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/updater/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/updater/__main__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/utils/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/utils/async_utils.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/utils/dict_utils.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/utils/image_preview.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/utils/metaclasses.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/utils/uv_utils.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/utils/version_utils.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/version_compatibility/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/version_compatibility/versions/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/version_compatibility/versions/v0_39_0/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/version_compatibility/versions/v0_39_0/modified_parameters_set_removal.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/version_compatibility/workflow_versions/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/version_compatibility/workflow_versions/v0_7_0/__init__.py +0 -0
- {griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/version_compatibility/workflow_versions/v0_7_0/local_executor_argument_addition.py +0 -0
|
@@ -501,18 +501,42 @@ class ParameterMessage(BaseNodeElement, UIOptionsMixin):
|
|
|
501
501
|
"error": "Error",
|
|
502
502
|
"success": "Success",
|
|
503
503
|
"tip": "Tip",
|
|
504
|
+
"link": "Link",
|
|
505
|
+
"docs": "Documentation",
|
|
506
|
+
"help": "Help",
|
|
507
|
+
"note": "Note",
|
|
508
|
+
"none": "",
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
# Define default icons as a class-level constant (based on Lucide icons)
|
|
512
|
+
DEFAULT_ICONS: ClassVar[dict[str, str]] = {
|
|
513
|
+
"info": "info",
|
|
514
|
+
"warning": "alert-triangle",
|
|
515
|
+
"error": "x-circle",
|
|
516
|
+
"success": "check-circle",
|
|
517
|
+
"tip": "lightbulb",
|
|
518
|
+
"link": "external-link",
|
|
519
|
+
"docs": "book-open",
|
|
520
|
+
"help": "help-circle",
|
|
521
|
+
"note": "sticky-note",
|
|
504
522
|
"none": "",
|
|
505
523
|
}
|
|
506
524
|
|
|
507
525
|
# Create a type alias using the keys from DEFAULT_TITLES
|
|
508
|
-
type VariantType = Literal["info", "warning", "error", "success", "tip", "none"]
|
|
526
|
+
type VariantType = Literal["info", "warning", "error", "success", "tip", "link", "docs", "help", "note", "none"]
|
|
527
|
+
type ButtonAlignType = Literal["full-width", "left", "center", "right"]
|
|
528
|
+
type ButtonVariantType = Literal["default", "destructive", "outline", "secondary", "ghost", "link"]
|
|
509
529
|
|
|
510
530
|
element_type: str = field(default_factory=lambda: ParameterMessage.__name__)
|
|
511
531
|
_variant: VariantType = field(init=False)
|
|
512
532
|
_title: str | None = field(default=None, init=False)
|
|
513
533
|
_value: str = field(init=False)
|
|
534
|
+
_message_icon: str | None = field(default="__DEFAULT__", init=False)
|
|
514
535
|
_button_link: str | None = field(default=None, init=False)
|
|
515
536
|
_button_text: str | None = field(default=None, init=False)
|
|
537
|
+
_button_icon: str | None = field(default=None, init=False)
|
|
538
|
+
_button_variant: ButtonVariantType = field(default="outline", init=False)
|
|
539
|
+
_button_align: ButtonAlignType = field(default="full-width", init=False)
|
|
516
540
|
_full_width: bool = field(default=False, init=False)
|
|
517
541
|
_ui_options: dict = field(default_factory=dict, init=False)
|
|
518
542
|
|
|
@@ -522,8 +546,12 @@ class ParameterMessage(BaseNodeElement, UIOptionsMixin):
|
|
|
522
546
|
value: str,
|
|
523
547
|
*,
|
|
524
548
|
title: str | None = None,
|
|
549
|
+
message_icon: str | None = "__DEFAULT__",
|
|
525
550
|
button_link: str | None = None,
|
|
526
551
|
button_text: str | None = None,
|
|
552
|
+
button_icon: str | None = None,
|
|
553
|
+
button_variant: ButtonVariantType = "outline",
|
|
554
|
+
button_align: ButtonAlignType = "full-width",
|
|
527
555
|
full_width: bool = False,
|
|
528
556
|
ui_options: dict | None = None,
|
|
529
557
|
**kwargs,
|
|
@@ -532,8 +560,12 @@ class ParameterMessage(BaseNodeElement, UIOptionsMixin):
|
|
|
532
560
|
self._variant = variant
|
|
533
561
|
self._title = title
|
|
534
562
|
self._value = value
|
|
563
|
+
self._message_icon = message_icon
|
|
535
564
|
self._button_link = button_link
|
|
536
565
|
self._button_text = button_text
|
|
566
|
+
self._button_icon = button_icon
|
|
567
|
+
self._button_variant = button_variant
|
|
568
|
+
self._button_align = button_align
|
|
537
569
|
self._full_width = full_width
|
|
538
570
|
self._ui_options = ui_options or {}
|
|
539
571
|
|
|
@@ -591,6 +623,42 @@ class ParameterMessage(BaseNodeElement, UIOptionsMixin):
|
|
|
591
623
|
def full_width(self, value: bool) -> None:
|
|
592
624
|
self._full_width = value
|
|
593
625
|
|
|
626
|
+
@property
|
|
627
|
+
def message_icon(self) -> str | None:
|
|
628
|
+
return self._message_icon
|
|
629
|
+
|
|
630
|
+
@message_icon.setter
|
|
631
|
+
@BaseNodeElement.emits_update_on_write
|
|
632
|
+
def message_icon(self, value: str | None) -> None:
|
|
633
|
+
self._message_icon = value
|
|
634
|
+
|
|
635
|
+
@property
|
|
636
|
+
def button_icon(self) -> str | None:
|
|
637
|
+
return self._button_icon
|
|
638
|
+
|
|
639
|
+
@button_icon.setter
|
|
640
|
+
@BaseNodeElement.emits_update_on_write
|
|
641
|
+
def button_icon(self, value: str | None) -> None:
|
|
642
|
+
self._button_icon = value
|
|
643
|
+
|
|
644
|
+
@property
|
|
645
|
+
def button_variant(self) -> ButtonVariantType:
|
|
646
|
+
return self._button_variant
|
|
647
|
+
|
|
648
|
+
@button_variant.setter
|
|
649
|
+
@BaseNodeElement.emits_update_on_write
|
|
650
|
+
def button_variant(self, value: ButtonVariantType) -> None:
|
|
651
|
+
self._button_variant = value
|
|
652
|
+
|
|
653
|
+
@property
|
|
654
|
+
def button_align(self) -> ButtonAlignType:
|
|
655
|
+
return self._button_align
|
|
656
|
+
|
|
657
|
+
@button_align.setter
|
|
658
|
+
@BaseNodeElement.emits_update_on_write
|
|
659
|
+
def button_align(self, value: ButtonAlignType) -> None:
|
|
660
|
+
self._button_align = value
|
|
661
|
+
|
|
594
662
|
@property
|
|
595
663
|
def ui_options(self) -> dict:
|
|
596
664
|
return self._ui_options
|
|
@@ -603,23 +671,46 @@ class ParameterMessage(BaseNodeElement, UIOptionsMixin):
|
|
|
603
671
|
def to_dict(self) -> dict[str, Any]:
|
|
604
672
|
data = super().to_dict()
|
|
605
673
|
|
|
606
|
-
# Use class-level default titles
|
|
674
|
+
# Use class-level default titles and icons
|
|
607
675
|
title = self.title or self.DEFAULT_TITLES.get(str(self.variant), "")
|
|
608
676
|
|
|
677
|
+
# Handle message_icon logic:
|
|
678
|
+
# - "__DEFAULT__" means use the default icon for the variant
|
|
679
|
+
# - None means explicitly no icon (empty string)
|
|
680
|
+
# - Any other string means use that icon
|
|
681
|
+
if self.message_icon == "__DEFAULT__":
|
|
682
|
+
message_icon = self.DEFAULT_ICONS.get(str(self.variant), "")
|
|
683
|
+
elif self.message_icon is None:
|
|
684
|
+
message_icon = ""
|
|
685
|
+
else:
|
|
686
|
+
message_icon = self.message_icon
|
|
687
|
+
|
|
688
|
+
# Handle button_icon logic:
|
|
689
|
+
# - None means no icon
|
|
690
|
+
# - Empty string means no icon
|
|
691
|
+
# - Any other string means use that icon
|
|
692
|
+
if self.button_icon is None or self.button_icon == "":
|
|
693
|
+
button_icon = ""
|
|
694
|
+
else:
|
|
695
|
+
button_icon = self.button_icon
|
|
696
|
+
|
|
609
697
|
# Merge the UI options with the message-specific options
|
|
698
|
+
# Always include these fields, even if they're None or empty
|
|
699
|
+
message_ui_options = {
|
|
700
|
+
"title": title,
|
|
701
|
+
"variant": self.variant,
|
|
702
|
+
"message_icon": message_icon,
|
|
703
|
+
"button_link": self.button_link,
|
|
704
|
+
"button_text": self.button_text,
|
|
705
|
+
"button_icon": button_icon,
|
|
706
|
+
"button_variant": self.button_variant,
|
|
707
|
+
"button_align": self.button_align,
|
|
708
|
+
"full_width": self.full_width,
|
|
709
|
+
}
|
|
710
|
+
|
|
610
711
|
merged_ui_options = {
|
|
611
712
|
**self.ui_options,
|
|
612
|
-
**
|
|
613
|
-
k: v
|
|
614
|
-
for k, v in {
|
|
615
|
-
"title": title,
|
|
616
|
-
"variant": self.variant,
|
|
617
|
-
"button_link": self.button_link,
|
|
618
|
-
"button_text": self.button_text,
|
|
619
|
-
"full_width": self.full_width,
|
|
620
|
-
}.items()
|
|
621
|
-
if v is not None
|
|
622
|
-
},
|
|
713
|
+
**message_ui_options,
|
|
623
714
|
}
|
|
624
715
|
|
|
625
716
|
data["name"] = self.name
|
|
@@ -986,11 +1077,6 @@ class Parameter(BaseNodeElement, UIOptionsMixin):
|
|
|
986
1077
|
for trait in traits:
|
|
987
1078
|
ui_options = ui_options | trait.ui_options_for_trait()
|
|
988
1079
|
ui_options = ui_options | self._ui_options
|
|
989
|
-
if self._parent is not None and isinstance(self._parent, ParameterGroup):
|
|
990
|
-
# Access the field value directly for ParameterGroup
|
|
991
|
-
parent_ui_options = getattr(self._parent, "ui_options", {})
|
|
992
|
-
if isinstance(parent_ui_options, dict):
|
|
993
|
-
ui_options = ui_options | parent_ui_options
|
|
994
1080
|
return ui_options
|
|
995
1081
|
|
|
996
1082
|
@ui_options.setter
|
|
@@ -335,7 +335,7 @@ class BaseNode(ABC):
|
|
|
335
335
|
msg = f"Failed to add Parameter `{param.name}`. Parameter names cannot currently any whitespace characters. Please see https://github.com/griptape-ai/griptape-nodes/issues/714 to check the status on a remedy for this issue."
|
|
336
336
|
raise ValueError(msg)
|
|
337
337
|
if self.does_name_exist(param.name):
|
|
338
|
-
msg = "Cannot have duplicate names on parameters."
|
|
338
|
+
msg = f"Cannot have duplicate names on parameters. Encountered two instances of '{param.name}'."
|
|
339
339
|
raise ValueError(msg)
|
|
340
340
|
self.add_node_element(param)
|
|
341
341
|
self._emit_parameter_lifecycle_event(param)
|
|
@@ -1254,8 +1254,10 @@ class SuccessFailureNode(BaseNode):
|
|
|
1254
1254
|
|
|
1255
1255
|
def _create_status_parameters(
|
|
1256
1256
|
self,
|
|
1257
|
+
*,
|
|
1257
1258
|
result_details_tooltip: str = "Details about the operation result",
|
|
1258
1259
|
result_details_placeholder: str = "Details on the operation will be presented here.",
|
|
1260
|
+
parameter_group_initially_collapsed: bool = True,
|
|
1259
1261
|
) -> None:
|
|
1260
1262
|
"""Create and add standard status output parameters in a collapsible group.
|
|
1261
1263
|
|
|
@@ -1270,13 +1272,14 @@ class SuccessFailureNode(BaseNode):
|
|
|
1270
1272
|
Args:
|
|
1271
1273
|
result_details_tooltip: Custom tooltip for result_details parameter
|
|
1272
1274
|
result_details_placeholder: Custom placeholder text for result_details parameter
|
|
1275
|
+
parameter_group_initially_collapsed: Whether the Status group should start collapsed
|
|
1273
1276
|
"""
|
|
1274
1277
|
# Create status component with OUTPUT modes for SuccessFailureNode
|
|
1275
1278
|
self.status_component = ExecutionStatusComponent(
|
|
1276
1279
|
self,
|
|
1277
1280
|
was_successful_modes={ParameterMode.OUTPUT},
|
|
1278
1281
|
result_details_modes={ParameterMode.OUTPUT},
|
|
1279
|
-
parameter_group_initially_collapsed=
|
|
1282
|
+
parameter_group_initially_collapsed=parameter_group_initially_collapsed,
|
|
1280
1283
|
result_details_tooltip=result_details_tooltip,
|
|
1281
1284
|
result_details_placeholder=result_details_placeholder,
|
|
1282
1285
|
)
|
{griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/machines/parallel_resolution.py
RENAMED
|
@@ -16,11 +16,13 @@ from griptape_nodes.retained_mode.events.base_events import (
|
|
|
16
16
|
ExecutionGriptapeNodeEvent,
|
|
17
17
|
)
|
|
18
18
|
from griptape_nodes.retained_mode.events.execution_events import (
|
|
19
|
+
CurrentControlNodeEvent,
|
|
19
20
|
CurrentDataNodeEvent,
|
|
20
21
|
NodeResolvedEvent,
|
|
21
22
|
ParameterValueUpdateEvent,
|
|
22
23
|
)
|
|
23
24
|
from griptape_nodes.retained_mode.events.parameter_events import SetParameterValueRequest
|
|
25
|
+
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
24
26
|
|
|
25
27
|
if TYPE_CHECKING:
|
|
26
28
|
from griptape_nodes.common.directed_graph import DirectedGraph
|
|
@@ -103,7 +105,7 @@ class ExecuteDagState(State):
|
|
|
103
105
|
current_node = done_node.node_reference
|
|
104
106
|
|
|
105
107
|
# Check if node was already resolved (shouldn't happen)
|
|
106
|
-
if current_node.state == NodeResolutionState.RESOLVED:
|
|
108
|
+
if current_node.state == NodeResolutionState.RESOLVED and not current_node.lock:
|
|
107
109
|
logger.error(
|
|
108
110
|
"DUPLICATE COMPLETION DETECTED: Node '%s' was already RESOLVED but handle_done_nodes was called again from network '%s'. This should not happen!",
|
|
109
111
|
current_node.name,
|
|
@@ -129,7 +131,6 @@ class ExecuteDagState(State):
|
|
|
129
131
|
data_type = parameter.type
|
|
130
132
|
if data_type is None:
|
|
131
133
|
data_type = ParameterTypeBuiltin.NONE.value
|
|
132
|
-
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
133
134
|
|
|
134
135
|
await GriptapeNodes.EventManager().aput_event(
|
|
135
136
|
ExecutionGriptapeNodeEvent(
|
|
@@ -149,7 +150,6 @@ class ExecuteDagState(State):
|
|
|
149
150
|
library_name = library[0]
|
|
150
151
|
else:
|
|
151
152
|
library_name = None
|
|
152
|
-
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
153
153
|
|
|
154
154
|
await GriptapeNodes.EventManager().aput_event(
|
|
155
155
|
ExecutionGriptapeNodeEvent(
|
|
@@ -169,8 +169,6 @@ class ExecuteDagState(State):
|
|
|
169
169
|
@staticmethod
|
|
170
170
|
def get_next_control_graph(context: ParallelResolutionContext, node: BaseNode, network_name: str) -> None:
|
|
171
171
|
"""Get next control flow nodes and add them to the DAG graph."""
|
|
172
|
-
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
173
|
-
|
|
174
172
|
flow_manager = GriptapeNodes.FlowManager()
|
|
175
173
|
|
|
176
174
|
# Early returns for various conditions
|
|
@@ -224,7 +222,11 @@ class ExecuteDagState(State):
|
|
|
224
222
|
}
|
|
225
223
|
)
|
|
226
224
|
)
|
|
227
|
-
|
|
225
|
+
GriptapeNodes.EventManager().put_event(
|
|
226
|
+
ExecutionGriptapeNodeEvent(
|
|
227
|
+
wrapped_event=ExecutionEvent(payload=CurrentControlNodeEvent(node_name=next_node.name))
|
|
228
|
+
)
|
|
229
|
+
)
|
|
228
230
|
ExecuteDagState._add_and_queue_nodes(context, next_node, network_name)
|
|
229
231
|
|
|
230
232
|
@staticmethod
|
|
@@ -270,8 +272,6 @@ class ExecuteDagState(State):
|
|
|
270
272
|
Args:
|
|
271
273
|
node_reference (DagOrchestrator.DagNode): The node to collect values for.
|
|
272
274
|
"""
|
|
273
|
-
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
274
|
-
|
|
275
275
|
current_node = node_reference.node_reference
|
|
276
276
|
connections = GriptapeNodes.FlowManager().get_connections()
|
|
277
277
|
|
|
@@ -447,16 +447,22 @@ class ExecuteDagState(State):
|
|
|
447
447
|
node_reference.node_reference.state = NodeResolutionState.RESOLVING
|
|
448
448
|
|
|
449
449
|
# Send an event that this is a current data node:
|
|
450
|
-
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
451
450
|
|
|
452
451
|
await GriptapeNodes.EventManager().aput_event(
|
|
453
452
|
ExecutionGriptapeNodeEvent(wrapped_event=ExecutionEvent(payload=CurrentDataNodeEvent(node_name=node)))
|
|
454
453
|
)
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
454
|
+
|
|
455
|
+
# Wait for a task to finish - only if there are tasks running
|
|
456
|
+
if context.task_to_node:
|
|
457
|
+
done, _ = await asyncio.wait(context.task_to_node.keys(), return_when=asyncio.FIRST_COMPLETED)
|
|
458
|
+
# Check for task exceptions and handle them properly
|
|
459
|
+
for task in done:
|
|
460
|
+
if task.exception():
|
|
461
|
+
# Get the actual exception and re-raise it
|
|
462
|
+
exc = task.exception()
|
|
463
|
+
context.task_to_node.pop(task)
|
|
464
|
+
raise RuntimeError(exc)
|
|
465
|
+
context.task_to_node.pop(task)
|
|
460
466
|
# Once a task has finished, loop back to the top.
|
|
461
467
|
await ExecuteDagState.pop_done_states(context)
|
|
462
468
|
# Remove all nodes that are done
|
|
@@ -538,8 +544,6 @@ class ParallelResolutionMachine(FSM[ParallelResolutionContext]):
|
|
|
538
544
|
|
|
539
545
|
async def resolve_node(self, node: BaseNode | None = None) -> None: # noqa: ARG002
|
|
540
546
|
"""Execute the DAG structure using the existing DagBuilder."""
|
|
541
|
-
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
542
|
-
|
|
543
547
|
if self.context.dag_builder is None:
|
|
544
548
|
self.context.dag_builder = GriptapeNodes.FlowManager().global_dag_builder
|
|
545
549
|
await self.start(ExecuteDagState)
|
{griptape_nodes-0.54.1 → griptape_nodes-0.55.1}/src/griptape_nodes/node_library/library_registry.py
RENAMED
|
@@ -69,6 +69,7 @@ class CategoryDefinition(BaseModel):
|
|
|
69
69
|
description: str
|
|
70
70
|
color: str
|
|
71
71
|
icon: str
|
|
72
|
+
group: str | None = None
|
|
72
73
|
|
|
73
74
|
|
|
74
75
|
class NodeDefinition(BaseModel):
|
|
@@ -179,10 +180,6 @@ class LibraryRegistry(metaclass=SingletonMeta):
|
|
|
179
180
|
logger.error(details)
|
|
180
181
|
return details
|
|
181
182
|
|
|
182
|
-
details = f"When registering Node class '{node_class_name}', Nodes with the same class name were already registered from the following Libraries: '{library_collisions}'. This is a collision. If you want to use this Node, you will need to specify the Library name in addition to the Node class name so that it can be disambiguated."
|
|
183
|
-
logger.warning(details)
|
|
184
|
-
return details
|
|
185
|
-
|
|
186
183
|
return None
|
|
187
184
|
|
|
188
185
|
@classmethod
|
|
@@ -225,10 +225,12 @@ class GetFlowStateResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
|
225
225
|
Args:
|
|
226
226
|
control_node: Name of the current control node (if any)
|
|
227
227
|
resolving_node: Name of the node currently being resolved (if any)
|
|
228
|
+
involved_nodes: Names of nodes that are queued to be executed or have been executed in the current run.
|
|
228
229
|
"""
|
|
229
230
|
|
|
230
231
|
control_nodes: list[str] | None
|
|
231
232
|
resolving_node: list[str] | None
|
|
233
|
+
involved_nodes: list[str] | None
|
|
232
234
|
|
|
233
235
|
|
|
234
236
|
@dataclass
|
|
@@ -1090,14 +1090,17 @@ class FlowManager:
|
|
|
1090
1090
|
details = f"Could not get flow state. Error: {err}"
|
|
1091
1091
|
return GetFlowStateResultFailure(result_details=details)
|
|
1092
1092
|
try:
|
|
1093
|
-
control_nodes, resolving_nodes = self.flow_state(flow)
|
|
1093
|
+
control_nodes, resolving_nodes, involved_nodes = self.flow_state(flow)
|
|
1094
1094
|
except Exception as e:
|
|
1095
1095
|
details = f"Failed to get flow state of flow with name {flow_name}. Exception occurred: {e} "
|
|
1096
1096
|
logger.exception(details)
|
|
1097
1097
|
return GetFlowStateResultFailure(result_details=details)
|
|
1098
1098
|
details = f"Successfully got flow state for flow with name {flow_name}."
|
|
1099
1099
|
return GetFlowStateResultSuccess(
|
|
1100
|
-
control_nodes=control_nodes,
|
|
1100
|
+
control_nodes=control_nodes,
|
|
1101
|
+
resolving_node=resolving_nodes,
|
|
1102
|
+
result_details=details,
|
|
1103
|
+
involved_nodes=involved_nodes,
|
|
1101
1104
|
)
|
|
1102
1105
|
|
|
1103
1106
|
def on_cancel_flow_request(self, request: CancelFlowRequest) -> ResultPayload:
|
|
@@ -1713,28 +1716,27 @@ class FlowManager:
|
|
|
1713
1716
|
await machine.start_flow(start_node, debug_mode)
|
|
1714
1717
|
|
|
1715
1718
|
async def resolve_singular_node(self, flow: ControlFlow, node: BaseNode, *, debug_mode: bool = False) -> None:
|
|
1716
|
-
#
|
|
1719
|
+
# We are now going to have different behavior depending on how the node is behaving.
|
|
1717
1720
|
if self.check_for_existing_running_flow():
|
|
1718
|
-
#
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
resolution_machine.
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
self._global_control_flow_machine.context.current_nodes = []
|
|
1721
|
+
# Now we know something is running, it's ParallelResolutionMachine, and that we are in single_node_resolution.
|
|
1722
|
+
self._global_dag_builder.add_node_with_dependencies(node, node.name)
|
|
1723
|
+
else:
|
|
1724
|
+
# Set that we are only working on one node right now!
|
|
1725
|
+
self._global_single_node_resolution = True
|
|
1726
|
+
# Get or create machine
|
|
1727
|
+
self._global_control_flow_machine = ControlFlowMachine(flow.name)
|
|
1728
|
+
self._global_control_flow_machine.context.current_nodes = [node]
|
|
1729
|
+
resolution_machine = self._global_control_flow_machine.resolution_machine
|
|
1730
|
+
resolution_machine.change_debug_mode(debug_mode=debug_mode)
|
|
1731
|
+
node.state = NodeResolutionState.UNRESOLVED
|
|
1732
|
+
# Build the DAG for the node
|
|
1733
|
+
if isinstance(resolution_machine, ParallelResolutionMachine):
|
|
1734
|
+
self._global_dag_builder.add_node_with_dependencies(node)
|
|
1735
|
+
resolution_machine.context.dag_builder = self._global_dag_builder
|
|
1736
|
+
await resolution_machine.resolve_node(node)
|
|
1737
|
+
if resolution_machine.is_complete():
|
|
1738
|
+
self._global_single_node_resolution = False
|
|
1739
|
+
self._global_control_flow_machine.context.current_nodes = []
|
|
1738
1740
|
|
|
1739
1741
|
async def single_execution_step(self, flow: ControlFlow, change_debug_mode: bool) -> None: # noqa: FBT001
|
|
1740
1742
|
# do a granular step
|
|
@@ -1792,12 +1794,12 @@ class FlowManager:
|
|
|
1792
1794
|
# Clear entry control parameter for new execution
|
|
1793
1795
|
node.set_entry_control_parameter(None)
|
|
1794
1796
|
|
|
1795
|
-
def flow_state(self, flow: ControlFlow) -> tuple[list[str] | None, list[str] | None]: # noqa: ARG002
|
|
1797
|
+
def flow_state(self, flow: ControlFlow) -> tuple[list[str] | None, list[str] | None, list[str] | None]: # noqa: ARG002
|
|
1796
1798
|
if not self.check_for_existing_running_flow():
|
|
1797
1799
|
msg = "Flow hasn't started."
|
|
1798
1800
|
raise RuntimeError(msg)
|
|
1799
1801
|
if self._global_control_flow_machine is None:
|
|
1800
|
-
return None, None
|
|
1802
|
+
return None, None, None
|
|
1801
1803
|
control_flow_context = self._global_control_flow_machine.context
|
|
1802
1804
|
current_control_nodes = (
|
|
1803
1805
|
[control_flow_node.name for control_flow_node in control_flow_context.current_nodes]
|
|
@@ -1810,12 +1812,13 @@ class FlowManager:
|
|
|
1810
1812
|
node.node_reference.name
|
|
1811
1813
|
for node in control_flow_context.resolution_machine.context.task_to_node.values()
|
|
1812
1814
|
]
|
|
1813
|
-
|
|
1815
|
+
involved_nodes = list(self._global_dag_builder.node_to_reference.keys())
|
|
1816
|
+
return current_control_nodes, current_resolving_nodes, involved_nodes if len(involved_nodes) != 0 else None
|
|
1814
1817
|
if isinstance(control_flow_context.resolution_machine, SequentialResolutionMachine):
|
|
1815
1818
|
focus_stack_for_node = control_flow_context.resolution_machine.context.focus_stack
|
|
1816
1819
|
current_resolving_node = focus_stack_for_node[-1].node.name if len(focus_stack_for_node) else None
|
|
1817
|
-
return current_control_nodes, [current_resolving_node] if current_resolving_node else None
|
|
1818
|
-
return current_control_nodes, None
|
|
1820
|
+
return current_control_nodes, [current_resolving_node] if current_resolving_node else None, None
|
|
1821
|
+
return current_control_nodes, None, None
|
|
1819
1822
|
|
|
1820
1823
|
def get_start_node_from_node(self, flow: ControlFlow, node: BaseNode) -> BaseNode | None:
|
|
1821
1824
|
# backwards chain in control outputs.
|
|
@@ -116,6 +116,7 @@ console = Console()
|
|
|
116
116
|
|
|
117
117
|
class LibraryManager:
|
|
118
118
|
SANDBOX_LIBRARY_NAME = "Sandbox Library"
|
|
119
|
+
LIBRARY_CONFIG_FILENAME = "griptape_nodes_library.json"
|
|
119
120
|
|
|
120
121
|
@dataclass
|
|
121
122
|
class LibraryInfo:
|
|
@@ -480,24 +481,18 @@ class LibraryManager:
|
|
|
480
481
|
successful_libraries = []
|
|
481
482
|
failed_libraries = []
|
|
482
483
|
|
|
483
|
-
#
|
|
484
|
-
|
|
485
|
-
user_libraries_section = "app_events.on_app_initialization_complete.libraries_to_register"
|
|
486
|
-
libraries_to_register: list[str] = config_mgr.get_config_value(user_libraries_section)
|
|
484
|
+
# Discover library files for metadata loading
|
|
485
|
+
library_files = self._discover_library_files()
|
|
487
486
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
metadata_request = LoadLibraryMetadataFromFileRequest(file_path=library_to_register)
|
|
493
|
-
metadata_result = self.load_library_metadata_from_file_request(metadata_request)
|
|
487
|
+
# Load metadata for all discovered library files
|
|
488
|
+
for library_file in library_files:
|
|
489
|
+
metadata_request = LoadLibraryMetadataFromFileRequest(file_path=str(library_file))
|
|
490
|
+
metadata_result = self.load_library_metadata_from_file_request(metadata_request)
|
|
494
491
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
# Note: We skip requirement specifier libraries (non-.json) as they don't have
|
|
500
|
-
# JSON files we can load metadata from without installation
|
|
492
|
+
if isinstance(metadata_result, LoadLibraryMetadataFromFileResultSuccess):
|
|
493
|
+
successful_libraries.append(metadata_result)
|
|
494
|
+
else:
|
|
495
|
+
failed_libraries.append(cast("LoadLibraryMetadataFromFileResultFailure", metadata_result))
|
|
501
496
|
|
|
502
497
|
# Generate sandbox library metadata
|
|
503
498
|
sandbox_result = self._generate_sandbox_library_metadata()
|
|
@@ -1504,8 +1499,6 @@ class LibraryManager:
|
|
|
1504
1499
|
return node_class
|
|
1505
1500
|
|
|
1506
1501
|
async def load_all_libraries_from_config(self) -> None:
|
|
1507
|
-
# Comment out lines 1503-1545 and call the _load libraries from provenance system to test the other functionality.
|
|
1508
|
-
|
|
1509
1502
|
# Load metadata for all libraries to determine which ones can be safely loaded
|
|
1510
1503
|
metadata_request = LoadMetadataForAllLibrariesRequest()
|
|
1511
1504
|
metadata_result = self.load_metadata_for_all_libraries_request(metadata_request)
|
|
@@ -1525,9 +1518,6 @@ class LibraryManager:
|
|
|
1525
1518
|
)
|
|
1526
1519
|
|
|
1527
1520
|
# Use metadata results to selectively load libraries
|
|
1528
|
-
user_libraries_section = "app_events.on_app_initialization_complete.libraries_to_register"
|
|
1529
|
-
|
|
1530
|
-
# Load libraries that had successful metadata loading
|
|
1531
1521
|
for library_result in metadata_result.successful_libraries:
|
|
1532
1522
|
if library_result.library_schema.name == LibraryManager.SANDBOX_LIBRARY_NAME:
|
|
1533
1523
|
# Handle sandbox library - use the schema we already have
|
|
@@ -1543,7 +1533,7 @@ class LibraryManager:
|
|
|
1543
1533
|
if isinstance(register_result, RegisterLibraryFromFileResultFailure):
|
|
1544
1534
|
# Registration failed - the failure info is already recorded in _library_file_path_to_info
|
|
1545
1535
|
# by register_library_from_file_request, so we just log it here for visibility
|
|
1546
|
-
logger.warning(
|
|
1536
|
+
logger.warning("Failed to register library from %s", library_result.file_path)
|
|
1547
1537
|
|
|
1548
1538
|
# Print 'em all pretty
|
|
1549
1539
|
self.print_library_load_status()
|
|
@@ -2041,3 +2031,42 @@ class LibraryManager:
|
|
|
2041
2031
|
"Successfully reloaded all libraries. All object state was cleared and previous libraries were unloaded."
|
|
2042
2032
|
)
|
|
2043
2033
|
return ReloadAllLibrariesResultSuccess(result_details=ResultDetails(message=details, level=logging.INFO))
|
|
2034
|
+
|
|
2035
|
+
def _discover_library_files(self) -> list[Path]:
|
|
2036
|
+
"""Discover library JSON files from config and workspace recursively.
|
|
2037
|
+
|
|
2038
|
+
Returns:
|
|
2039
|
+
List of library file paths found
|
|
2040
|
+
"""
|
|
2041
|
+
config_mgr = GriptapeNodes.ConfigManager()
|
|
2042
|
+
user_libraries_section = "app_events.on_app_initialization_complete.libraries_to_register"
|
|
2043
|
+
|
|
2044
|
+
libraries_to_process = []
|
|
2045
|
+
|
|
2046
|
+
# Add from config
|
|
2047
|
+
config_libraries = config_mgr.get_config_value(user_libraries_section, default=[])
|
|
2048
|
+
libraries_to_process.extend(config_libraries)
|
|
2049
|
+
|
|
2050
|
+
# Add from workspace - recursive discovery of library JSON files
|
|
2051
|
+
workspace_path = config_mgr.workspace_path
|
|
2052
|
+
libraries_to_process.append(str(workspace_path))
|
|
2053
|
+
|
|
2054
|
+
library_files = []
|
|
2055
|
+
|
|
2056
|
+
def process_path(path: Path) -> None:
|
|
2057
|
+
"""Process a path, handling both files and directories."""
|
|
2058
|
+
if path.is_dir():
|
|
2059
|
+
# Process all library JSON files recursively in the directory
|
|
2060
|
+
library_files.extend(path.rglob(LibraryManager.LIBRARY_CONFIG_FILENAME))
|
|
2061
|
+
elif path.suffix == ".json":
|
|
2062
|
+
library_files.append(path)
|
|
2063
|
+
|
|
2064
|
+
# Process library paths
|
|
2065
|
+
for library_to_process in libraries_to_process:
|
|
2066
|
+
library_path = Path(library_to_process)
|
|
2067
|
+
|
|
2068
|
+
# Handle library config files and directories only (skip requirement specifiers)
|
|
2069
|
+
if library_path.exists():
|
|
2070
|
+
process_path(library_path)
|
|
2071
|
+
|
|
2072
|
+
return library_files
|
|
@@ -22,6 +22,7 @@ from griptape_nodes.exe_types.node_types import (
|
|
|
22
22
|
StartLoopNode,
|
|
23
23
|
)
|
|
24
24
|
from griptape_nodes.exe_types.type_validator import TypeValidator
|
|
25
|
+
from griptape_nodes.machines.sequential_resolution import SequentialResolutionMachine
|
|
25
26
|
from griptape_nodes.node_library.library_registry import LibraryNameAndVersion, LibraryRegistry
|
|
26
27
|
from griptape_nodes.retained_mode.events.base_events import (
|
|
27
28
|
ResultDetails,
|
|
@@ -445,7 +446,7 @@ class NodeManager:
|
|
|
445
446
|
# get the current node executing / resolving
|
|
446
447
|
# if it's in connected nodes, cancel flow.
|
|
447
448
|
# otherwise, leave it.
|
|
448
|
-
control_node_names, resolving_node_names = GriptapeNodes.FlowManager().flow_state(parent_flow)
|
|
449
|
+
control_node_names, resolving_node_names, _ = GriptapeNodes.FlowManager().flow_state(parent_flow)
|
|
449
450
|
connected_nodes = parent_flow.get_all_connected_nodes(node)
|
|
450
451
|
cancelled = False
|
|
451
452
|
if control_node_names is not None:
|
|
@@ -1856,9 +1857,28 @@ class NodeManager:
|
|
|
1856
1857
|
if flow is None:
|
|
1857
1858
|
details = f'Failed to fetch parent flow for "{node_name}"'
|
|
1858
1859
|
return ResolveNodeResultFailure(validation_exceptions=[], result_details=details)
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1860
|
+
|
|
1861
|
+
# Check for existing running flow
|
|
1862
|
+
flow_mgr = GriptapeNodes.FlowManager()
|
|
1863
|
+
if flow_mgr.check_for_existing_running_flow():
|
|
1864
|
+
# Behavior should stay the same for sequential flows.
|
|
1865
|
+
if flow_mgr._global_control_flow_machine and isinstance(
|
|
1866
|
+
flow_mgr._global_control_flow_machine.resolution_machine, SequentialResolutionMachine
|
|
1867
|
+
):
|
|
1868
|
+
errormsg = f"This workflow is already in progress. Please wait for the current process to finish before starting {node.name} again."
|
|
1869
|
+
return ResolveNodeResultFailure(validation_exceptions=[RuntimeError(errormsg)], result_details=errormsg)
|
|
1870
|
+
# Behavior should also match if the flow running is a Control Flow, and not a singular node resolution.
|
|
1871
|
+
if not flow_mgr._global_single_node_resolution:
|
|
1872
|
+
errormsg = f"This workflow is already in progress. Please wait for the current control process to finish before starting {node.name} again."
|
|
1873
|
+
return ResolveNodeResultFailure(validation_exceptions=[RuntimeError(errormsg)], result_details=errormsg)
|
|
1874
|
+
|
|
1875
|
+
# Check if the node is already in the DAG - if so, skip this resolution. It's already queued or has been resolved.
|
|
1876
|
+
if node.name in flow_mgr._global_dag_builder.node_to_reference:
|
|
1877
|
+
logger.error("Node %s is already executing. Cannot start execution.", node.name)
|
|
1878
|
+
return ResolveNodeResultFailure(
|
|
1879
|
+
validation_exceptions=[],
|
|
1880
|
+
result_details=f"Node {node.name} is already executing. Cannot start execution.",
|
|
1881
|
+
)
|
|
1862
1882
|
try:
|
|
1863
1883
|
GriptapeNodes.FlowManager().get_connections().unresolve_future_nodes(node)
|
|
1864
1884
|
except Exception as e:
|