griptape-nodes 0.43.0__py3-none-any.whl → 0.44.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- griptape_nodes/__init__.py +41 -51
- griptape_nodes/app/.python-version +0 -0
- griptape_nodes/app/__init__.py +0 -0
- griptape_nodes/app/api.py +35 -6
- griptape_nodes/app/app.py +0 -0
- griptape_nodes/app/watch.py +0 -0
- griptape_nodes/bootstrap/__init__.py +0 -0
- griptape_nodes/bootstrap/workflow_executors/__init__.py +0 -0
- griptape_nodes/bootstrap/workflow_executors/local_workflow_executor.py +7 -1
- griptape_nodes/bootstrap/workflow_executors/subprocess_workflow_executor.py +90 -0
- griptape_nodes/bootstrap/workflow_executors/workflow_executor.py +7 -1
- griptape_nodes/drivers/__init__.py +0 -0
- griptape_nodes/drivers/storage/__init__.py +0 -0
- griptape_nodes/drivers/storage/base_storage_driver.py +53 -0
- griptape_nodes/drivers/storage/griptape_cloud_storage_driver.py +49 -2
- griptape_nodes/drivers/storage/local_storage_driver.py +37 -0
- griptape_nodes/drivers/storage/storage_backend.py +0 -0
- griptape_nodes/exe_types/__init__.py +0 -0
- griptape_nodes/exe_types/connections.py +0 -0
- griptape_nodes/exe_types/core_types.py +113 -8
- griptape_nodes/exe_types/flow.py +0 -0
- griptape_nodes/exe_types/node_types.py +1 -0
- griptape_nodes/exe_types/type_validator.py +0 -0
- griptape_nodes/machines/__init__.py +0 -0
- griptape_nodes/machines/control_flow.py +5 -4
- griptape_nodes/machines/fsm.py +0 -0
- griptape_nodes/machines/node_resolution.py +110 -74
- griptape_nodes/mcp_server/__init__.py +0 -0
- griptape_nodes/mcp_server/server.py +16 -8
- griptape_nodes/mcp_server/ws_request_manager.py +0 -0
- griptape_nodes/node_library/__init__.py +0 -0
- griptape_nodes/node_library/advanced_node_library.py +0 -0
- griptape_nodes/node_library/library_registry.py +0 -0
- griptape_nodes/node_library/workflow_registry.py +0 -0
- griptape_nodes/py.typed +0 -0
- griptape_nodes/retained_mode/__init__.py +0 -0
- griptape_nodes/retained_mode/events/__init__.py +0 -0
- griptape_nodes/retained_mode/events/agent_events.py +0 -0
- griptape_nodes/retained_mode/events/app_events.py +0 -6
- griptape_nodes/retained_mode/events/arbitrary_python_events.py +0 -0
- griptape_nodes/retained_mode/events/base_events.py +6 -7
- griptape_nodes/retained_mode/events/config_events.py +0 -0
- griptape_nodes/retained_mode/events/connection_events.py +0 -0
- griptape_nodes/retained_mode/events/context_events.py +0 -0
- griptape_nodes/retained_mode/events/execution_events.py +0 -0
- griptape_nodes/retained_mode/events/flow_events.py +2 -1
- griptape_nodes/retained_mode/events/generate_request_payload_schemas.py +0 -0
- griptape_nodes/retained_mode/events/library_events.py +0 -0
- griptape_nodes/retained_mode/events/logger_events.py +0 -0
- griptape_nodes/retained_mode/events/node_events.py +36 -0
- griptape_nodes/retained_mode/events/object_events.py +0 -0
- griptape_nodes/retained_mode/events/os_events.py +98 -6
- griptape_nodes/retained_mode/events/parameter_events.py +0 -0
- griptape_nodes/retained_mode/events/payload_registry.py +0 -0
- griptape_nodes/retained_mode/events/secrets_events.py +0 -0
- griptape_nodes/retained_mode/events/static_file_events.py +0 -0
- griptape_nodes/retained_mode/events/validation_events.py +0 -0
- griptape_nodes/retained_mode/events/workflow_events.py +0 -0
- griptape_nodes/retained_mode/griptape_nodes.py +1 -4
- griptape_nodes/retained_mode/managers/__init__.py +0 -0
- griptape_nodes/retained_mode/managers/agent_manager.py +0 -0
- griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py +0 -0
- griptape_nodes/retained_mode/managers/config_manager.py +1 -1
- griptape_nodes/retained_mode/managers/context_manager.py +0 -0
- griptape_nodes/retained_mode/managers/engine_identity_manager.py +0 -0
- griptape_nodes/retained_mode/managers/event_manager.py +0 -0
- griptape_nodes/retained_mode/managers/flow_manager.py +6 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/__init__.py +0 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/data_models.py +0 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_directory.py +0 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_fsm.py +0 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/__init__.py +0 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/base.py +0 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/github.py +0 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/local_file.py +0 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/package.py +0 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/sandbox.py +0 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance.py +0 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_status.py +0 -0
- griptape_nodes/retained_mode/managers/library_manager.py +2 -8
- griptape_nodes/retained_mode/managers/node_manager.py +76 -5
- griptape_nodes/retained_mode/managers/object_manager.py +0 -0
- griptape_nodes/retained_mode/managers/operation_manager.py +0 -0
- griptape_nodes/retained_mode/managers/os_manager.py +133 -8
- griptape_nodes/retained_mode/managers/secrets_manager.py +0 -0
- griptape_nodes/retained_mode/managers/session_manager.py +0 -0
- griptape_nodes/retained_mode/managers/settings.py +0 -0
- griptape_nodes/retained_mode/managers/static_files_manager.py +0 -0
- griptape_nodes/retained_mode/managers/version_compatibility_manager.py +0 -0
- griptape_nodes/retained_mode/managers/workflow_manager.py +54 -5
- griptape_nodes/retained_mode/retained_mode.py +0 -0
- griptape_nodes/retained_mode/utils/__init__.py +0 -0
- griptape_nodes/retained_mode/utils/engine_identity.py +0 -0
- griptape_nodes/retained_mode/utils/name_generator.py +0 -0
- griptape_nodes/traits/__init__.py +0 -0
- griptape_nodes/traits/add_param_button.py +0 -0
- griptape_nodes/traits/button.py +0 -0
- griptape_nodes/traits/clamp.py +0 -0
- griptape_nodes/traits/compare.py +0 -0
- griptape_nodes/traits/compare_images.py +0 -0
- griptape_nodes/traits/file_system_picker.py +18 -0
- griptape_nodes/traits/minmax.py +0 -0
- griptape_nodes/traits/options.py +0 -0
- griptape_nodes/traits/slider.py +0 -0
- griptape_nodes/traits/trait_registry.py +0 -0
- griptape_nodes/traits/traits.json +0 -0
- griptape_nodes/updater/__init__.py +0 -0
- griptape_nodes/updater/__main__.py +0 -0
- griptape_nodes/utils/__init__.py +0 -0
- griptape_nodes/utils/dict_utils.py +0 -0
- griptape_nodes/utils/image_preview.py +0 -0
- griptape_nodes/utils/metaclasses.py +0 -0
- griptape_nodes/utils/version_utils.py +51 -0
- griptape_nodes/version_compatibility/__init__.py +0 -0
- griptape_nodes/version_compatibility/versions/__init__.py +0 -0
- griptape_nodes/version_compatibility/versions/v0_39_0/__init__.py +0 -0
- griptape_nodes/version_compatibility/versions/v0_39_0/modified_parameters_set_removal.py +0 -0
- {griptape_nodes-0.43.0.dist-info → griptape_nodes-0.44.0.dist-info}/METADATA +1 -1
- {griptape_nodes-0.43.0.dist-info → griptape_nodes-0.44.0.dist-info}/RECORD +31 -39
- {griptape_nodes-0.43.0.dist-info → griptape_nodes-0.44.0.dist-info}/WHEEL +1 -1
- griptape_nodes/bootstrap/bootstrap_script.py +0 -54
- griptape_nodes/bootstrap/post_build_install_script.sh +0 -3
- griptape_nodes/bootstrap/pre_build_install_script.sh +0 -4
- griptape_nodes/bootstrap/register_libraries_script.py +0 -32
- griptape_nodes/bootstrap/structure_config.yaml +0 -15
- griptape_nodes/bootstrap/workflow_runners/__init__.py +0 -1
- griptape_nodes/bootstrap/workflow_runners/bootstrap_workflow_runner.py +0 -28
- griptape_nodes/bootstrap/workflow_runners/local_workflow_runner.py +0 -237
- griptape_nodes/bootstrap/workflow_runners/subprocess_workflow_runner.py +0 -62
- griptape_nodes/bootstrap/workflow_runners/workflow_runner.py +0 -11
- {griptape_nodes-0.43.0.dist-info → griptape_nodes-0.44.0.dist-info}/entry_points.txt +0 -0
|
@@ -303,6 +303,7 @@ class GetAllNodeInfoResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess)
|
|
|
303
303
|
|
|
304
304
|
metadata: dict
|
|
305
305
|
node_resolution_state: str
|
|
306
|
+
locked: bool
|
|
306
307
|
connections: ListConnectionsForNodeResultSuccess
|
|
307
308
|
element_id_to_value: dict[str, ParameterInfoValue]
|
|
308
309
|
root_node_element: dict[str, Any]
|
|
@@ -317,6 +318,39 @@ class GetAllNodeInfoResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure)
|
|
|
317
318
|
"""
|
|
318
319
|
|
|
319
320
|
|
|
321
|
+
@dataclass
|
|
322
|
+
@PayloadRegistry.register
|
|
323
|
+
class SetLockNodeStateRequest(WorkflowNotAlteredMixin, RequestPayload):
|
|
324
|
+
"""Lock a node.
|
|
325
|
+
|
|
326
|
+
Use when: Implementing locking functionality, preventing changes to nodes.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
node_name: Name of the node to lock
|
|
330
|
+
lock: Whether to lock or unlock the node. If true, the node will be locked, otherwise it will be unlocked.
|
|
331
|
+
|
|
332
|
+
Results: SetLockNodeStateResultSuccess (node locked) | SetLockNodeStateResultFailure (node not found)
|
|
333
|
+
"""
|
|
334
|
+
|
|
335
|
+
node_name: str | None
|
|
336
|
+
lock: bool
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
@dataclass
|
|
340
|
+
@PayloadRegistry.register
|
|
341
|
+
class SetLockNodeStateResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
342
|
+
"""Node locked successfully."""
|
|
343
|
+
|
|
344
|
+
node_name: str
|
|
345
|
+
locked: bool
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
@dataclass
|
|
349
|
+
@PayloadRegistry.register
|
|
350
|
+
class SetLockNodeStateResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
351
|
+
"""Node failed to lock."""
|
|
352
|
+
|
|
353
|
+
|
|
320
354
|
# A Node's state can be serialized to a sequence of commands that the engine runs.
|
|
321
355
|
@dataclass
|
|
322
356
|
class SerializedNodeCommands:
|
|
@@ -354,6 +388,7 @@ class SerializedNodeCommands:
|
|
|
354
388
|
create_node_command: CreateNodeRequest
|
|
355
389
|
element_modification_commands: list[RequestPayload]
|
|
356
390
|
node_library_details: LibraryNameAndVersion
|
|
391
|
+
lock_node_command: SetLockNodeStateRequest | None = None
|
|
357
392
|
node_uuid: NodeUUID = field(default_factory=lambda: SerializedNodeCommands.NodeUUID(str(uuid4())))
|
|
358
393
|
|
|
359
394
|
|
|
@@ -477,6 +512,7 @@ class SerializedSelectedNodesCommands:
|
|
|
477
512
|
set_parameter_value_commands: dict[
|
|
478
513
|
SerializedNodeCommands.NodeUUID, list[SerializedNodeCommands.IndirectSetParameterValueCommand]
|
|
479
514
|
]
|
|
515
|
+
set_lock_commands_per_node: dict[SerializedNodeCommands.NodeUUID, SetLockNodeStateRequest]
|
|
480
516
|
serialized_connection_commands: list[IndirectConnectionSerialization]
|
|
481
517
|
|
|
482
518
|
|
|
File without changes
|
|
@@ -18,21 +18,23 @@ class FileSystemEntry:
|
|
|
18
18
|
is_dir: bool
|
|
19
19
|
size: int
|
|
20
20
|
modified_time: float
|
|
21
|
+
mime_type: str | None = None # None for directories, mimetype for files
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
@dataclass
|
|
24
25
|
@PayloadRegistry.register
|
|
25
26
|
class OpenAssociatedFileRequest(RequestPayload):
|
|
26
|
-
"""Open a file using the operating system's associated application.
|
|
27
|
+
"""Open a file or directory using the operating system's associated application.
|
|
27
28
|
|
|
28
29
|
Use when: Opening generated files, launching external applications,
|
|
29
|
-
providing file viewing capabilities, implementing file associations
|
|
30
|
+
providing file viewing capabilities, implementing file associations,
|
|
31
|
+
opening folders in system explorer.
|
|
30
32
|
|
|
31
33
|
Args:
|
|
32
|
-
path_to_file: Path to the file to open (mutually exclusive with file_entry)
|
|
34
|
+
path_to_file: Path to the file or directory to open (mutually exclusive with file_entry)
|
|
33
35
|
file_entry: FileSystemEntry object from directory listing (mutually exclusive with path_to_file)
|
|
34
36
|
|
|
35
|
-
Results: OpenAssociatedFileResultSuccess | OpenAssociatedFileResultFailure (
|
|
37
|
+
Results: OpenAssociatedFileResultSuccess | OpenAssociatedFileResultFailure (path not found, no association)
|
|
36
38
|
"""
|
|
37
39
|
|
|
38
40
|
path_to_file: str | None = None
|
|
@@ -42,13 +44,13 @@ class OpenAssociatedFileRequest(RequestPayload):
|
|
|
42
44
|
@dataclass
|
|
43
45
|
@PayloadRegistry.register
|
|
44
46
|
class OpenAssociatedFileResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
45
|
-
"""File opened successfully with associated application."""
|
|
47
|
+
"""File or directory opened successfully with associated application."""
|
|
46
48
|
|
|
47
49
|
|
|
48
50
|
@dataclass
|
|
49
51
|
@PayloadRegistry.register
|
|
50
52
|
class OpenAssociatedFileResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
51
|
-
"""File opening failed. Common causes:
|
|
53
|
+
"""File or directory opening failed. Common causes: path not found, no associated application, permission denied."""
|
|
52
54
|
|
|
53
55
|
|
|
54
56
|
@dataclass
|
|
@@ -138,3 +140,93 @@ class ReadFileResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
|
138
140
|
@PayloadRegistry.register
|
|
139
141
|
class ReadFileResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
140
142
|
"""File reading failed. Common causes: file not found, permission denied, encoding error."""
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@dataclass
|
|
146
|
+
@PayloadRegistry.register
|
|
147
|
+
class CreateFileRequest(RequestPayload):
|
|
148
|
+
"""Create a new file or directory.
|
|
149
|
+
|
|
150
|
+
Use when: Creating files/directories through file picker,
|
|
151
|
+
implementing file creation functionality.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
path: Path where the file/directory should be created (legacy, use directory_path + name instead)
|
|
155
|
+
directory_path: Directory where to create the file/directory (mutually exclusive with path)
|
|
156
|
+
name: Name of the file/directory to create (mutually exclusive with path)
|
|
157
|
+
is_directory: True to create a directory, False for a file
|
|
158
|
+
content: Initial content for files (optional)
|
|
159
|
+
encoding: Text encoding for file content (default: 'utf-8')
|
|
160
|
+
workspace_only: If True, constrain to workspace directory
|
|
161
|
+
|
|
162
|
+
Results: CreateFileResultSuccess | CreateFileResultFailure
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
path: str | None = None
|
|
166
|
+
directory_path: str | None = None
|
|
167
|
+
name: str | None = None
|
|
168
|
+
is_directory: bool = False
|
|
169
|
+
content: str | None = None
|
|
170
|
+
encoding: str = "utf-8"
|
|
171
|
+
workspace_only: bool | None = True
|
|
172
|
+
|
|
173
|
+
def get_full_path(self) -> str:
|
|
174
|
+
"""Get the full path, constructing from directory_path + name if path is not provided."""
|
|
175
|
+
if self.path is not None:
|
|
176
|
+
return self.path
|
|
177
|
+
if self.directory_path is not None and self.name is not None:
|
|
178
|
+
from pathlib import Path
|
|
179
|
+
|
|
180
|
+
return str(Path(self.directory_path) / self.name)
|
|
181
|
+
msg = "Either 'path' or both 'directory_path' and 'name' must be provided"
|
|
182
|
+
raise ValueError(msg)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@dataclass
|
|
186
|
+
@PayloadRegistry.register
|
|
187
|
+
class CreateFileResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
188
|
+
"""File/directory created successfully."""
|
|
189
|
+
|
|
190
|
+
created_path: str
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@dataclass
|
|
194
|
+
@PayloadRegistry.register
|
|
195
|
+
class CreateFileResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
196
|
+
"""File/directory creation failed."""
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
@dataclass
|
|
200
|
+
@PayloadRegistry.register
|
|
201
|
+
class RenameFileRequest(RequestPayload):
|
|
202
|
+
"""Rename a file or directory.
|
|
203
|
+
|
|
204
|
+
Use when: Renaming files/directories through file picker,
|
|
205
|
+
implementing file rename functionality.
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
old_path: Current path of the file/directory to rename
|
|
209
|
+
new_path: New path for the file/directory
|
|
210
|
+
workspace_only: If True, constrain to workspace directory
|
|
211
|
+
|
|
212
|
+
Results: RenameFileResultSuccess | RenameFileResultFailure
|
|
213
|
+
"""
|
|
214
|
+
|
|
215
|
+
old_path: str
|
|
216
|
+
new_path: str
|
|
217
|
+
workspace_only: bool | None = True
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
@dataclass
|
|
221
|
+
@PayloadRegistry.register
|
|
222
|
+
class RenameFileResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
223
|
+
"""File/directory renamed successfully."""
|
|
224
|
+
|
|
225
|
+
old_path: str
|
|
226
|
+
new_path: str
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
@dataclass
|
|
230
|
+
@PayloadRegistry.register
|
|
231
|
+
class RenameFileResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
232
|
+
"""File/directory rename failed."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import importlib.metadata
|
|
4
3
|
import logging
|
|
5
4
|
import os
|
|
6
5
|
import re
|
|
@@ -46,6 +45,7 @@ from griptape_nodes.retained_mode.events.flow_events import (
|
|
|
46
45
|
DeleteFlowRequest,
|
|
47
46
|
)
|
|
48
47
|
from griptape_nodes.utils.metaclasses import SingletonMeta
|
|
48
|
+
from griptape_nodes.utils.version_utils import engine_version
|
|
49
49
|
|
|
50
50
|
if TYPE_CHECKING:
|
|
51
51
|
from griptape_nodes.retained_mode.managers.agent_manager import AgentManager
|
|
@@ -78,9 +78,6 @@ if TYPE_CHECKING:
|
|
|
78
78
|
logger = logging.getLogger("griptape_nodes")
|
|
79
79
|
|
|
80
80
|
|
|
81
|
-
engine_version = importlib.metadata.version("griptape_nodes")
|
|
82
|
-
|
|
83
|
-
|
|
84
81
|
@dataclass
|
|
85
82
|
class Version:
|
|
86
83
|
major: int
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -254,7 +254,7 @@ class ConfigManager:
|
|
|
254
254
|
existing_workflows = self.get_config_value(config_loc)
|
|
255
255
|
if not existing_workflows:
|
|
256
256
|
existing_workflows = []
|
|
257
|
-
existing_workflows.append(workflow_file_name)
|
|
257
|
+
existing_workflows.append(workflow_file_name) if workflow_file_name not in existing_workflows else None
|
|
258
258
|
self.set_config_value(config_loc, existing_workflows)
|
|
259
259
|
|
|
260
260
|
def delete_user_workflow(self, workflow_file_name: str) -> None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1338,6 +1338,7 @@ class FlowManager:
|
|
|
1338
1338
|
|
|
1339
1339
|
serialized_node_commands = []
|
|
1340
1340
|
set_parameter_value_commands_per_node = {} # Maps a node UUID to a list of set parameter value commands
|
|
1341
|
+
set_lock_commands_per_node = {} # Maps a node UUID to a set Lock command, if it exists.
|
|
1341
1342
|
|
|
1342
1343
|
# Now each of the child nodes in the flow.
|
|
1343
1344
|
node_name_to_uuid = {}
|
|
@@ -1379,6 +1380,10 @@ class FlowManager:
|
|
|
1379
1380
|
node_libraries_in_use.add(serialized_node.node_library_details)
|
|
1380
1381
|
# Get the list of set value commands for THIS node.
|
|
1381
1382
|
set_value_commands_list = serialize_node_result.set_parameter_value_commands
|
|
1383
|
+
if serialize_node_result.serialized_node_commands.lock_node_command is not None:
|
|
1384
|
+
set_lock_commands_per_node[serialized_node.node_uuid] = (
|
|
1385
|
+
serialize_node_result.serialized_node_commands.lock_node_command
|
|
1386
|
+
)
|
|
1382
1387
|
set_parameter_value_commands_per_node[serialized_node.node_uuid] = set_value_commands_list
|
|
1383
1388
|
|
|
1384
1389
|
# We'll have to do a patch-up of all the connections, since we can't predict all of the node names being accurate
|
|
@@ -1461,6 +1466,7 @@ class FlowManager:
|
|
|
1461
1466
|
serialized_connections=create_connection_commands,
|
|
1462
1467
|
unique_parameter_uuid_to_values=unique_parameter_uuid_to_values,
|
|
1463
1468
|
set_parameter_value_commands=set_parameter_value_commands_per_node,
|
|
1469
|
+
set_lock_commands_per_node=set_lock_commands_per_node,
|
|
1464
1470
|
sub_flows_commands=sub_flow_commands,
|
|
1465
1471
|
node_libraries_used=node_libraries_in_use,
|
|
1466
1472
|
referenced_workflows=referenced_workflows_in_use,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -96,6 +96,7 @@ from griptape_nodes.retained_mode.managers.library_lifecycle.library_provenance.
|
|
|
96
96
|
)
|
|
97
97
|
from griptape_nodes.retained_mode.managers.library_lifecycle.library_status import LibraryStatus
|
|
98
98
|
from griptape_nodes.retained_mode.managers.os_manager import OSManager
|
|
99
|
+
from griptape_nodes.utils.version_utils import get_complete_version_string
|
|
99
100
|
|
|
100
101
|
if TYPE_CHECKING:
|
|
101
102
|
from collections.abc import Callable
|
|
@@ -1594,14 +1595,7 @@ class LibraryManager:
|
|
|
1594
1595
|
GriptapeNodes.WorkflowManager().on_libraries_initialization_complete()
|
|
1595
1596
|
|
|
1596
1597
|
# Print the engine ready message
|
|
1597
|
-
|
|
1598
|
-
engine_version_result = GriptapeNodes.get_instance().handle_engine_version_request(engine_version_request)
|
|
1599
|
-
if isinstance(engine_version_result, GetEngineVersionResultSuccess):
|
|
1600
|
-
engine_version = (
|
|
1601
|
-
f"v{engine_version_result.major}.{engine_version_result.minor}.{engine_version_result.patch}"
|
|
1602
|
-
)
|
|
1603
|
-
else:
|
|
1604
|
-
engine_version = "<UNKNOWN ENGINE VERSION>"
|
|
1598
|
+
engine_version = get_complete_version_string()
|
|
1605
1599
|
|
|
1606
1600
|
# Get current session ID
|
|
1607
1601
|
session_id = GriptapeNodes.get_session_id()
|
|
@@ -81,6 +81,9 @@ from griptape_nodes.retained_mode.events.node_events import (
|
|
|
81
81
|
SerializeNodeToCommandsResultSuccess,
|
|
82
82
|
SerializeSelectedNodesToCommandsRequest,
|
|
83
83
|
SerializeSelectedNodesToCommandsResultSuccess,
|
|
84
|
+
SetLockNodeStateRequest,
|
|
85
|
+
SetLockNodeStateResultFailure,
|
|
86
|
+
SetLockNodeStateResultSuccess,
|
|
84
87
|
SetNodeMetadataRequest,
|
|
85
88
|
SetNodeMetadataResultFailure,
|
|
86
89
|
SetNodeMetadataResultSuccess,
|
|
@@ -178,6 +181,7 @@ class NodeManager:
|
|
|
178
181
|
DeserializeSelectedNodesFromCommandsRequest, self.on_deserialize_selected_nodes_from_commands
|
|
179
182
|
)
|
|
180
183
|
event_manager.assign_manager_to_request_type(DuplicateSelectedNodesRequest, self.on_duplicate_selected_nodes)
|
|
184
|
+
event_manager.assign_manager_to_request_type(SetLockNodeStateRequest, self.on_toggle_lock_node_request)
|
|
181
185
|
|
|
182
186
|
def handle_node_rename(self, old_name: str, new_name: str) -> None:
|
|
183
187
|
# Get the node itself
|
|
@@ -781,6 +785,13 @@ class NodeManager:
|
|
|
781
785
|
result = AddParameterToNodeResultFailure()
|
|
782
786
|
return result
|
|
783
787
|
|
|
788
|
+
# Check if node is locked
|
|
789
|
+
if node.lock:
|
|
790
|
+
details = f"Attempted to add Parameter '{request.parameter_name}' to Node '{node_name}'. Failed because the Node was locked."
|
|
791
|
+
logger.error(details)
|
|
792
|
+
result = AddParameterToNodeResultFailure()
|
|
793
|
+
return result
|
|
794
|
+
|
|
784
795
|
if request.parent_container_name and not request.initial_setup:
|
|
785
796
|
parameter = node.get_parameter_by_name(request.parent_container_name)
|
|
786
797
|
if parameter is None:
|
|
@@ -923,7 +934,13 @@ class NodeManager:
|
|
|
923
934
|
|
|
924
935
|
result = RemoveParameterFromNodeResultFailure()
|
|
925
936
|
return result
|
|
937
|
+
# Check if the node is locked
|
|
938
|
+
if node.lock:
|
|
939
|
+
details = f"Attempted to remove Element '{request.parameter_name}' from Node '{node_name}'. Failed because the Node was locked."
|
|
940
|
+
logger.error(details)
|
|
926
941
|
|
|
942
|
+
result = RemoveParameterFromNodeResultFailure()
|
|
943
|
+
return result
|
|
927
944
|
# Does the Element actually exist on the Node?
|
|
928
945
|
element = node.get_element_by_name_and_type(request.parameter_name)
|
|
929
946
|
if element is None:
|
|
@@ -1246,7 +1263,7 @@ class NodeManager:
|
|
|
1246
1263
|
|
|
1247
1264
|
return None
|
|
1248
1265
|
|
|
1249
|
-
def on_alter_parameter_details_request(self, request: AlterParameterDetailsRequest) -> ResultPayload: # noqa: C901
|
|
1266
|
+
def on_alter_parameter_details_request(self, request: AlterParameterDetailsRequest) -> ResultPayload: # noqa: C901, PLR0911
|
|
1250
1267
|
node_name = request.node_name
|
|
1251
1268
|
node = None
|
|
1252
1269
|
|
|
@@ -1269,6 +1286,12 @@ class NodeManager:
|
|
|
1269
1286
|
|
|
1270
1287
|
return AlterParameterDetailsResultFailure()
|
|
1271
1288
|
|
|
1289
|
+
# Is the node locked?
|
|
1290
|
+
if node.lock:
|
|
1291
|
+
details = f"Attempted to alter details for Parameter '{request.parameter_name}' from Node '{node_name}'. Failed because the Node was locked."
|
|
1292
|
+
logger.error(details)
|
|
1293
|
+
return AlterParameterDetailsResultFailure()
|
|
1294
|
+
|
|
1272
1295
|
# Does the Element actually exist on the Node?
|
|
1273
1296
|
element = node.get_element_by_name_and_type(request.parameter_name)
|
|
1274
1297
|
if element is None:
|
|
@@ -1397,6 +1420,12 @@ class NodeManager:
|
|
|
1397
1420
|
logger.error(details)
|
|
1398
1421
|
return SetParameterValueResultFailure()
|
|
1399
1422
|
|
|
1423
|
+
# Is the node locked?
|
|
1424
|
+
if node.lock:
|
|
1425
|
+
details = f"Attempted to set parameter '{param_name}' value on node '{node_name}'. Failed because the Node was locked."
|
|
1426
|
+
logger.error(details)
|
|
1427
|
+
return SetParameterValueResultFailure()
|
|
1428
|
+
|
|
1400
1429
|
# Does the Parameter actually exist on the Node?
|
|
1401
1430
|
parameter = node.get_parameter_by_name(param_name)
|
|
1402
1431
|
if parameter is None:
|
|
@@ -1596,6 +1625,7 @@ class NodeManager:
|
|
|
1596
1625
|
result = GetAllNodeInfoResultSuccess(
|
|
1597
1626
|
metadata=get_metadata_success.metadata,
|
|
1598
1627
|
node_resolution_state=get_resolution_state_success.state,
|
|
1628
|
+
locked=node.lock,
|
|
1599
1629
|
connections=list_connections_success,
|
|
1600
1630
|
element_id_to_value=element_id_to_value,
|
|
1601
1631
|
root_node_element=element_details,
|
|
@@ -1837,7 +1867,7 @@ class NodeManager:
|
|
|
1837
1867
|
validation_succeeded=(len(all_exceptions) == 0), exceptions=all_exceptions
|
|
1838
1868
|
)
|
|
1839
1869
|
|
|
1840
|
-
def on_serialize_node_to_commands(self, request: SerializeNodeToCommandsRequest) -> ResultPayload: # noqa: C901, PLR0912
|
|
1870
|
+
def on_serialize_node_to_commands(self, request: SerializeNodeToCommandsRequest) -> ResultPayload: # noqa: C901, PLR0912, PLR0915
|
|
1841
1871
|
node_name = request.node_name
|
|
1842
1872
|
node = None
|
|
1843
1873
|
|
|
@@ -1923,12 +1953,19 @@ class NodeManager:
|
|
|
1923
1953
|
)
|
|
1924
1954
|
if set_param_value_requests is not None:
|
|
1925
1955
|
set_value_commands.extend(set_param_value_requests)
|
|
1926
|
-
|
|
1956
|
+
else:
|
|
1957
|
+
create_node_request.resolution = NodeResolutionState.UNRESOLVED.value
|
|
1958
|
+
# now check if locked
|
|
1959
|
+
if node.lock:
|
|
1960
|
+
lock_command = SetLockNodeStateRequest(node_name=None, lock=True)
|
|
1961
|
+
else:
|
|
1962
|
+
lock_command = None
|
|
1927
1963
|
# Hooray
|
|
1928
1964
|
serialized_node_commands = SerializedNodeCommands(
|
|
1929
1965
|
create_node_command=create_node_request,
|
|
1930
1966
|
element_modification_commands=element_modification_commands,
|
|
1931
1967
|
node_library_details=library_details,
|
|
1968
|
+
lock_node_command=lock_command,
|
|
1932
1969
|
)
|
|
1933
1970
|
details = f"Successfully serialized node '{node_name}' into commands."
|
|
1934
1971
|
logger.debug(details)
|
|
@@ -2073,7 +2110,6 @@ class NodeManager:
|
|
|
2073
2110
|
details = f"Attempted to deserialize a serialized set of Node Creation commands. Failed to execute an element command for node '{node_name}'."
|
|
2074
2111
|
logger.error(details)
|
|
2075
2112
|
return DeserializeNodeFromCommandsResultFailure()
|
|
2076
|
-
|
|
2077
2113
|
details = f"Successfully deserialized a serialized set of Node Creation commands for node '{node_name}'."
|
|
2078
2114
|
logger.debug(details)
|
|
2079
2115
|
return DeserializeNodeFromCommandsResultSuccess(node_name=node_name)
|
|
@@ -2091,6 +2127,8 @@ class NodeManager:
|
|
|
2091
2127
|
connections_to_serialize = []
|
|
2092
2128
|
# This is also node_uuid to the parameter serialization command.
|
|
2093
2129
|
parameter_commands = {}
|
|
2130
|
+
# This is node_uuid to lock commands.
|
|
2131
|
+
lock_commands = {}
|
|
2094
2132
|
# I need to store node names and parameter names to UUID
|
|
2095
2133
|
unique_uuid_to_values = {}
|
|
2096
2134
|
# And track how values map into that map.
|
|
@@ -2111,6 +2149,7 @@ class NodeManager:
|
|
|
2111
2149
|
node_commands[node_name] = result.serialized_node_commands
|
|
2112
2150
|
node_name_to_uuid[node_name] = result.serialized_node_commands.node_uuid
|
|
2113
2151
|
parameter_commands[result.serialized_node_commands.node_uuid] = result.set_parameter_value_commands
|
|
2152
|
+
lock_commands[result.serialized_node_commands.node_uuid] = result.serialized_node_commands.lock_node_command
|
|
2114
2153
|
try:
|
|
2115
2154
|
flow_name = self.get_node_parent_flow_by_name(node_name)
|
|
2116
2155
|
GriptapeNodes.FlowManager().get_flow_by_name(flow_name)
|
|
@@ -2146,6 +2185,7 @@ class NodeManager:
|
|
|
2146
2185
|
serialized_node_commands=list(node_commands.values()),
|
|
2147
2186
|
serialized_connection_commands=serialized_connections,
|
|
2148
2187
|
set_parameter_value_commands=parameter_commands,
|
|
2188
|
+
set_lock_commands_per_node=lock_commands,
|
|
2149
2189
|
)
|
|
2150
2190
|
# Set everything in the clipboard!
|
|
2151
2191
|
GriptapeNodes.ContextManager()._clipboard.node_commands = final_result
|
|
@@ -2209,6 +2249,12 @@ class NodeManager:
|
|
|
2209
2249
|
if not set_parameter_result.succeeded():
|
|
2210
2250
|
details = f"Failed to set parameter value for {param_request.parameter_name} on node {param_request.node_name}"
|
|
2211
2251
|
logger.warning(details)
|
|
2252
|
+
lock_command = commands.set_lock_commands_per_node[node_command.node_uuid]
|
|
2253
|
+
if lock_command is not None:
|
|
2254
|
+
lock_node_result = GriptapeNodes.handle_request(lock_command)
|
|
2255
|
+
if not lock_node_result.succeeded():
|
|
2256
|
+
details = f"Failed to lock node {lock_command.node_name}"
|
|
2257
|
+
logger.warning(details)
|
|
2212
2258
|
# create Connections
|
|
2213
2259
|
for connection_command in connections:
|
|
2214
2260
|
connection_request = CreateConnectionRequest(
|
|
@@ -2389,7 +2435,7 @@ class NodeManager:
|
|
|
2389
2435
|
commands.append(output_command)
|
|
2390
2436
|
return commands if commands else None
|
|
2391
2437
|
|
|
2392
|
-
def on_rename_parameter_request(self, request: RenameParameterRequest) -> ResultPayload: # noqa: C901, PLR0912
|
|
2438
|
+
def on_rename_parameter_request(self, request: RenameParameterRequest) -> ResultPayload: # noqa: C901, PLR0911, PLR0912
|
|
2393
2439
|
"""Handle renaming a parameter on a node.
|
|
2394
2440
|
|
|
2395
2441
|
Args:
|
|
@@ -2415,6 +2461,12 @@ class NodeManager:
|
|
|
2415
2461
|
logger.error(details)
|
|
2416
2462
|
return RenameParameterResultFailure()
|
|
2417
2463
|
|
|
2464
|
+
# Is the node locked?
|
|
2465
|
+
if node.lock:
|
|
2466
|
+
details = f"Attempted to rename Parameter '{request.parameter_name}' on Node '{node_name}'. Failed because the Node is locked."
|
|
2467
|
+
logger.error(details)
|
|
2468
|
+
return RenameParameterResultFailure()
|
|
2469
|
+
|
|
2418
2470
|
# Get the parameter
|
|
2419
2471
|
parameter = node.get_parameter_by_name(request.parameter_name)
|
|
2420
2472
|
if parameter is None:
|
|
@@ -2469,3 +2521,22 @@ class NodeManager:
|
|
|
2469
2521
|
return RenameParameterResultSuccess(
|
|
2470
2522
|
old_parameter_name=old_name, new_parameter_name=request.new_parameter_name, node_name=node_name
|
|
2471
2523
|
)
|
|
2524
|
+
|
|
2525
|
+
def on_toggle_lock_node_request(self, request: SetLockNodeStateRequest) -> ResultPayload:
|
|
2526
|
+
node_name = request.node_name
|
|
2527
|
+
if node_name is None:
|
|
2528
|
+
if not GriptapeNodes.ContextManager().has_current_node():
|
|
2529
|
+
details = "Attempted to lock node in the Current Context. Failed because the Current Context was empty."
|
|
2530
|
+
logger.error(details)
|
|
2531
|
+
return SetLockNodeStateResultFailure()
|
|
2532
|
+
node = GriptapeNodes.ContextManager().get_current_node()
|
|
2533
|
+
node_name = node.name
|
|
2534
|
+
else:
|
|
2535
|
+
try:
|
|
2536
|
+
node = self.get_node_by_name(node_name)
|
|
2537
|
+
except ValueError as err:
|
|
2538
|
+
details = f"Attempted to lock node '{request.node_name}'. Failed because the Node could not be found. Error: {err}"
|
|
2539
|
+
logger.error(details)
|
|
2540
|
+
return SetLockNodeStateResultFailure()
|
|
2541
|
+
node.lock = request.lock
|
|
2542
|
+
return SetLockNodeStateResultSuccess(node_name=node_name, locked=node.lock)
|
|
File without changes
|
|
File without changes
|