griptape-nodes 0.43.1__py3-none-any.whl → 0.45.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 +46 -52
- griptape_nodes/app/.python-version +0 -0
- griptape_nodes/app/__init__.py +0 -0
- griptape_nodes/app/api.py +37 -41
- griptape_nodes/app/app.py +70 -3
- griptape_nodes/app/watch.py +5 -2
- 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 +90 -0
- griptape_nodes/drivers/storage/griptape_cloud_storage_driver.py +48 -0
- 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 +222 -17
- griptape_nodes/exe_types/flow.py +0 -0
- griptape_nodes/exe_types/node_types.py +20 -5
- 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 +29 -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 +3 -8
- griptape_nodes/retained_mode/events/arbitrary_python_events.py +0 -0
- griptape_nodes/retained_mode/events/base_events.py +15 -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/sync_events.py +60 -0
- griptape_nodes/retained_mode/events/validation_events.py +0 -0
- griptape_nodes/retained_mode/events/workflow_events.py +231 -0
- griptape_nodes/retained_mode/griptape_nodes.py +9 -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 +8 -26
- griptape_nodes/retained_mode/managers/node_manager.py +78 -7
- griptape_nodes/retained_mode/managers/object_manager.py +0 -0
- griptape_nodes/retained_mode/managers/operation_manager.py +7 -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 +5 -0
- griptape_nodes/retained_mode/managers/static_files_manager.py +0 -0
- griptape_nodes/retained_mode/managers/sync_manager.py +498 -0
- griptape_nodes/retained_mode/managers/version_compatibility_manager.py +0 -0
- griptape_nodes/retained_mode/managers/workflow_manager.py +736 -33
- griptape_nodes/retained_mode/retained_mode.py +23 -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 +4 -2
- 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/uv_utils.py +18 -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.1.dist-info → griptape_nodes-0.45.0.dist-info}/METADATA +2 -1
- {griptape_nodes-0.43.1.dist-info → griptape_nodes-0.45.0.dist-info}/RECORD +42 -47
- {griptape_nodes-0.43.1.dist-info → griptape_nodes-0.45.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.1.dist-info → griptape_nodes-0.45.0.dist-info}/entry_points.txt +0 -0
|
@@ -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
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from griptape_nodes.retained_mode.events.base_events import (
|
|
4
|
+
AppPayload,
|
|
5
|
+
RequestPayload,
|
|
6
|
+
ResultPayloadFailure,
|
|
7
|
+
ResultPayloadSuccess,
|
|
8
|
+
WorkflowNotAlteredMixin,
|
|
9
|
+
)
|
|
10
|
+
from griptape_nodes.retained_mode.events.payload_registry import PayloadRegistry
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
@PayloadRegistry.register
|
|
15
|
+
class StartSyncAllCloudWorkflowsRequest(RequestPayload):
|
|
16
|
+
"""Start syncing all cloud workflows to local synced_workflows directory.
|
|
17
|
+
|
|
18
|
+
Use when: Initiating download of all workflow files from cloud storage, keeping local sync directory updated,
|
|
19
|
+
preparing for offline workflow development, backing up cloud workflows locally.
|
|
20
|
+
|
|
21
|
+
Results: StartSyncAllCloudWorkflowsResultSuccess (sync started) | StartSyncAllCloudWorkflowsResultFailure (failed to start)
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
@PayloadRegistry.register
|
|
27
|
+
class StartSyncAllCloudWorkflowsResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
28
|
+
"""Cloud workflow sync started successfully.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
sync_directory: Path to the local sync directory where files will be saved
|
|
32
|
+
total_workflows: Number of workflows that will be synced
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
sync_directory: str
|
|
36
|
+
total_workflows: int
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
@PayloadRegistry.register
|
|
41
|
+
class StartSyncAllCloudWorkflowsResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
42
|
+
"""Cloud workflow sync failed to start. Common causes: cloud not configured, network error, storage error, permission denied."""
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
@PayloadRegistry.register
|
|
47
|
+
class SyncComplete(AppPayload):
|
|
48
|
+
"""Cloud workflow sync completed successfully.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
sync_directory: Path to the local sync directory where files were saved
|
|
52
|
+
synced_workflows: List of workflows that were successfully synced
|
|
53
|
+
failed_workflows: List of workflows that failed to sync
|
|
54
|
+
total_workflows: Total number of workflows that were processed
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
sync_directory: str
|
|
58
|
+
synced_workflows: list[str]
|
|
59
|
+
failed_workflows: list[str]
|
|
60
|
+
total_workflows: int
|
|
File without changes
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
+
from typing import Literal
|
|
2
3
|
|
|
3
4
|
from griptape_nodes.node_library.workflow_registry import WorkflowMetadata
|
|
4
5
|
from griptape_nodes.retained_mode.events.base_events import (
|
|
@@ -364,3 +365,233 @@ class PublishWorkflowResultSuccess(ResultPayloadSuccess):
|
|
|
364
365
|
@PayloadRegistry.register
|
|
365
366
|
class PublishWorkflowResultFailure(ResultPayloadFailure):
|
|
366
367
|
"""Workflow publish failed. Common causes: workflow not found, publish error, file system error."""
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
@dataclass
|
|
371
|
+
@PayloadRegistry.register
|
|
372
|
+
class BranchWorkflowRequest(RequestPayload):
|
|
373
|
+
"""Create a branch (copy) of an existing workflow with branch tracking.
|
|
374
|
+
|
|
375
|
+
Use when: Creating workflow variants, branching workflows for experimentation,
|
|
376
|
+
creating personal copies of shared workflows, preparing for workflow collaboration.
|
|
377
|
+
|
|
378
|
+
Args:
|
|
379
|
+
workflow_name: Name of the workflow to branch
|
|
380
|
+
branched_workflow_name: Name for the branched workflow (None for auto-generated)
|
|
381
|
+
|
|
382
|
+
Results: BranchWorkflowResultSuccess (with branch name) | BranchWorkflowResultFailure (branch error)
|
|
383
|
+
"""
|
|
384
|
+
|
|
385
|
+
workflow_name: str
|
|
386
|
+
branched_workflow_name: str | None = None
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
@dataclass
|
|
390
|
+
@PayloadRegistry.register
|
|
391
|
+
class BranchWorkflowResultSuccess(WorkflowAlteredMixin, ResultPayloadSuccess):
|
|
392
|
+
"""Workflow branched successfully.
|
|
393
|
+
|
|
394
|
+
Args:
|
|
395
|
+
branched_workflow_name: Name of the created branch
|
|
396
|
+
original_workflow_name: Name of the original workflow
|
|
397
|
+
"""
|
|
398
|
+
|
|
399
|
+
branched_workflow_name: str
|
|
400
|
+
original_workflow_name: str
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
@dataclass
|
|
404
|
+
@PayloadRegistry.register
|
|
405
|
+
class BranchWorkflowResultFailure(ResultPayloadFailure):
|
|
406
|
+
"""Workflow branch failed. Common causes: workflow not found, name conflict, save error."""
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
@dataclass
|
|
410
|
+
@PayloadRegistry.register
|
|
411
|
+
class MergeWorkflowBranchRequest(RequestPayload):
|
|
412
|
+
"""Merge a branch back into its source workflow, removing the branch when complete.
|
|
413
|
+
|
|
414
|
+
Use when: Integrating branch changes back into the original workflow, consolidating
|
|
415
|
+
successful branch experiments, applying approved branch modifications to source.
|
|
416
|
+
|
|
417
|
+
Args:
|
|
418
|
+
workflow_name: Name of the branch workflow to merge back into its source
|
|
419
|
+
|
|
420
|
+
Results: MergeWorkflowBranchResultSuccess (with merge details) | MergeWorkflowBranchResultFailure (merge error)
|
|
421
|
+
"""
|
|
422
|
+
|
|
423
|
+
workflow_name: str
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
@dataclass
|
|
427
|
+
@PayloadRegistry.register
|
|
428
|
+
class MergeWorkflowBranchResultSuccess(WorkflowAlteredMixin, ResultPayloadSuccess):
|
|
429
|
+
"""Branch merge back to source completed successfully.
|
|
430
|
+
|
|
431
|
+
Args:
|
|
432
|
+
merged_workflow_name: Name of the source workflow after merge
|
|
433
|
+
"""
|
|
434
|
+
|
|
435
|
+
merged_workflow_name: str
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
@dataclass
|
|
439
|
+
@PayloadRegistry.register
|
|
440
|
+
class MergeWorkflowBranchResultFailure(ResultPayloadFailure):
|
|
441
|
+
"""Workflow branch merge failed."""
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
@dataclass
|
|
445
|
+
@PayloadRegistry.register
|
|
446
|
+
class ResetWorkflowBranchRequest(RequestPayload):
|
|
447
|
+
"""Reset a branch to match its source workflow, discarding branch changes.
|
|
448
|
+
|
|
449
|
+
Use when: Discarding branch modifications, reverting branch to source state,
|
|
450
|
+
abandoning branch experiments, syncing branch with latest source changes.
|
|
451
|
+
|
|
452
|
+
Args:
|
|
453
|
+
workflow_name: Name of the branch workflow to reset to its source
|
|
454
|
+
|
|
455
|
+
Results: ResetWorkflowBranchResultSuccess (with reset details) | ResetWorkflowBranchResultFailure (reset error)
|
|
456
|
+
"""
|
|
457
|
+
|
|
458
|
+
workflow_name: str
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
@dataclass
|
|
462
|
+
@PayloadRegistry.register
|
|
463
|
+
class ResetWorkflowBranchResultSuccess(WorkflowAlteredMixin, ResultPayloadSuccess):
|
|
464
|
+
"""Branch reset to source completed successfully.
|
|
465
|
+
|
|
466
|
+
Args:
|
|
467
|
+
reset_workflow_name: Name of the branch workflow after reset
|
|
468
|
+
"""
|
|
469
|
+
|
|
470
|
+
reset_workflow_name: str
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
@dataclass
|
|
474
|
+
@PayloadRegistry.register
|
|
475
|
+
class ResetWorkflowBranchResultFailure(ResultPayloadFailure):
|
|
476
|
+
"""Workflow branch reset failed. Common causes: workflows not branch-related, reset conflict, save error."""
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
@dataclass
|
|
480
|
+
@PayloadRegistry.register
|
|
481
|
+
class CompareWorkflowsRequest(RequestPayload):
|
|
482
|
+
"""Compare two workflows to determine if one is ahead, behind, or up-to-date relative to the other.
|
|
483
|
+
|
|
484
|
+
Use when: Checking if branched workflows need updates, determining if local changes exist,
|
|
485
|
+
managing workflow synchronization, preparing for merge operations.
|
|
486
|
+
|
|
487
|
+
Args:
|
|
488
|
+
workflow_name: Name of the workflow to evaluate
|
|
489
|
+
compare_workflow_name: Name of the workflow to compare against
|
|
490
|
+
|
|
491
|
+
Results: CompareWorkflowsResultSuccess (with status details) | CompareWorkflowsResultFailure (evaluation error)
|
|
492
|
+
"""
|
|
493
|
+
|
|
494
|
+
workflow_name: str
|
|
495
|
+
compare_workflow_name: str
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
@dataclass
|
|
499
|
+
@PayloadRegistry.register
|
|
500
|
+
class CompareWorkflowsResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
501
|
+
"""Workflow comparison completed successfully.
|
|
502
|
+
|
|
503
|
+
Args:
|
|
504
|
+
workflow_name: Name of the evaluated workflow
|
|
505
|
+
compare_workflow_name: Name of the workflow being compared against (if any)
|
|
506
|
+
status: Status relative to source - "up_to_date", "ahead", "behind", "diverged", or "no_source"
|
|
507
|
+
workflow_last_modified: Last modified timestamp of the workflow
|
|
508
|
+
source_last_modified: Last modified timestamp of the source (if exists)
|
|
509
|
+
details: Additional details about the comparison
|
|
510
|
+
"""
|
|
511
|
+
|
|
512
|
+
workflow_name: str
|
|
513
|
+
compare_workflow_name: str | None
|
|
514
|
+
status: Literal["up_to_date", "ahead", "behind", "diverged", "no_source"]
|
|
515
|
+
workflow_last_modified: str | None
|
|
516
|
+
source_last_modified: str | None
|
|
517
|
+
details: str
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
@dataclass
|
|
521
|
+
@PayloadRegistry.register
|
|
522
|
+
class CompareWorkflowsResultFailure(ResultPayloadFailure):
|
|
523
|
+
"""Workflow comparison failed. Common causes: workflow not found, source not accessible, comparison error."""
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
@dataclass
|
|
527
|
+
@PayloadRegistry.register
|
|
528
|
+
class MoveWorkflowRequest(RequestPayload):
|
|
529
|
+
"""Move a workflow to a different directory in the workspace.
|
|
530
|
+
|
|
531
|
+
Use when: Organizing workflows into directories, restructuring workflow hierarchies,
|
|
532
|
+
moving workflows to categorized folders, cleaning up workspace organization.
|
|
533
|
+
|
|
534
|
+
Args:
|
|
535
|
+
workflow_name: Name of the workflow to move
|
|
536
|
+
target_directory: Target directory path relative to workspace root
|
|
537
|
+
|
|
538
|
+
Results: MoveWorkflowResultSuccess (with new path) | MoveWorkflowResultFailure (move error)
|
|
539
|
+
"""
|
|
540
|
+
|
|
541
|
+
workflow_name: str
|
|
542
|
+
target_directory: str
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
@dataclass
|
|
546
|
+
@PayloadRegistry.register
|
|
547
|
+
class MoveWorkflowResultSuccess(WorkflowAlteredMixin, ResultPayloadSuccess):
|
|
548
|
+
"""Workflow moved successfully.
|
|
549
|
+
|
|
550
|
+
Args:
|
|
551
|
+
moved_file_path: New file path after the move
|
|
552
|
+
"""
|
|
553
|
+
|
|
554
|
+
moved_file_path: str
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
@dataclass
|
|
558
|
+
@PayloadRegistry.register
|
|
559
|
+
class MoveWorkflowResultFailure(ResultPayloadFailure):
|
|
560
|
+
"""Workflow move failed. Common causes: workflow not found, invalid target directory, file system error."""
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
@dataclass
|
|
564
|
+
@PayloadRegistry.register
|
|
565
|
+
class RegisterWorkflowsFromConfigRequest(RequestPayload):
|
|
566
|
+
"""Register workflows from configuration section.
|
|
567
|
+
|
|
568
|
+
Use when: Loading workflows from configuration after library initialization,
|
|
569
|
+
registering workflows from synced directories, batch workflow registration.
|
|
570
|
+
|
|
571
|
+
Args:
|
|
572
|
+
config_section: Configuration section path containing workflow paths to register
|
|
573
|
+
|
|
574
|
+
Results: RegisterWorkflowsFromConfigResultSuccess (with count) | RegisterWorkflowsFromConfigResultFailure (registration error)
|
|
575
|
+
"""
|
|
576
|
+
|
|
577
|
+
config_section: str
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
@dataclass
|
|
581
|
+
@PayloadRegistry.register
|
|
582
|
+
class RegisterWorkflowsFromConfigResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
583
|
+
"""Workflows registered from configuration successfully.
|
|
584
|
+
|
|
585
|
+
Args:
|
|
586
|
+
succeeded_workflows: List of workflow names that were successfully registered
|
|
587
|
+
failed_workflows: List of workflow names that failed to register
|
|
588
|
+
"""
|
|
589
|
+
|
|
590
|
+
succeeded_workflows: list[str]
|
|
591
|
+
failed_workflows: list[str]
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
@dataclass
|
|
595
|
+
@PayloadRegistry.register
|
|
596
|
+
class RegisterWorkflowsFromConfigResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
597
|
+
"""Workflow registration from configuration failed. Common causes: configuration not found, invalid paths, registration errors."""
|
|
@@ -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
|
|
@@ -69,6 +69,7 @@ if TYPE_CHECKING:
|
|
|
69
69
|
from griptape_nodes.retained_mode.managers.static_files_manager import (
|
|
70
70
|
StaticFilesManager,
|
|
71
71
|
)
|
|
72
|
+
from griptape_nodes.retained_mode.managers.sync_manager import SyncManager
|
|
72
73
|
from griptape_nodes.retained_mode.managers.version_compatibility_manager import (
|
|
73
74
|
VersionCompatibilityManager,
|
|
74
75
|
)
|
|
@@ -78,9 +79,6 @@ if TYPE_CHECKING:
|
|
|
78
79
|
logger = logging.getLogger("griptape_nodes")
|
|
79
80
|
|
|
80
81
|
|
|
81
|
-
engine_version = importlib.metadata.version("griptape_nodes")
|
|
82
|
-
|
|
83
|
-
|
|
84
82
|
@dataclass
|
|
85
83
|
class Version:
|
|
86
84
|
major: int
|
|
@@ -141,6 +139,7 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
141
139
|
_version_compatibility_manager: VersionCompatibilityManager
|
|
142
140
|
_session_manager: SessionManager
|
|
143
141
|
_engine_identity_manager: EngineIdentityManager
|
|
142
|
+
_sync_manager: SyncManager
|
|
144
143
|
|
|
145
144
|
def __init__(self) -> None:
|
|
146
145
|
from griptape_nodes.retained_mode.managers.agent_manager import AgentManager
|
|
@@ -164,6 +163,7 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
164
163
|
from griptape_nodes.retained_mode.managers.static_files_manager import (
|
|
165
164
|
StaticFilesManager,
|
|
166
165
|
)
|
|
166
|
+
from griptape_nodes.retained_mode.managers.sync_manager import SyncManager
|
|
167
167
|
from griptape_nodes.retained_mode.managers.version_compatibility_manager import (
|
|
168
168
|
VersionCompatibilityManager,
|
|
169
169
|
)
|
|
@@ -192,6 +192,7 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
192
192
|
self._version_compatibility_manager = VersionCompatibilityManager(self._event_manager)
|
|
193
193
|
self._session_manager = SessionManager(self._event_manager)
|
|
194
194
|
self._engine_identity_manager = EngineIdentityManager(self._event_manager)
|
|
195
|
+
self._sync_manager = SyncManager(self._event_manager, self._config_manager)
|
|
195
196
|
|
|
196
197
|
# Assign handlers now that these are created.
|
|
197
198
|
self._event_manager.assign_manager_to_request_type(
|
|
@@ -329,6 +330,10 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
329
330
|
def EngineIdentityManager(cls) -> EngineIdentityManager:
|
|
330
331
|
return GriptapeNodes.get_instance()._engine_identity_manager
|
|
331
332
|
|
|
333
|
+
@classmethod
|
|
334
|
+
def SyncManager(cls) -> SyncManager:
|
|
335
|
+
return GriptapeNodes.get_instance()._sync_manager
|
|
336
|
+
|
|
332
337
|
@classmethod
|
|
333
338
|
def clear_data(cls) -> None:
|
|
334
339
|
# Get canvas
|
|
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
|
|
@@ -13,7 +13,6 @@ from importlib.resources import files
|
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
from typing import TYPE_CHECKING, cast
|
|
15
15
|
|
|
16
|
-
import uv
|
|
17
16
|
from packaging.requirements import InvalidRequirement, Requirement
|
|
18
17
|
from pydantic import ValidationError
|
|
19
18
|
from rich.align import Align
|
|
@@ -96,6 +95,8 @@ from griptape_nodes.retained_mode.managers.library_lifecycle.library_provenance.
|
|
|
96
95
|
)
|
|
97
96
|
from griptape_nodes.retained_mode.managers.library_lifecycle.library_status import LibraryStatus
|
|
98
97
|
from griptape_nodes.retained_mode.managers.os_manager import OSManager
|
|
98
|
+
from griptape_nodes.utils.uv_utils import find_uv_bin
|
|
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
|
|
@@ -109,21 +110,6 @@ logger = logging.getLogger("griptape_nodes")
|
|
|
109
110
|
console = Console()
|
|
110
111
|
|
|
111
112
|
|
|
112
|
-
def _find_griptape_uv_bin() -> str:
|
|
113
|
-
"""Find the uv binary, checking dedicated Griptape installation first, then system uv.
|
|
114
|
-
|
|
115
|
-
Returns:
|
|
116
|
-
Path to the uv binary to use
|
|
117
|
-
"""
|
|
118
|
-
# Check for dedicated Griptape uv installation first
|
|
119
|
-
dedicated_uv_path = xdg_data_home() / "griptape_nodes" / "bin" / "uv"
|
|
120
|
-
if dedicated_uv_path.exists():
|
|
121
|
-
return str(dedicated_uv_path)
|
|
122
|
-
|
|
123
|
-
# Fall back to system uv installation
|
|
124
|
-
return uv.find_uv_bin()
|
|
125
|
-
|
|
126
|
-
|
|
127
113
|
class LibraryManager:
|
|
128
114
|
SANDBOX_LIBRARY_NAME = "Sandbox Library"
|
|
129
115
|
|
|
@@ -959,10 +945,12 @@ class LibraryManager:
|
|
|
959
945
|
)
|
|
960
946
|
return RegisterLibraryFromRequirementSpecifierResultFailure()
|
|
961
947
|
|
|
948
|
+
uv_path = find_uv_bin()
|
|
949
|
+
|
|
962
950
|
logger.info("Installing dependency '%s' with pip in venv at %s", package_name, venv_path)
|
|
963
951
|
subprocess.run( # noqa: S603
|
|
964
952
|
[
|
|
965
|
-
|
|
953
|
+
uv_path,
|
|
966
954
|
"pip",
|
|
967
955
|
"install",
|
|
968
956
|
request.requirement_specifier,
|
|
@@ -1032,9 +1020,10 @@ class LibraryManager:
|
|
|
1032
1020
|
raise RuntimeError(error_message)
|
|
1033
1021
|
|
|
1034
1022
|
try:
|
|
1023
|
+
uv_path = find_uv_bin()
|
|
1035
1024
|
logger.info("Creating virtual environment at %s with Python %s", library_venv_path, python_version)
|
|
1036
1025
|
subprocess.run( # noqa: S603
|
|
1037
|
-
[
|
|
1026
|
+
[uv_path, "venv", str(library_venv_path), "--python", python_version],
|
|
1038
1027
|
check=True,
|
|
1039
1028
|
capture_output=True,
|
|
1040
1029
|
text=True,
|
|
@@ -1594,14 +1583,7 @@ class LibraryManager:
|
|
|
1594
1583
|
GriptapeNodes.WorkflowManager().on_libraries_initialization_complete()
|
|
1595
1584
|
|
|
1596
1585
|
# 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>"
|
|
1586
|
+
engine_version = get_complete_version_string()
|
|
1605
1587
|
|
|
1606
1588
|
# Get current session ID
|
|
1607
1589
|
session_id = GriptapeNodes.get_session_id()
|