griptape-nodes 0.46.0__tar.gz → 0.47.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.46.0 → griptape_nodes-0.47.0}/PKG-INFO +1 -1
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/pyproject.toml +1 -1
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/exe_types/core_types.py +65 -10
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/exe_types/node_types.py +10 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/machines/node_resolution.py +10 -8
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/base_events.py +74 -1
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/secrets_events.py +2 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/griptape_nodes.py +17 -13
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/agent_manager.py +8 -6
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py +1 -1
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/config_manager.py +36 -45
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/flow_manager.py +98 -98
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/library_manager.py +51 -51
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/node_manager.py +121 -124
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/object_manager.py +9 -10
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/os_manager.py +31 -31
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/secrets_manager.py +5 -5
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/static_files_manager.py +18 -17
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/sync_manager.py +3 -2
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/workflow_manager.py +134 -160
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/retained_mode.py +22 -44
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/README.md +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/app/.python-version +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/app/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/app/api.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/app/app.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/app/watch.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/bootstrap/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/bootstrap/workflow_executors/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/bootstrap/workflow_executors/local_workflow_executor.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/bootstrap/workflow_executors/subprocess_workflow_executor.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/bootstrap/workflow_executors/workflow_executor.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/drivers/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/drivers/storage/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/drivers/storage/base_storage_driver.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/drivers/storage/griptape_cloud_storage_driver.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/drivers/storage/local_storage_driver.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/drivers/storage/storage_backend.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/exe_types/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/exe_types/connections.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/exe_types/flow.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/exe_types/type_validator.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/machines/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/machines/control_flow.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/machines/fsm.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/mcp_server/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/mcp_server/server.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/mcp_server/ws_request_manager.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/node_library/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/node_library/advanced_node_library.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/node_library/library_registry.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/node_library/workflow_registry.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/py.typed +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/agent_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/app_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/arbitrary_python_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/config_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/connection_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/context_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/execution_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/flow_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/generate_request_payload_schemas.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/library_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/logger_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/node_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/object_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/os_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/parameter_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/payload_registry.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/static_file_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/sync_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/validation_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/events/workflow_events.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/context_manager.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/engine_identity_manager.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/event_manager.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/data_models.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_directory.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_fsm.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/base.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/github.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/local_file.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/package.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/sandbox.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/library_lifecycle/library_status.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/operation_manager.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/session_manager.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/settings.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/managers/version_compatibility_manager.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/utils/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/utils/engine_identity.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/utils/name_generator.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/traits/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/traits/add_param_button.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/traits/button.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/traits/clamp.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/traits/compare.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/traits/compare_images.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/traits/file_system_picker.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/traits/minmax.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/traits/options.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/traits/slider.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/traits/trait_registry.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/traits/traits.json +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/updater/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/updater/__main__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/utils/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/utils/dict_utils.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/utils/image_preview.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/utils/metaclasses.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/utils/uv_utils.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/utils/version_utils.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/version_compatibility/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/version_compatibility/versions/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/version_compatibility/versions/v0_39_0/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/version_compatibility/versions/v0_39_0/modified_parameters_set_removal.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/version_compatibility/workflow_versions/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/version_compatibility/workflow_versions/v0_7_0/__init__.py +0 -0
- {griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/version_compatibility/workflow_versions/v0_7_0/local_executor_argument_addition.py +0 -0
|
@@ -65,25 +65,52 @@ class ParameterType:
|
|
|
65
65
|
return ret_val
|
|
66
66
|
|
|
67
67
|
@staticmethod
|
|
68
|
-
def
|
|
68
|
+
def _extract_base_type(type_str: str) -> str:
|
|
69
|
+
"""Extract the base type from a potentially generic type string.
|
|
70
|
+
|
|
71
|
+
Examples:
|
|
72
|
+
'list[any]' -> 'list'
|
|
73
|
+
'dict[str, int]' -> 'dict'
|
|
74
|
+
'str' -> 'str'
|
|
75
|
+
"""
|
|
76
|
+
bracket_index = type_str.find("[")
|
|
77
|
+
if bracket_index == -1:
|
|
78
|
+
return type_str
|
|
79
|
+
return type_str[:bracket_index]
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def are_types_compatible(source_type: str | None, target_type: str | None) -> bool: # noqa: PLR0911
|
|
69
83
|
if source_type is None or target_type is None:
|
|
70
84
|
return False
|
|
71
85
|
|
|
72
|
-
ret_val = False
|
|
73
86
|
source_type_lower = source_type.lower()
|
|
74
87
|
target_type_lower = target_type.lower()
|
|
75
88
|
|
|
76
89
|
# If either are None, bail.
|
|
77
90
|
if ParameterTypeBuiltin.NONE.value in (source_type_lower, target_type_lower):
|
|
78
|
-
|
|
79
|
-
|
|
91
|
+
return False
|
|
92
|
+
if target_type_lower == ParameterTypeBuiltin.ANY.value:
|
|
80
93
|
# If the TARGET accepts Any, we're good. Not always true the other way 'round.
|
|
81
|
-
|
|
82
|
-
else:
|
|
83
|
-
# Do a compare.
|
|
84
|
-
ret_val = source_type_lower == target_type_lower
|
|
94
|
+
return True
|
|
85
95
|
|
|
86
|
-
|
|
96
|
+
# First try exact match
|
|
97
|
+
if source_type_lower == target_type_lower:
|
|
98
|
+
return True
|
|
99
|
+
|
|
100
|
+
source_base = ParameterType._extract_base_type(source_type_lower)
|
|
101
|
+
target_base = ParameterType._extract_base_type(target_type_lower)
|
|
102
|
+
|
|
103
|
+
# If base types match
|
|
104
|
+
if source_base == target_base:
|
|
105
|
+
# Allow any generic to flow to base type (list[any] -> list, list[str] -> list)
|
|
106
|
+
if target_type_lower == target_base:
|
|
107
|
+
return True
|
|
108
|
+
|
|
109
|
+
# Allow specific types to flow to [any] generic (list[str] -> list[any])
|
|
110
|
+
if target_type_lower == f"{target_base}[{ParameterTypeBuiltin.ANY.value}]":
|
|
111
|
+
return True
|
|
112
|
+
|
|
113
|
+
return False
|
|
87
114
|
|
|
88
115
|
@staticmethod
|
|
89
116
|
def parse_kv_type_pair(type_str: str) -> KeyValueTypePair | None: # noqa: C901
|
|
@@ -250,7 +277,6 @@ class BaseNodeElement:
|
|
|
250
277
|
self._changes["ui_options"] = complete_dict["ui_options"]
|
|
251
278
|
|
|
252
279
|
event_data.update(self._changes)
|
|
253
|
-
|
|
254
280
|
# Publish the event
|
|
255
281
|
event = ExecutionGriptapeNodeEvent(
|
|
256
282
|
wrapped_event=ExecutionEvent(payload=AlterElementEvent(element_details=event_data))
|
|
@@ -1326,6 +1352,27 @@ class ParameterList(ParameterContainer):
|
|
|
1326
1352
|
result = f"list[{base_type}]"
|
|
1327
1353
|
return result
|
|
1328
1354
|
|
|
1355
|
+
def _custom_setter_for_property_type(self, value: str | None) -> None:
|
|
1356
|
+
# If we are setting a type, we need to propagate this to our children as well.
|
|
1357
|
+
for child in self._children:
|
|
1358
|
+
if isinstance(child, Parameter):
|
|
1359
|
+
child.type = value
|
|
1360
|
+
super()._custom_setter_for_property_type(value)
|
|
1361
|
+
|
|
1362
|
+
def _custom_setter_for_property_input_types(self, value: list[str] | None) -> None:
|
|
1363
|
+
# If we are setting a type, we need to propagate this to our children as well.
|
|
1364
|
+
for child in self._children:
|
|
1365
|
+
if isinstance(child, Parameter):
|
|
1366
|
+
child.input_types = value
|
|
1367
|
+
return super()._custom_setter_for_property_input_types(value)
|
|
1368
|
+
|
|
1369
|
+
def _custom_setter_for_property_output_type(self, value: str | None) -> None:
|
|
1370
|
+
# If we are setting a type, we need to propagate this to our children as well.
|
|
1371
|
+
for child in self._children:
|
|
1372
|
+
if isinstance(child, Parameter):
|
|
1373
|
+
child.output_type = value
|
|
1374
|
+
return super()._custom_setter_for_property_output_type(value)
|
|
1375
|
+
|
|
1329
1376
|
def _custom_getter_for_property_input_types(self) -> list[str]:
|
|
1330
1377
|
# For every valid input type, also accept a list variant of that for the CONTAINER Parameter only.
|
|
1331
1378
|
# Children still use the input types given to them.
|
|
@@ -1395,6 +1442,14 @@ class ParameterList(ParameterContainer):
|
|
|
1395
1442
|
|
|
1396
1443
|
return param
|
|
1397
1444
|
|
|
1445
|
+
def clear_list(self) -> None:
|
|
1446
|
+
"""Remove all children that have been added to the list."""
|
|
1447
|
+
children = self.find_elements_by_type(element_type=Parameter)
|
|
1448
|
+
for child in children:
|
|
1449
|
+
if isinstance(child, Parameter):
|
|
1450
|
+
self.remove_child(child)
|
|
1451
|
+
del child
|
|
1452
|
+
|
|
1398
1453
|
def add_child(self, child: BaseNodeElement) -> None:
|
|
1399
1454
|
"""Override to mark parent node as unresolved when children are added.
|
|
1400
1455
|
|
|
@@ -848,12 +848,22 @@ class BaseNode(ABC):
|
|
|
848
848
|
|
|
849
849
|
# Create event data using the parameter's to_event method
|
|
850
850
|
if remove:
|
|
851
|
+
# Import logger here to avoid circular dependency
|
|
852
|
+
from griptape_nodes.retained_mode.griptape_nodes import logger
|
|
853
|
+
|
|
854
|
+
logger.info(
|
|
855
|
+
f"RemoveElementEvent: Emitting parameter lifecycle event for element {parameter.name} on node {self.name}"
|
|
856
|
+
)
|
|
851
857
|
event = ExecutionGriptapeNodeEvent(
|
|
852
858
|
wrapped_event=ExecutionEvent(payload=RemoveElementEvent(element_id=parameter.element_id))
|
|
853
859
|
)
|
|
854
860
|
else:
|
|
855
861
|
event_data = parameter.to_event(self)
|
|
862
|
+
from griptape_nodes.retained_mode.griptape_nodes import logger
|
|
856
863
|
|
|
864
|
+
logger.info(
|
|
865
|
+
f"AlterElementEvent: Emitting parameter lifecycle eventfor element {parameter.name} on node {self.name}"
|
|
866
|
+
)
|
|
857
867
|
# Publish the event
|
|
858
868
|
event = ExecutionGriptapeNodeEvent(
|
|
859
869
|
wrapped_event=ExecutionEvent(payload=AlterElementEvent(element_details=event_data))
|
{griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/machines/node_resolution.py
RENAMED
|
@@ -225,16 +225,18 @@ class ExecuteNodeState(State):
|
|
|
225
225
|
# If the upstream node is resolved, collect its output value
|
|
226
226
|
if upstream_parameter.name in upstream_node.parameter_output_values:
|
|
227
227
|
output_value = upstream_node.parameter_output_values[upstream_parameter.name]
|
|
228
|
+
else:
|
|
229
|
+
output_value = upstream_node.get_parameter_value(upstream_parameter.name)
|
|
228
230
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
)
|
|
231
|
+
# Pass the value through using the same mechanism as normal resolution
|
|
232
|
+
GriptapeNodes.get_instance().handle_request(
|
|
233
|
+
SetParameterValueRequest(
|
|
234
|
+
parameter_name=parameter.name,
|
|
235
|
+
node_name=current_node.name,
|
|
236
|
+
value=output_value,
|
|
237
|
+
data_type=upstream_parameter.output_type,
|
|
237
238
|
)
|
|
239
|
+
)
|
|
238
240
|
|
|
239
241
|
@staticmethod
|
|
240
242
|
def on_enter(context: ResolutionContext) -> type[State] | None:
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import logging
|
|
4
5
|
from abc import ABC, abstractmethod
|
|
5
6
|
from dataclasses import asdict, dataclass, field, is_dataclass
|
|
6
|
-
from typing import TYPE_CHECKING, Any, ClassVar, TypeVar
|
|
7
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Literal, TypeVar
|
|
7
8
|
|
|
8
9
|
from griptape.artifacts import BaseArtifact
|
|
9
10
|
from griptape.events import BaseEvent as GtBaseEvent
|
|
@@ -16,6 +17,64 @@ if TYPE_CHECKING:
|
|
|
16
17
|
import builtins
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
@dataclass
|
|
21
|
+
class ResultDetail:
|
|
22
|
+
"""A single detail about an operation result, including logging level and human readable message."""
|
|
23
|
+
|
|
24
|
+
level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
|
25
|
+
message: str
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class ResultDetails:
|
|
30
|
+
"""Container for multiple ResultDetail objects."""
|
|
31
|
+
|
|
32
|
+
result_details: list[ResultDetail]
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
*result_details: ResultDetail,
|
|
37
|
+
message: str | None = None,
|
|
38
|
+
level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] | None = None,
|
|
39
|
+
logger: logging.Logger | str | None = "griptape_nodes",
|
|
40
|
+
):
|
|
41
|
+
"""Initialize with ResultDetail objects or create a single one from message/level.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
*result_details: Variable number of ResultDetail objects
|
|
45
|
+
message: If provided, creates a single ResultDetail with this message
|
|
46
|
+
level: Logging level for the single ResultDetail (required if message is provided)
|
|
47
|
+
logger: Logger to use for auto-logging. String for logger name, Logger object, or None to skip
|
|
48
|
+
"""
|
|
49
|
+
# Handle single message/level convenience
|
|
50
|
+
if message is not None:
|
|
51
|
+
if level is None:
|
|
52
|
+
err_msg = "level is required when message is provided"
|
|
53
|
+
raise ValueError(err_msg)
|
|
54
|
+
if result_details:
|
|
55
|
+
err_msg = "Cannot provide both result_details and message/level"
|
|
56
|
+
raise ValueError(err_msg)
|
|
57
|
+
self.result_details = [ResultDetail(level=level, message=message)]
|
|
58
|
+
else:
|
|
59
|
+
if not result_details:
|
|
60
|
+
err_msg = "ResultDetails requires at least one ResultDetail or message/level"
|
|
61
|
+
raise ValueError(err_msg)
|
|
62
|
+
self.result_details = list(result_details)
|
|
63
|
+
|
|
64
|
+
# Auto-log if logger is provided
|
|
65
|
+
if logger is not None:
|
|
66
|
+
try:
|
|
67
|
+
if isinstance(logger, str):
|
|
68
|
+
logger = logging.getLogger(logger)
|
|
69
|
+
|
|
70
|
+
for detail in self.result_details:
|
|
71
|
+
numeric_level = getattr(logging, detail.level)
|
|
72
|
+
logger.log(numeric_level, detail.message)
|
|
73
|
+
except Exception: # noqa: S110
|
|
74
|
+
# If logging fails for any reason, don't let it break the ResultDetails creation
|
|
75
|
+
pass
|
|
76
|
+
|
|
77
|
+
|
|
19
78
|
# The Payload class is a marker interface
|
|
20
79
|
class Payload(ABC): # noqa: B024
|
|
21
80
|
"""Base class for all payload types. Customers will derive from this."""
|
|
@@ -32,6 +91,7 @@ class RequestPayload(Payload, ABC):
|
|
|
32
91
|
class ResultPayload(Payload, ABC):
|
|
33
92
|
"""Base class for all result payloads."""
|
|
34
93
|
|
|
94
|
+
result_details: ResultDetails | str
|
|
35
95
|
"""When set to True, alerts clients that this result made changes to the workflow state.
|
|
36
96
|
Editors can use this to determine if the workflow is dirty and needs to be re-saved, for example."""
|
|
37
97
|
altered_workflow_state: bool = False
|
|
@@ -76,6 +136,13 @@ class SkipTheLineMixin:
|
|
|
76
136
|
class ResultPayloadSuccess(ResultPayload, ABC):
|
|
77
137
|
"""Abstract base class for success result payloads."""
|
|
78
138
|
|
|
139
|
+
result_details: ResultDetails | str = "Success"
|
|
140
|
+
|
|
141
|
+
def __post_init__(self) -> None:
|
|
142
|
+
"""Initialize success result with INFO level default for strings."""
|
|
143
|
+
if isinstance(self.result_details, str):
|
|
144
|
+
self.result_details = ResultDetails(message=self.result_details, level="DEBUG")
|
|
145
|
+
|
|
79
146
|
def succeeded(self) -> bool:
|
|
80
147
|
"""Returns True as this is a success result.
|
|
81
148
|
|
|
@@ -90,8 +157,14 @@ class ResultPayloadSuccess(ResultPayload, ABC):
|
|
|
90
157
|
class ResultPayloadFailure(ResultPayload, ABC):
|
|
91
158
|
"""Abstract base class for failure result payloads."""
|
|
92
159
|
|
|
160
|
+
result_details: ResultDetails | str = "Failure"
|
|
93
161
|
exception: Exception | None = None
|
|
94
162
|
|
|
163
|
+
def __post_init__(self) -> None:
|
|
164
|
+
"""Initialize failure result with ERROR level default for strings."""
|
|
165
|
+
if isinstance(self.result_details, str):
|
|
166
|
+
self.result_details = ResultDetails(message=self.result_details, level="ERROR")
|
|
167
|
+
|
|
95
168
|
def succeeded(self) -> bool:
|
|
96
169
|
"""Returns False as this is a failure result.
|
|
97
170
|
|
|
@@ -20,11 +20,13 @@ class GetSecretValueRequest(RequestPayload):
|
|
|
20
20
|
|
|
21
21
|
Args:
|
|
22
22
|
key: Name of the secret key to retrieve
|
|
23
|
+
should_error_on_not_found: Whether to error if the key is not found (default: True)
|
|
23
24
|
|
|
24
25
|
Results: GetSecretValueResultSuccess (with value) | GetSecretValueResultFailure (key not found)
|
|
25
26
|
"""
|
|
26
27
|
|
|
27
28
|
key: str
|
|
29
|
+
should_error_on_not_found: bool = True
|
|
28
30
|
|
|
29
31
|
|
|
30
32
|
@dataclass
|
{griptape_nodes-0.46.0 → griptape_nodes-0.47.0}/src/griptape_nodes/retained_mode/griptape_nodes.py
RENAMED
|
@@ -389,11 +389,11 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
389
389
|
)
|
|
390
390
|
details = f"Attempted to get engine version. Failed because version string '{engine_ver}' wasn't in expected major.minor.patch format."
|
|
391
391
|
logger.error(details)
|
|
392
|
-
return GetEngineVersionResultFailure()
|
|
392
|
+
return GetEngineVersionResultFailure(result_details=details)
|
|
393
393
|
except Exception as err:
|
|
394
394
|
details = f"Attempted to get engine version. Failed due to '{err}'."
|
|
395
395
|
logger.error(details)
|
|
396
|
-
return GetEngineVersionResultFailure()
|
|
396
|
+
return GetEngineVersionResultFailure(result_details=details)
|
|
397
397
|
|
|
398
398
|
def handle_session_start_request(self, request: AppStartSessionRequest) -> ResultPayload: # noqa: ARG002
|
|
399
399
|
from griptape_nodes.app.app import subscribe_to_topic
|
|
@@ -434,7 +434,7 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
434
434
|
except Exception as err:
|
|
435
435
|
details = f"Failed to end session due to '{err}'."
|
|
436
436
|
logger.error(details)
|
|
437
|
-
return AppEndSessionResultFailure()
|
|
437
|
+
return AppEndSessionResultFailure(result_details=details)
|
|
438
438
|
|
|
439
439
|
def handle_get_session_request(self, _: AppGetSessionRequest) -> ResultPayload:
|
|
440
440
|
return AppGetSessionResultSuccess(session_id=GriptapeNodes.SessionManager().get_active_session_id())
|
|
@@ -447,14 +447,17 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
447
447
|
try:
|
|
448
448
|
active_session_id = GriptapeNodes.SessionManager().get_active_session_id()
|
|
449
449
|
if active_session_id is None:
|
|
450
|
-
|
|
451
|
-
|
|
450
|
+
details = "Session heartbeat received but no active session found"
|
|
451
|
+
logger.warning(details)
|
|
452
|
+
return SessionHeartbeatResultFailure(result_details=details)
|
|
452
453
|
|
|
453
|
-
|
|
454
|
+
details = f"Session heartbeat successful for session: {active_session_id}"
|
|
455
|
+
logger.debug(details)
|
|
454
456
|
return SessionHeartbeatResultSuccess()
|
|
455
457
|
except Exception as err:
|
|
456
|
-
|
|
457
|
-
|
|
458
|
+
details = f"Failed to handle session heartbeat: {err}"
|
|
459
|
+
logger.error(details)
|
|
460
|
+
return SessionHeartbeatResultFailure(result_details=details)
|
|
458
461
|
|
|
459
462
|
def handle_engine_heartbeat_request(self, request: EngineHeartbeatRequest) -> ResultPayload:
|
|
460
463
|
"""Handle engine heartbeat requests.
|
|
@@ -483,8 +486,9 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
483
486
|
**workflow_info,
|
|
484
487
|
)
|
|
485
488
|
except Exception as err:
|
|
486
|
-
|
|
487
|
-
|
|
489
|
+
details = f"Failed to handle engine heartbeat: {err}"
|
|
490
|
+
logger.error(details)
|
|
491
|
+
return EngineHeartbeatResultFailure(heartbeat_id=request.heartbeat_id, result_details=details)
|
|
488
492
|
|
|
489
493
|
def handle_get_engine_name_request(self, request: GetEngineNameRequest) -> ResultPayload: # noqa: ARG002
|
|
490
494
|
"""Handle requests to get the current engine name."""
|
|
@@ -495,7 +499,7 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
495
499
|
except Exception as err:
|
|
496
500
|
error_message = f"Failed to get engine name: {err}"
|
|
497
501
|
logger.error(error_message)
|
|
498
|
-
return GetEngineNameResultFailure(error_message=error_message)
|
|
502
|
+
return GetEngineNameResultFailure(error_message=error_message, result_details=error_message)
|
|
499
503
|
|
|
500
504
|
def handle_set_engine_name_request(self, request: SetEngineNameRequest) -> ResultPayload:
|
|
501
505
|
"""Handle requests to set a new engine name."""
|
|
@@ -504,7 +508,7 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
504
508
|
if not request.engine_name or not request.engine_name.strip():
|
|
505
509
|
error_message = "Engine name cannot be empty"
|
|
506
510
|
logger.warning(error_message)
|
|
507
|
-
return SetEngineNameResultFailure(error_message=error_message)
|
|
511
|
+
return SetEngineNameResultFailure(error_message=error_message, result_details=error_message)
|
|
508
512
|
|
|
509
513
|
# Set the new engine name
|
|
510
514
|
GriptapeNodes.EngineIdentityManager().set_engine_name(request.engine_name.strip())
|
|
@@ -514,7 +518,7 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
514
518
|
except Exception as err:
|
|
515
519
|
error_message = f"Failed to set engine name: {err}"
|
|
516
520
|
logger.error(error_message)
|
|
517
|
-
return SetEngineNameResultFailure(error_message=error_message)
|
|
521
|
+
return SetEngineNameResultFailure(error_message=error_message, result_details=error_message)
|
|
518
522
|
|
|
519
523
|
def _get_instance_info(self) -> dict[str, str | None]:
|
|
520
524
|
"""Get instance information from environment variables.
|
|
@@ -204,16 +204,18 @@ class AgentManager:
|
|
|
204
204
|
pass # Ignore incomplete JSON
|
|
205
205
|
if isinstance(last_event, FinishTaskEvent):
|
|
206
206
|
if isinstance(last_event.task_output, ErrorArtifact):
|
|
207
|
-
return RunAgentResultFailure(
|
|
207
|
+
return RunAgentResultFailure(
|
|
208
|
+
error=last_event.task_output.to_dict(), result_details=last_event.task_output.to_json()
|
|
209
|
+
)
|
|
208
210
|
if isinstance(last_event.task_output, JsonArtifact):
|
|
209
211
|
return RunAgentResultSuccess(last_event.task_output.to_dict())
|
|
210
212
|
err_msg = f"Unexpected final event: {last_event}"
|
|
211
213
|
logger.error(err_msg)
|
|
212
|
-
return RunAgentResultFailure(ErrorArtifact(last_event).to_dict())
|
|
214
|
+
return RunAgentResultFailure(error=ErrorArtifact(last_event).to_dict(), result_details=err_msg)
|
|
213
215
|
except Exception as e:
|
|
214
216
|
err_msg = f"Error running agent: {e}"
|
|
215
217
|
logger.error(err_msg)
|
|
216
|
-
return RunAgentResultFailure(ErrorArtifact(e).to_dict())
|
|
218
|
+
return RunAgentResultFailure(error=ErrorArtifact(e).to_dict(), result_details=err_msg)
|
|
217
219
|
|
|
218
220
|
def on_handle_configure_agent_request(self, request: ConfigureAgentRequest) -> ResultPayload:
|
|
219
221
|
try:
|
|
@@ -224,7 +226,7 @@ class AgentManager:
|
|
|
224
226
|
except Exception as e:
|
|
225
227
|
details = f"Error configuring agent: {e}"
|
|
226
228
|
logger.error(details)
|
|
227
|
-
return ConfigureAgentResultFailure()
|
|
229
|
+
return ConfigureAgentResultFailure(result_details=details)
|
|
228
230
|
return ConfigureAgentResultSuccess()
|
|
229
231
|
|
|
230
232
|
def on_handle_reset_agent_conversation_memory_request(
|
|
@@ -235,7 +237,7 @@ class AgentManager:
|
|
|
235
237
|
except Exception as e:
|
|
236
238
|
details = f"Error resetting agent conversation memory: {e}"
|
|
237
239
|
logger.error(details)
|
|
238
|
-
return ResetAgentConversationMemoryResultFailure()
|
|
240
|
+
return ResetAgentConversationMemoryResultFailure(result_details=details)
|
|
239
241
|
return ResetAgentConversationMemoryResultSuccess()
|
|
240
242
|
|
|
241
243
|
def on_handle_get_conversation_memory_request(self, _: GetConversationMemoryRequest) -> ResultPayload:
|
|
@@ -244,5 +246,5 @@ class AgentManager:
|
|
|
244
246
|
except Exception as e:
|
|
245
247
|
details = f"Error getting conversation memory: {e}"
|
|
246
248
|
logger.error(details)
|
|
247
|
-
return GetConversationMemoryResultFailure()
|
|
249
|
+
return GetConversationMemoryResultFailure(result_details=details)
|
|
248
250
|
return GetConversationMemoryResultSuccess(runs=conversation_memory)
|
|
@@ -46,6 +46,6 @@ class ArbitraryCodeExecManager:
|
|
|
46
46
|
result = RunArbitraryPythonStringResultSuccess(python_output=captured_output)
|
|
47
47
|
except Exception as e:
|
|
48
48
|
python_output = f"ERROR: {e}"
|
|
49
|
-
result = RunArbitraryPythonStringResultFailure(python_output=python_output)
|
|
49
|
+
result = RunArbitraryPythonStringResultFailure(python_output=python_output, result_details=python_output)
|
|
50
50
|
|
|
51
51
|
return result
|
|
@@ -9,7 +9,9 @@ from pydantic import ValidationError
|
|
|
9
9
|
from xdg_base_dirs import xdg_config_home
|
|
10
10
|
|
|
11
11
|
from griptape_nodes.retained_mode.events.app_events import AppInitializationComplete
|
|
12
|
-
from griptape_nodes.retained_mode.events.base_events import
|
|
12
|
+
from griptape_nodes.retained_mode.events.base_events import (
|
|
13
|
+
ResultPayload,
|
|
14
|
+
)
|
|
13
15
|
from griptape_nodes.retained_mode.events.config_events import (
|
|
14
16
|
GetConfigCategoryRequest,
|
|
15
17
|
GetConfigCategoryResultFailure,
|
|
@@ -353,39 +355,33 @@ class ConfigManager:
|
|
|
353
355
|
if request.category is None or request.category == "":
|
|
354
356
|
# Return the whole shebang. Start with the defaults and then layer on the user config.
|
|
355
357
|
contents = self.merged_config
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
return GetConfigCategoryResultSuccess(contents=contents)
|
|
358
|
+
result_details = "Successfully returned the entire config dictionary."
|
|
359
|
+
return GetConfigCategoryResultSuccess(contents=contents, result_details=result_details)
|
|
359
360
|
|
|
360
361
|
# See if we got something valid.
|
|
361
362
|
find_results = self.get_config_value(request.category)
|
|
362
363
|
if find_results is None:
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
return GetConfigCategoryResultFailure()
|
|
364
|
+
result_details = f"Attempted to get config details for category '{request.category}'. Failed because no such category could be found."
|
|
365
|
+
return GetConfigCategoryResultFailure(result_details=result_details)
|
|
366
366
|
|
|
367
367
|
if not isinstance(find_results, dict):
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
return GetConfigCategoryResultFailure()
|
|
368
|
+
result_details = f"Attempted to get config details for category '{request.category}'. Failed because this was was not a dictionary."
|
|
369
|
+
return GetConfigCategoryResultFailure(result_details=result_details)
|
|
371
370
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
return GetConfigCategoryResultSuccess(contents=find_results)
|
|
371
|
+
result_details = f"Successfully returned the config dictionary for section '{request.category}'."
|
|
372
|
+
return GetConfigCategoryResultSuccess(contents=find_results, result_details=result_details)
|
|
375
373
|
|
|
376
374
|
def on_handle_set_config_category_request(self, request: SetConfigCategoryRequest) -> ResultPayload:
|
|
377
375
|
# Validate the value is a dict
|
|
378
376
|
if not isinstance(request.contents, dict):
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
return SetConfigCategoryResultFailure()
|
|
377
|
+
result_details = f"Attempted to set config details for category '{request.category}'. Failed because the contents provided were not a dictionary."
|
|
378
|
+
return SetConfigCategoryResultFailure(result_details=result_details)
|
|
382
379
|
|
|
383
380
|
if request.category is None or request.category == "":
|
|
384
381
|
# Assign the whole shebang.
|
|
385
382
|
self._write_user_config_delta(request.contents)
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
return SetConfigCategoryResultSuccess()
|
|
383
|
+
result_details = "Successfully assigned the entire config dictionary."
|
|
384
|
+
return SetConfigCategoryResultSuccess(result_details=result_details)
|
|
389
385
|
|
|
390
386
|
self.set_config_value(key=request.category, value=request.contents)
|
|
391
387
|
|
|
@@ -395,29 +391,26 @@ class ConfigManager:
|
|
|
395
391
|
for after_env_var in after_env_vars_set:
|
|
396
392
|
self._update_secret_from_env_var(after_env_var)
|
|
397
393
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
return SetConfigCategoryResultSuccess()
|
|
394
|
+
result_details = f"Successfully assigned the config dictionary for section '{request.category}'."
|
|
395
|
+
return SetConfigCategoryResultSuccess(result_details=result_details)
|
|
401
396
|
|
|
402
397
|
def on_handle_get_config_value_request(self, request: GetConfigValueRequest) -> ResultPayload:
|
|
403
398
|
if request.category_and_key == "":
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
return GetConfigValueResultFailure()
|
|
399
|
+
result_details = "Attempted to get config value but no category or key was specified."
|
|
400
|
+
return GetConfigValueResultFailure(result_details=result_details)
|
|
407
401
|
|
|
408
402
|
# See if we got something valid.
|
|
409
403
|
find_results = self.get_config_value(request.category_and_key)
|
|
410
404
|
if find_results is None:
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
return GetConfigValueResultFailure()
|
|
405
|
+
result_details = f"Attempted to get config value for category.key '{request.category_and_key}'. Failed because no such category.key could be found."
|
|
406
|
+
return GetConfigValueResultFailure(result_details=result_details)
|
|
414
407
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
return GetConfigValueResultSuccess(value=find_results)
|
|
408
|
+
result_details = f"Successfully returned the config value for section '{request.category_and_key}'."
|
|
409
|
+
return GetConfigValueResultSuccess(value=find_results, result_details=result_details)
|
|
418
410
|
|
|
419
411
|
def on_handle_get_config_path_request(self, request: GetConfigPathRequest) -> ResultPayload: # noqa: ARG002
|
|
420
|
-
|
|
412
|
+
result_details = "Successfully returned the config path."
|
|
413
|
+
return GetConfigPathResultSuccess(config_path=str(USER_CONFIG_PATH), result_details=result_details)
|
|
421
414
|
|
|
422
415
|
def on_handle_reset_config_request(self, request: ResetConfigRequest) -> ResultPayload: # noqa: ARG002
|
|
423
416
|
try:
|
|
@@ -425,11 +418,11 @@ class ConfigManager:
|
|
|
425
418
|
self._set_log_level(str(self.merged_config["log_level"]))
|
|
426
419
|
self.workspace_path = Path(self.merged_config["workspace_directory"])
|
|
427
420
|
|
|
428
|
-
|
|
421
|
+
result_details = "Successfully reset user configuration."
|
|
422
|
+
return ResetConfigResultSuccess(result_details=result_details)
|
|
429
423
|
except Exception as e:
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
return ResetConfigResultFailure()
|
|
424
|
+
result_details = f"Attempted to reset user configuration but failed: {e}."
|
|
425
|
+
return ResetConfigResultFailure(result_details=result_details)
|
|
433
426
|
|
|
434
427
|
def _get_diff(self, old_value: Any, new_value: Any) -> dict[Any, Any]:
|
|
435
428
|
"""Generate a diff between the old and new values."""
|
|
@@ -469,9 +462,8 @@ class ConfigManager:
|
|
|
469
462
|
|
|
470
463
|
def on_handle_set_config_value_request(self, request: SetConfigValueRequest) -> ResultPayload:
|
|
471
464
|
if request.category_and_key == "":
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
return SetConfigValueResultFailure()
|
|
465
|
+
result_details = "Attempted to set config value but no category or key was specified."
|
|
466
|
+
return SetConfigValueResultFailure(result_details=result_details)
|
|
475
467
|
|
|
476
468
|
# Fetch the existing value (don't go to the env vars directly; we want the key)
|
|
477
469
|
old_value = self.get_config_value(request.category_and_key, should_load_env_var_if_detected=False)
|
|
@@ -497,16 +489,15 @@ class ConfigManager:
|
|
|
497
489
|
diff = self._get_diff(old_value_copy, request.value)
|
|
498
490
|
formatted_diff = self._format_diff(diff)
|
|
499
491
|
if formatted_diff:
|
|
500
|
-
|
|
492
|
+
result_details = f"Successfully updated {type(request.value).__name__} at '{request.category_and_key}'. Changes:\n{formatted_diff}"
|
|
501
493
|
else:
|
|
502
|
-
|
|
494
|
+
result_details = f"Successfully updated {type(request.value).__name__} at '{request.category_and_key}'. No changes detected."
|
|
503
495
|
else:
|
|
504
|
-
|
|
496
|
+
result_details = f"Successfully updated {type(request.value).__name__} at '{request.category_and_key}'"
|
|
505
497
|
else:
|
|
506
|
-
|
|
498
|
+
result_details = f"Successfully assigned the config value for '{request.category_and_key}':\n\tFROM '{old_value_copy}'\n\tTO: '{request.value}'"
|
|
507
499
|
|
|
508
|
-
|
|
509
|
-
return SetConfigValueResultSuccess()
|
|
500
|
+
return SetConfigValueResultSuccess(result_details=result_details)
|
|
510
501
|
|
|
511
502
|
def _write_user_config_delta(self, user_config_delta: dict) -> None:
|
|
512
503
|
"""Write the user configuration to the config file.
|