griptape-nodes 0.55.1__tar.gz → 0.56.0__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.55.1 → griptape_nodes-0.56.0}/PKG-INFO +1 -1
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/pyproject.toml +1 -1
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/cli/commands/init.py +88 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/cli/commands/models.py +2 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/cli/shared.py +1 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/exe_types/core_types.py +104 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/exe_types/node_types.py +9 -12
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/machines/control_flow.py +10 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/machines/dag_builder.py +21 -2
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/machines/parallel_resolution.py +25 -10
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/node_library/workflow_registry.py +73 -3
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/execution_events.py +12 -2
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/flow_events.py +58 -0
- griptape_nodes-0.56.0/src/griptape_nodes/retained_mode/events/resource_events.py +290 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/workflow_events.py +57 -2
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/griptape_nodes.py +9 -1
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/flow_manager.py +678 -12
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/library_manager.py +13 -19
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/model_manager.py +184 -83
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/node_manager.py +3 -3
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/os_manager.py +118 -1
- griptape_nodes-0.56.0/src/griptape_nodes/retained_mode/managers/resource_components/__init__.py +1 -0
- griptape_nodes-0.56.0/src/griptape_nodes/retained_mode/managers/resource_components/capability_field.py +41 -0
- griptape_nodes-0.56.0/src/griptape_nodes/retained_mode/managers/resource_components/comparator.py +18 -0
- griptape_nodes-0.56.0/src/griptape_nodes/retained_mode/managers/resource_components/resource_instance.py +236 -0
- griptape_nodes-0.56.0/src/griptape_nodes/retained_mode/managers/resource_components/resource_type.py +79 -0
- griptape_nodes-0.56.0/src/griptape_nodes/retained_mode/managers/resource_manager.py +306 -0
- griptape_nodes-0.56.0/src/griptape_nodes/retained_mode/managers/resource_types/__init__.py +1 -0
- griptape_nodes-0.56.0/src/griptape_nodes/retained_mode/managers/resource_types/cpu_resource.py +108 -0
- griptape_nodes-0.56.0/src/griptape_nodes/retained_mode/managers/resource_types/os_resource.py +87 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/settings.py +5 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/sync_manager.py +10 -3
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/workflow_manager.py +359 -261
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/README.md +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/__main__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/app/.python-version +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/app/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/app/app.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/app/watch.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/bootstrap/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/bootstrap/workflow_executors/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/bootstrap/workflow_executors/local_workflow_executor.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/bootstrap/workflow_executors/workflow_executor.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/cli/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/cli/commands/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/cli/commands/config.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/cli/commands/engine.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/cli/commands/libraries.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/cli/commands/self.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/cli/main.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/common/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/common/directed_graph.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/drivers/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/drivers/storage/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/drivers/storage/base_storage_driver.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/drivers/storage/griptape_cloud_storage_driver.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/drivers/storage/local_storage_driver.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/drivers/storage/storage_backend.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/exe_types/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/exe_types/connections.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/exe_types/flow.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/exe_types/param_components/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/exe_types/param_components/execution_status_component.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/exe_types/type_validator.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/machines/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/machines/fsm.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/machines/sequential_resolution.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/mcp_server/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/node_library/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/node_library/advanced_node_library.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/node_library/library_registry.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/py.typed +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/agent_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/app_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/arbitrary_python_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/base_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/config_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/connection_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/context_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/generate_request_payload_schemas.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/library_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/logger_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/model_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/node_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/object_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/os_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/parameter_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/payload_registry.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/secrets_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/static_file_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/sync_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/validation_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/events/variable_events.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/agent_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/config_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/context_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/engine_identity_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/event_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/data_models.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_directory.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_fsm.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/base.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/github.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/local_file.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/package.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/sandbox.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_status.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/object_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/operation_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/secrets_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/session_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/static_files_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/variable_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/managers/version_compatibility_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/retained_mode.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/utils/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/utils/engine_identity.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/utils/name_generator.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/retained_mode/variable_types.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/servers/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/servers/mcp.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/servers/static.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/servers/ws_request_manager.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/add_param_button.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/button.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/clamp.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/color_picker.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/compare.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/compare_images.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/file_system_picker.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/minmax.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/multi_options.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/numbers_selector.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/options.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/slider.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/trait_registry.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/traits/traits.json +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/updater/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/updater/__main__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/utils/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/utils/async_utils.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/utils/dict_utils.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/utils/image_preview.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/utils/metaclasses.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/utils/uv_utils.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/utils/version_utils.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/version_compatibility/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/version_compatibility/versions/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/version_compatibility/versions/v0_39_0/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/version_compatibility/versions/v0_39_0/modified_parameters_set_removal.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/version_compatibility/workflow_versions/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/version_compatibility/workflow_versions/v0_7_0/__init__.py +0 -0
- {griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/version_compatibility/workflow_versions/v0_7_0/local_executor_argument_addition.py +0 -0
|
@@ -55,6 +55,10 @@ def init_command( # noqa: PLR0913
|
|
|
55
55
|
bool,
|
|
56
56
|
typer.Option(help="Run init in non-interactive mode (no prompts)."),
|
|
57
57
|
] = False,
|
|
58
|
+
hf_token: Annotated[
|
|
59
|
+
str | None,
|
|
60
|
+
typer.Option(help="Set the Hugging Face token for downloading gated models."),
|
|
61
|
+
] = None,
|
|
58
62
|
config: Annotated[
|
|
59
63
|
list[str] | None,
|
|
60
64
|
typer.Option(
|
|
@@ -83,6 +87,7 @@ def init_command( # noqa: PLR0913
|
|
|
83
87
|
secret_values=secret_values,
|
|
84
88
|
libraries_sync=libraries_sync,
|
|
85
89
|
bucket_name=bucket_name,
|
|
90
|
+
hf_token=hf_token,
|
|
86
91
|
)
|
|
87
92
|
)
|
|
88
93
|
|
|
@@ -128,6 +133,7 @@ def _run_init_configuration(config: InitConfig) -> None:
|
|
|
128
133
|
_handle_workspace_config(config)
|
|
129
134
|
_handle_storage_backend_config(config)
|
|
130
135
|
_handle_bucket_config(config)
|
|
136
|
+
_handle_hf_token_config(config)
|
|
131
137
|
_handle_advanced_library_config(config)
|
|
132
138
|
_handle_arbitrary_configs(config)
|
|
133
139
|
|
|
@@ -193,6 +199,25 @@ def _handle_bucket_config(config: InitConfig) -> str | None:
|
|
|
193
199
|
return bucket_id
|
|
194
200
|
|
|
195
201
|
|
|
202
|
+
def _handle_hf_token_config(config: InitConfig) -> str | None:
|
|
203
|
+
"""Handle Hugging Face token configuration step."""
|
|
204
|
+
hf_token = None
|
|
205
|
+
|
|
206
|
+
if config.interactive:
|
|
207
|
+
# First ask if they want to configure an HF token
|
|
208
|
+
configure_hf_token = _prompt_for_hf_token_configuration()
|
|
209
|
+
if configure_hf_token:
|
|
210
|
+
hf_token = _prompt_for_hf_token(default_hf_token=config.hf_token)
|
|
211
|
+
elif config.hf_token is not None:
|
|
212
|
+
hf_token = config.hf_token
|
|
213
|
+
|
|
214
|
+
if hf_token is not None:
|
|
215
|
+
secrets_manager.set_secret("HF_TOKEN", hf_token)
|
|
216
|
+
console.print("[bold green]Hugging Face token set[/bold green]")
|
|
217
|
+
|
|
218
|
+
return hf_token
|
|
219
|
+
|
|
220
|
+
|
|
196
221
|
def _handle_advanced_library_config(config: InitConfig) -> bool | None:
|
|
197
222
|
"""Handle advanced library configuration step."""
|
|
198
223
|
register_advanced_library = config.register_advanced_library
|
|
@@ -513,6 +538,69 @@ def _create_new_bucket(bucket_name: str) -> str:
|
|
|
513
538
|
return bucket_id
|
|
514
539
|
|
|
515
540
|
|
|
541
|
+
def _prompt_for_hf_token_configuration() -> bool:
|
|
542
|
+
"""Prompts the user whether to configure a Hugging Face token."""
|
|
543
|
+
# Check if there's already an HF token configured
|
|
544
|
+
current_hf_token = secrets_manager.get_secret("HF_TOKEN", should_error_on_not_found=False)
|
|
545
|
+
|
|
546
|
+
if current_hf_token:
|
|
547
|
+
explainer = """[bold cyan]Hugging Face Token Configuration[/bold cyan]
|
|
548
|
+
You currently have a Hugging Face token configured.
|
|
549
|
+
|
|
550
|
+
Hugging Face tokens are used to access gated models from the Hugging Face Hub, such as:
|
|
551
|
+
- Meta's Llama models
|
|
552
|
+
- black-forest-labs/FLUX.1-dev
|
|
553
|
+
- Other restricted or premium models
|
|
554
|
+
|
|
555
|
+
Would you like to update your Hugging Face token or keep the current one?"""
|
|
556
|
+
prompt_text = "Update Hugging Face token?"
|
|
557
|
+
default_value = False
|
|
558
|
+
else:
|
|
559
|
+
explainer = """[bold cyan]Hugging Face Token Configuration[/bold cyan]
|
|
560
|
+
Would you like to configure a Hugging Face token?
|
|
561
|
+
|
|
562
|
+
Hugging Face tokens are used by the model manager to download gated models from the Hugging Face Hub, such as:
|
|
563
|
+
- Meta's Llama models
|
|
564
|
+
- black-forest-labs/FLUX.1-dev
|
|
565
|
+
- Other restricted or premium models
|
|
566
|
+
|
|
567
|
+
If you don't plan to use gated models, you can skip this step.
|
|
568
|
+
You can get a token from https://huggingface.co/settings/tokens
|
|
569
|
+
|
|
570
|
+
You can always configure a token later by running the initialization process again."""
|
|
571
|
+
prompt_text = "Configure Hugging Face token?"
|
|
572
|
+
default_value = False
|
|
573
|
+
|
|
574
|
+
console.print(Panel(explainer, expand=False))
|
|
575
|
+
return Confirm.ask(prompt_text, default=default_value)
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
def _prompt_for_hf_token(default_hf_token: str | None = None) -> str | None:
|
|
579
|
+
"""Prompts the user for their Hugging Face token."""
|
|
580
|
+
if default_hf_token is None:
|
|
581
|
+
default_hf_token = secrets_manager.get_secret("HF_TOKEN", should_error_on_not_found=False)
|
|
582
|
+
|
|
583
|
+
explainer = """[bold cyan]Hugging Face Token[/bold cyan]
|
|
584
|
+
Please enter your Hugging Face token to enable downloading of gated models.
|
|
585
|
+
|
|
586
|
+
To get a token:
|
|
587
|
+
1. Go to https://huggingface.co/settings/tokens
|
|
588
|
+
2. Create a new token with 'Read' permissions
|
|
589
|
+
3. Copy and paste the token here
|
|
590
|
+
|
|
591
|
+
You can leave this blank to skip token configuration."""
|
|
592
|
+
console.print(Panel(explainer, expand=False))
|
|
593
|
+
|
|
594
|
+
hf_token = Prompt.ask(
|
|
595
|
+
"Hugging Face Token (optional)",
|
|
596
|
+
default=default_hf_token or "",
|
|
597
|
+
show_default=False,
|
|
598
|
+
)
|
|
599
|
+
|
|
600
|
+
# Return None if empty string
|
|
601
|
+
return hf_token if hf_token.strip() else None
|
|
602
|
+
|
|
603
|
+
|
|
516
604
|
def _parse_key_value_pairs(pairs: list[str] | None) -> dict[str, Any] | None:
|
|
517
605
|
"""Parse key=value pairs from a list of strings.
|
|
518
606
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Models command for managing AI models."""
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
import sys
|
|
4
5
|
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
import typer
|
|
@@ -130,6 +131,7 @@ async def _download_model(
|
|
|
130
131
|
except Exception as e:
|
|
131
132
|
console.print("[bold red]Model download failed:[/bold red]")
|
|
132
133
|
console.print(f"[red]{e}[/red]")
|
|
134
|
+
sys.exit(1)
|
|
133
135
|
|
|
134
136
|
|
|
135
137
|
async def _list_models() -> None:
|
|
@@ -1483,12 +1483,23 @@ class ParameterList(ParameterContainer):
|
|
|
1483
1483
|
user_defined: bool = False,
|
|
1484
1484
|
element_id: str | None = None,
|
|
1485
1485
|
element_type: str | None = None,
|
|
1486
|
+
# UI convenience parameters
|
|
1487
|
+
collapsed: bool | None = None,
|
|
1488
|
+
child_prefix: str | None = None,
|
|
1489
|
+
grid: bool | None = None,
|
|
1490
|
+
grid_columns: int | None = None,
|
|
1486
1491
|
):
|
|
1487
1492
|
if traits:
|
|
1488
1493
|
self._original_traits = traits
|
|
1489
1494
|
else:
|
|
1490
1495
|
self._original_traits = set()
|
|
1491
1496
|
|
|
1497
|
+
# Store the UI convenience parameters
|
|
1498
|
+
self._collapsed = collapsed
|
|
1499
|
+
self._child_prefix = child_prefix
|
|
1500
|
+
self._grid = grid
|
|
1501
|
+
self._grid_columns = grid_columns
|
|
1502
|
+
|
|
1492
1503
|
# Remember: we're a Parameter, too, just like everybody else.
|
|
1493
1504
|
super().__init__(
|
|
1494
1505
|
name=name,
|
|
@@ -1511,6 +1522,99 @@ class ParameterList(ParameterContainer):
|
|
|
1511
1522
|
element_type=element_type,
|
|
1512
1523
|
)
|
|
1513
1524
|
|
|
1525
|
+
@property
|
|
1526
|
+
def collapsed(self) -> bool | None:
|
|
1527
|
+
return self._collapsed
|
|
1528
|
+
|
|
1529
|
+
@collapsed.setter
|
|
1530
|
+
@BaseNodeElement.emits_update_on_write
|
|
1531
|
+
def collapsed(self, value: bool | None) -> None:
|
|
1532
|
+
self._collapsed = value
|
|
1533
|
+
|
|
1534
|
+
@property
|
|
1535
|
+
def child_prefix(self) -> str | None:
|
|
1536
|
+
return self._child_prefix
|
|
1537
|
+
|
|
1538
|
+
@child_prefix.setter
|
|
1539
|
+
@BaseNodeElement.emits_update_on_write
|
|
1540
|
+
def child_prefix(self, value: str | None) -> None:
|
|
1541
|
+
self._child_prefix = value
|
|
1542
|
+
|
|
1543
|
+
@property
|
|
1544
|
+
def grid(self) -> bool | None:
|
|
1545
|
+
return self._grid
|
|
1546
|
+
|
|
1547
|
+
@grid.setter
|
|
1548
|
+
@BaseNodeElement.emits_update_on_write
|
|
1549
|
+
def grid(self, value: bool | None) -> None:
|
|
1550
|
+
self._grid = value
|
|
1551
|
+
|
|
1552
|
+
@property
|
|
1553
|
+
def grid_columns(self) -> int | None:
|
|
1554
|
+
return self._grid_columns
|
|
1555
|
+
|
|
1556
|
+
@grid_columns.setter
|
|
1557
|
+
@BaseNodeElement.emits_update_on_write
|
|
1558
|
+
def grid_columns(self, value: int | None) -> None:
|
|
1559
|
+
self._grid_columns = value
|
|
1560
|
+
|
|
1561
|
+
@property
|
|
1562
|
+
def ui_options(self) -> dict:
|
|
1563
|
+
"""Override ui_options to merge convenience parameters in real-time."""
|
|
1564
|
+
# Get base ui_options from parent
|
|
1565
|
+
base_ui_options = super().ui_options
|
|
1566
|
+
|
|
1567
|
+
# Build convenience options from instance parameters
|
|
1568
|
+
convenience_options = {}
|
|
1569
|
+
|
|
1570
|
+
if self._collapsed is not None:
|
|
1571
|
+
convenience_options["collapsed"] = self._collapsed
|
|
1572
|
+
|
|
1573
|
+
if self._child_prefix is not None:
|
|
1574
|
+
convenience_options["child_prefix"] = self._child_prefix
|
|
1575
|
+
|
|
1576
|
+
if self._grid is not None and self._grid:
|
|
1577
|
+
convenience_options["display"] = "grid"
|
|
1578
|
+
|
|
1579
|
+
if self._grid_columns is not None and self._grid:
|
|
1580
|
+
convenience_options["columns"] = self._grid_columns
|
|
1581
|
+
|
|
1582
|
+
# Merge convenience options with base ui_options
|
|
1583
|
+
return {
|
|
1584
|
+
**base_ui_options,
|
|
1585
|
+
**convenience_options,
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
@ui_options.setter
|
|
1589
|
+
@BaseNodeElement.emits_update_on_write
|
|
1590
|
+
def ui_options(self, value: dict) -> None:
|
|
1591
|
+
"""Set ui_options, preserving convenience parameters."""
|
|
1592
|
+
# Extract convenience parameters from the incoming value
|
|
1593
|
+
if "display" in value and value["display"] == "grid":
|
|
1594
|
+
self._grid = True
|
|
1595
|
+
if "columns" in value:
|
|
1596
|
+
self._grid_columns = value["columns"]
|
|
1597
|
+
else:
|
|
1598
|
+
self._grid = False
|
|
1599
|
+
|
|
1600
|
+
if "collapsed" in value:
|
|
1601
|
+
self._collapsed = value["collapsed"]
|
|
1602
|
+
|
|
1603
|
+
if "child_prefix" in value:
|
|
1604
|
+
self._child_prefix = value["child_prefix"]
|
|
1605
|
+
|
|
1606
|
+
# Set the base ui_options (excluding convenience parameters)
|
|
1607
|
+
base_ui_options = {
|
|
1608
|
+
k: v for k, v in value.items() if k not in ["display", "columns", "collapsed", "child_prefix"]
|
|
1609
|
+
}
|
|
1610
|
+
self._ui_options = base_ui_options
|
|
1611
|
+
|
|
1612
|
+
def to_dict(self) -> dict[str, Any]:
|
|
1613
|
+
"""Override to_dict to use the merged ui_options."""
|
|
1614
|
+
data = super().to_dict()
|
|
1615
|
+
data["ui_options"] = self.ui_options
|
|
1616
|
+
return data
|
|
1617
|
+
|
|
1514
1618
|
def _custom_getter_for_property_type(self) -> str:
|
|
1515
1619
|
base_type = super()._custom_getter_for_property_type()
|
|
1516
1620
|
result = f"list[{base_type}]"
|
|
@@ -384,9 +384,7 @@ class BaseNode(ABC):
|
|
|
384
384
|
for name in names:
|
|
385
385
|
parameter = self.get_parameter_by_name(name)
|
|
386
386
|
if parameter is not None:
|
|
387
|
-
ui_options = parameter.ui_options
|
|
388
|
-
ui_options["hide"] = not visible
|
|
389
|
-
parameter.ui_options = ui_options
|
|
387
|
+
parameter.ui_options = {**parameter.ui_options, "hide": not visible}
|
|
390
388
|
|
|
391
389
|
def get_message_by_name_or_element_id(self, element: str) -> ParameterMessage | None:
|
|
392
390
|
element_items = self.root_ui_element.find_elements_by_type(ParameterMessage)
|
|
@@ -408,9 +406,7 @@ class BaseNode(ABC):
|
|
|
408
406
|
for name in names:
|
|
409
407
|
message = self.get_message_by_name_or_element_id(name)
|
|
410
408
|
if message is not None:
|
|
411
|
-
ui_options = message.ui_options
|
|
412
|
-
ui_options["hide"] = not visible
|
|
413
|
-
message.ui_options = ui_options
|
|
409
|
+
message.ui_options = {**message.ui_options, "hide": not visible}
|
|
414
410
|
|
|
415
411
|
def hide_message_by_name(self, names: str | list[str]) -> None:
|
|
416
412
|
self._set_message_visibility(names, visible=False)
|
|
@@ -727,11 +723,9 @@ class BaseNode(ABC):
|
|
|
727
723
|
return param
|
|
728
724
|
return None
|
|
729
725
|
|
|
730
|
-
# Abstract method to process the node. Must be defined by the type
|
|
731
726
|
# Must save the values of the output parameters in NodeContext.
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
pass
|
|
727
|
+
def process(self) -> AsyncResult | None:
|
|
728
|
+
raise NotImplementedError
|
|
735
729
|
|
|
736
730
|
async def aprocess(self) -> None:
|
|
737
731
|
"""Async version of process().
|
|
@@ -867,7 +861,7 @@ class BaseNode(ABC):
|
|
|
867
861
|
msg = f"Parameter '{parameter_name} doesn't exist on {self.name}'"
|
|
868
862
|
raise RuntimeError(msg)
|
|
869
863
|
|
|
870
|
-
def reorder_elements(self, element_order: list[str | int]) -> None:
|
|
864
|
+
def reorder_elements(self, element_order: list[str] | list[int] | list[str | int]) -> None:
|
|
871
865
|
"""Reorder the elements of this node.
|
|
872
866
|
|
|
873
867
|
Args:
|
|
@@ -1109,7 +1103,10 @@ class TrackedParameterOutputValues(dict[str, Any]):
|
|
|
1109
1103
|
keys_to_clear = list(self.keys())
|
|
1110
1104
|
super().clear()
|
|
1111
1105
|
for key in keys_to_clear:
|
|
1112
|
-
|
|
1106
|
+
# Some nodes still have values set, even if their output values are cleared
|
|
1107
|
+
# Here, we are emitting an event with those set values, to not misrepresent the values of the parameters in the UI.
|
|
1108
|
+
value = self._node.get_parameter_value(key)
|
|
1109
|
+
self._emit_parameter_change_event(key, value, deleted=True)
|
|
1113
1110
|
|
|
1114
1111
|
def silent_clear(self) -> None:
|
|
1115
1112
|
"""Clear all values without emitting parameter change events."""
|
|
@@ -15,6 +15,7 @@ from griptape_nodes.retained_mode.events.base_events import ExecutionEvent, Exec
|
|
|
15
15
|
from griptape_nodes.retained_mode.events.execution_events import (
|
|
16
16
|
ControlFlowResolvedEvent,
|
|
17
17
|
CurrentControlNodeEvent,
|
|
18
|
+
InvolvedNodesEvent,
|
|
18
19
|
SelectedControlOutputEvent,
|
|
19
20
|
)
|
|
20
21
|
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
@@ -252,12 +253,21 @@ class ControlFlowMachine(FSM[ControlFlowContext]):
|
|
|
252
253
|
current_nodes = await self._process_nodes_for_dag(start_node)
|
|
253
254
|
else:
|
|
254
255
|
current_nodes = [start_node]
|
|
256
|
+
# For control flow/sequential: emit all nodes in flow as involved
|
|
255
257
|
self._context.current_nodes = current_nodes
|
|
256
258
|
# Set entry control parameter for initial node (None for workflow start)
|
|
257
259
|
for node in current_nodes:
|
|
258
260
|
node.set_entry_control_parameter(None)
|
|
259
261
|
# Set up to debug
|
|
260
262
|
self._context.paused = debug_mode
|
|
263
|
+
flow_manager = GriptapeNodes.FlowManager()
|
|
264
|
+
flow = flow_manager.get_flow_by_name(self._context.flow_name)
|
|
265
|
+
involved_nodes = list(flow.nodes.keys())
|
|
266
|
+
GriptapeNodes.EventManager().put_event(
|
|
267
|
+
ExecutionGriptapeNodeEvent(
|
|
268
|
+
wrapped_event=ExecutionEvent(payload=InvolvedNodesEvent(involved_nodes=involved_nodes))
|
|
269
|
+
)
|
|
270
|
+
)
|
|
261
271
|
await self.start(ResolveNodeState) # Begins the flow
|
|
262
272
|
|
|
263
273
|
async def update(self) -> None:
|
|
@@ -43,10 +43,12 @@ class DagBuilder:
|
|
|
43
43
|
|
|
44
44
|
graphs: dict[str, DirectedGraph] # Str is the name of the start node associated here.
|
|
45
45
|
node_to_reference: dict[str, DagNode]
|
|
46
|
+
graph_to_nodes: dict[str, set[str]] # Track which nodes belong to which graph
|
|
46
47
|
|
|
47
48
|
def __init__(self) -> None:
|
|
48
49
|
self.graphs = {}
|
|
49
50
|
self.node_to_reference: dict[str, DagNode] = {}
|
|
51
|
+
self.graph_to_nodes = {}
|
|
50
52
|
|
|
51
53
|
# Complex with the inner recursive method, but it needs connections and added_nodes.
|
|
52
54
|
def add_node_with_dependencies(self, node: BaseNode, graph_name: str = "default") -> list[BaseNode]: # noqa: C901
|
|
@@ -59,16 +61,15 @@ class DagBuilder:
|
|
|
59
61
|
if graph is None:
|
|
60
62
|
graph = DirectedGraph()
|
|
61
63
|
self.graphs[graph_name] = graph
|
|
64
|
+
self.graph_to_nodes[graph_name] = set()
|
|
62
65
|
|
|
63
66
|
def _add_node_recursive(current_node: BaseNode, visited: set[str], graph: DirectedGraph) -> None:
|
|
64
67
|
if current_node.name in visited:
|
|
65
68
|
return
|
|
66
69
|
visited.add(current_node.name)
|
|
67
|
-
|
|
68
70
|
# Skip if already in DAG (use DAG membership, not resolved state)
|
|
69
71
|
if current_node.name in self.node_to_reference:
|
|
70
72
|
return
|
|
71
|
-
|
|
72
73
|
# Process dependencies first (depth-first)
|
|
73
74
|
ignore_data_dependencies = False
|
|
74
75
|
# This is specifically for output_selector. Overriding 'initialize_spotlight' doesn't work anymore.
|
|
@@ -98,6 +99,10 @@ class DagBuilder:
|
|
|
98
99
|
dag_node = DagNode(node_reference=current_node, node_state=NodeState.WAITING)
|
|
99
100
|
self.node_to_reference[current_node.name] = dag_node
|
|
100
101
|
graph.add_node(node_for_adding=current_node.name)
|
|
102
|
+
|
|
103
|
+
# Track which nodes belong to this graph
|
|
104
|
+
self.graph_to_nodes[graph_name].add(current_node.name)
|
|
105
|
+
|
|
101
106
|
# DON'T mark as resolved - that happens during actual execution
|
|
102
107
|
added_nodes.append(current_node)
|
|
103
108
|
|
|
@@ -117,12 +122,19 @@ class DagBuilder:
|
|
|
117
122
|
graph = DirectedGraph()
|
|
118
123
|
self.graphs[graph_name] = graph
|
|
119
124
|
graph.add_node(node_for_adding=node.name)
|
|
125
|
+
|
|
126
|
+
# Track which nodes belong to this graph
|
|
127
|
+
if graph_name not in self.graph_to_nodes:
|
|
128
|
+
self.graph_to_nodes[graph_name] = set()
|
|
129
|
+
self.graph_to_nodes[graph_name].add(node.name)
|
|
130
|
+
|
|
120
131
|
return dag_node
|
|
121
132
|
|
|
122
133
|
def clear(self) -> None:
|
|
123
134
|
"""Clear all nodes and references from the DAG builder."""
|
|
124
135
|
self.graphs.clear()
|
|
125
136
|
self.node_to_reference.clear()
|
|
137
|
+
self.graph_to_nodes.clear()
|
|
126
138
|
|
|
127
139
|
def can_queue_control_node(self, node: DagNode) -> bool:
|
|
128
140
|
if len(self.graphs) == 1:
|
|
@@ -205,3 +217,10 @@ class DagBuilder:
|
|
|
205
217
|
return True
|
|
206
218
|
|
|
207
219
|
return False
|
|
220
|
+
|
|
221
|
+
def cleanup_empty_graph_nodes(self, graph_name: str) -> None:
|
|
222
|
+
"""Remove nodes from node_to_reference when their graph becomes empty (only in single node resolution)."""
|
|
223
|
+
if graph_name in self.graph_to_nodes:
|
|
224
|
+
for node_name in self.graph_to_nodes[graph_name]:
|
|
225
|
+
self.node_to_reference.pop(node_name, None)
|
|
226
|
+
self.graph_to_nodes.pop(graph_name, None)
|
{griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/machines/parallel_resolution.py
RENAMED
|
@@ -18,6 +18,7 @@ from griptape_nodes.retained_mode.events.base_events import (
|
|
|
18
18
|
from griptape_nodes.retained_mode.events.execution_events import (
|
|
19
19
|
CurrentControlNodeEvent,
|
|
20
20
|
CurrentDataNodeEvent,
|
|
21
|
+
InvolvedNodesEvent,
|
|
21
22
|
NodeResolvedEvent,
|
|
22
23
|
ParameterValueUpdateEvent,
|
|
23
24
|
)
|
|
@@ -184,19 +185,22 @@ class ExecuteDagState(State):
|
|
|
184
185
|
context: ParallelResolutionContext, node: BaseNode, network_name: str, flow_manager: FlowManager
|
|
185
186
|
) -> bool:
|
|
186
187
|
"""Check if control flow processing should be skipped."""
|
|
188
|
+
# Get network once to avoid duplicate lookups
|
|
189
|
+
if context.dag_builder is None:
|
|
190
|
+
msg = "DAG builder is not initialized"
|
|
191
|
+
raise ValueError(msg)
|
|
192
|
+
network = context.dag_builder.graphs.get(network_name, None)
|
|
193
|
+
if network is None:
|
|
194
|
+
msg = f"Network {network_name} not found in DAG builder"
|
|
195
|
+
raise ValueError(msg)
|
|
187
196
|
if flow_manager.global_single_node_resolution:
|
|
197
|
+
# Clean up nodes from emptied graphs in single node resolution mode
|
|
198
|
+
if len(network) == 0 and context.dag_builder is not None:
|
|
199
|
+
context.dag_builder.cleanup_empty_graph_nodes(network_name)
|
|
200
|
+
ExecuteDagState._emit_involved_nodes_update(context)
|
|
188
201
|
return True
|
|
189
202
|
|
|
190
|
-
|
|
191
|
-
network = context.dag_builder.graphs.get(network_name, None)
|
|
192
|
-
if network is not None and len(network) > 0:
|
|
193
|
-
return True
|
|
194
|
-
|
|
195
|
-
if node.stop_flow:
|
|
196
|
-
node.stop_flow = False
|
|
197
|
-
return True
|
|
198
|
-
|
|
199
|
-
return False
|
|
203
|
+
return bool(len(network) > 0 or node.stop_flow)
|
|
200
204
|
|
|
201
205
|
@staticmethod
|
|
202
206
|
def _process_next_control_node(
|
|
@@ -229,6 +233,17 @@ class ExecuteDagState(State):
|
|
|
229
233
|
)
|
|
230
234
|
ExecuteDagState._add_and_queue_nodes(context, next_node, network_name)
|
|
231
235
|
|
|
236
|
+
@staticmethod
|
|
237
|
+
def _emit_involved_nodes_update(context: ParallelResolutionContext) -> None:
|
|
238
|
+
"""Emit update of involved nodes based on current DAG state."""
|
|
239
|
+
if context.dag_builder is not None:
|
|
240
|
+
involved_nodes = list(context.node_to_reference.keys())
|
|
241
|
+
GriptapeNodes.EventManager().put_event(
|
|
242
|
+
ExecutionGriptapeNodeEvent(
|
|
243
|
+
wrapped_event=ExecutionEvent(payload=InvolvedNodesEvent(involved_nodes=involved_nodes))
|
|
244
|
+
)
|
|
245
|
+
)
|
|
246
|
+
|
|
232
247
|
@staticmethod
|
|
233
248
|
def _add_and_queue_nodes(context: ParallelResolutionContext, next_node: BaseNode, network_name: str) -> None:
|
|
234
249
|
"""Add nodes to DAG and queue them if ready."""
|
{griptape_nodes-0.55.1 → griptape_nodes-0.56.0}/src/griptape_nodes/node_library/workflow_registry.py
RENAMED
|
@@ -1,19 +1,45 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
3
5
|
from datetime import datetime # noqa: TC003 (can't put into type checking block as Pydantic model relies on it)
|
|
4
6
|
from pathlib import Path
|
|
5
|
-
from typing import ClassVar
|
|
7
|
+
from typing import Any, ClassVar
|
|
6
8
|
|
|
7
|
-
from pydantic import BaseModel, Field
|
|
9
|
+
from pydantic import BaseModel, Field, field_serializer, field_validator
|
|
8
10
|
|
|
9
11
|
from griptape_nodes.node_library.library_registry import (
|
|
10
12
|
LibraryNameAndVersion, # noqa: TC001 (putting this into type checking causes it to not be defined)
|
|
11
13
|
)
|
|
12
14
|
from griptape_nodes.utils.metaclasses import SingletonMeta
|
|
13
15
|
|
|
16
|
+
logger = logging.getLogger("griptape_nodes")
|
|
17
|
+
|
|
18
|
+
# Type aliases for clarity
|
|
19
|
+
type NodeName = str
|
|
20
|
+
type ParameterName = str
|
|
21
|
+
type ParameterAttribute = str
|
|
22
|
+
type ParameterMinimalDict = dict[ParameterAttribute, Any]
|
|
23
|
+
type NodeParametersMapping = dict[NodeName, dict[ParameterName, ParameterMinimalDict]]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class WorkflowShape(BaseModel):
|
|
27
|
+
"""This structure reflects the input and output shapes extracted from StartNodes and EndNodes inside of the workflow.
|
|
28
|
+
|
|
29
|
+
A workflow may have multiple StartNodes and multiple EndNodes, each contributing their parameters
|
|
30
|
+
to the overall workflow shape.
|
|
31
|
+
|
|
32
|
+
Structure is:
|
|
33
|
+
- inputs: {start_node_name: {param_name: param_minimal_dict}}
|
|
34
|
+
- outputs: {end_node_name: {param_name: param_minimal_dict}}
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
inputs: NodeParametersMapping = Field(default_factory=dict)
|
|
38
|
+
outputs: NodeParametersMapping = Field(default_factory=dict)
|
|
39
|
+
|
|
14
40
|
|
|
15
41
|
class WorkflowMetadata(BaseModel):
|
|
16
|
-
LATEST_SCHEMA_VERSION: ClassVar[str] = "0.
|
|
42
|
+
LATEST_SCHEMA_VERSION: ClassVar[str] = "0.8.0"
|
|
17
43
|
|
|
18
44
|
name: str
|
|
19
45
|
schema_version: str
|
|
@@ -27,6 +53,50 @@ class WorkflowMetadata(BaseModel):
|
|
|
27
53
|
creation_date: datetime | None = Field(default=None)
|
|
28
54
|
last_modified_date: datetime | None = Field(default=None)
|
|
29
55
|
branched_from: str | None = Field(default=None)
|
|
56
|
+
workflow_shape: WorkflowShape | None = Field(default=None)
|
|
57
|
+
|
|
58
|
+
@field_serializer("workflow_shape")
|
|
59
|
+
def serialize_workflow_shape(self, workflow_shape: WorkflowShape | None) -> str | None:
|
|
60
|
+
"""Serialize WorkflowShape as JSON string to avoid TOML serialization issues.
|
|
61
|
+
|
|
62
|
+
The WorkflowShape contains deeply nested dictionaries with None values that are
|
|
63
|
+
meaningful data (e.g., default_value: None). TOML's nested table format creates
|
|
64
|
+
unreadable output and tomlkit fails on None values in nested structures.
|
|
65
|
+
JSON preserves None as null and keeps the data compact and readable.
|
|
66
|
+
"""
|
|
67
|
+
if workflow_shape is None:
|
|
68
|
+
return None
|
|
69
|
+
# Use json.dumps to preserve None values as null, which TOML can handle
|
|
70
|
+
return json.dumps(workflow_shape.model_dump(), separators=(",", ":"))
|
|
71
|
+
|
|
72
|
+
@field_validator("workflow_shape", mode="before")
|
|
73
|
+
@classmethod
|
|
74
|
+
def validate_workflow_shape(cls, value: Any) -> WorkflowShape | None:
|
|
75
|
+
"""Deserialize WorkflowShape from JSON string during TOML loading.
|
|
76
|
+
|
|
77
|
+
When loading workflow metadata from TOML files, the workflow_shape field
|
|
78
|
+
is stored as a JSON string that needs to be converted back to a WorkflowShape
|
|
79
|
+
object. This validator handles the expected input formats:
|
|
80
|
+
- JSON strings (from TOML deserialization)
|
|
81
|
+
- WorkflowShape objects (from direct Python construction)
|
|
82
|
+
- None values (workflows without Start/End nodes)
|
|
83
|
+
|
|
84
|
+
If JSON deserialization fails, logs a warning and returns None for graceful
|
|
85
|
+
degradation, consistent with other metadata parsing failures in this codebase.
|
|
86
|
+
"""
|
|
87
|
+
if value is None:
|
|
88
|
+
return None
|
|
89
|
+
if isinstance(value, WorkflowShape):
|
|
90
|
+
return value
|
|
91
|
+
if isinstance(value, str):
|
|
92
|
+
try:
|
|
93
|
+
data = json.loads(value)
|
|
94
|
+
return WorkflowShape(**data)
|
|
95
|
+
except (json.JSONDecodeError, TypeError, ValueError) as e:
|
|
96
|
+
logger.error("Failed to deserialize workflow_shape from JSON: %s", e)
|
|
97
|
+
return None
|
|
98
|
+
# Unexpected type - let Pydantic's normal validation handle it
|
|
99
|
+
return value
|
|
30
100
|
|
|
31
101
|
|
|
32
102
|
class WorkflowRegistry(metaclass=SingletonMeta):
|
|
@@ -225,12 +225,10 @@ 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.
|
|
229
228
|
"""
|
|
230
229
|
|
|
231
230
|
control_nodes: list[str] | None
|
|
232
231
|
resolving_node: list[str] | None
|
|
233
|
-
involved_nodes: list[str] | None
|
|
234
232
|
|
|
235
233
|
|
|
236
234
|
@dataclass
|
|
@@ -348,6 +346,18 @@ class NodeFinishProcessEvent(ExecutionPayload):
|
|
|
348
346
|
node_name: str
|
|
349
347
|
|
|
350
348
|
|
|
349
|
+
@dataclass
|
|
350
|
+
@PayloadRegistry.register
|
|
351
|
+
class InvolvedNodesEvent(ExecutionPayload):
|
|
352
|
+
"""Event indicating which nodes are involved in the current execution.
|
|
353
|
+
|
|
354
|
+
For parallel resolution: Dynamic list based on DAG builder state
|
|
355
|
+
For control flow/sequential: All nodes when started, empty when complete
|
|
356
|
+
"""
|
|
357
|
+
|
|
358
|
+
involved_nodes: list[str]
|
|
359
|
+
|
|
360
|
+
|
|
351
361
|
@dataclass
|
|
352
362
|
@PayloadRegistry.register
|
|
353
363
|
class GriptapeEvent(ExecutionPayload):
|