griptape-nodes 0.60.3__py3-none-any.whl → 0.61.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/bootstrap/workflow_publishers/local_workflow_publisher.py +0 -1
- griptape_nodes/common/macro_parser/__init__.py +16 -1
- griptape_nodes/common/macro_parser/core.py +15 -3
- griptape_nodes/common/macro_parser/exceptions.py +99 -0
- griptape_nodes/common/macro_parser/formats.py +13 -4
- griptape_nodes/common/macro_parser/matching.py +5 -2
- griptape_nodes/common/macro_parser/parsing.py +48 -8
- griptape_nodes/common/macro_parser/resolution.py +23 -5
- griptape_nodes/common/project_templates/__init__.py +49 -0
- griptape_nodes/common/project_templates/default_project_template.py +92 -0
- griptape_nodes/common/project_templates/defaults/README.md +36 -0
- griptape_nodes/common/project_templates/defaults/project_template.yml +89 -0
- griptape_nodes/common/project_templates/directory.py +67 -0
- griptape_nodes/common/project_templates/loader.py +341 -0
- griptape_nodes/common/project_templates/project.py +252 -0
- griptape_nodes/common/project_templates/situation.py +155 -0
- griptape_nodes/common/project_templates/validation.py +140 -0
- griptape_nodes/exe_types/core_types.py +36 -3
- griptape_nodes/exe_types/node_types.py +4 -2
- griptape_nodes/exe_types/param_components/progress_bar_component.py +57 -0
- griptape_nodes/exe_types/param_types/parameter_audio.py +243 -0
- griptape_nodes/exe_types/param_types/parameter_image.py +243 -0
- griptape_nodes/exe_types/param_types/parameter_three_d.py +215 -0
- griptape_nodes/exe_types/param_types/parameter_video.py +243 -0
- griptape_nodes/node_library/workflow_registry.py +1 -1
- griptape_nodes/retained_mode/events/execution_events.py +41 -0
- griptape_nodes/retained_mode/events/node_events.py +90 -1
- griptape_nodes/retained_mode/events/os_events.py +108 -0
- griptape_nodes/retained_mode/events/parameter_events.py +1 -1
- griptape_nodes/retained_mode/events/project_events.py +413 -0
- griptape_nodes/retained_mode/events/workflow_events.py +19 -1
- griptape_nodes/retained_mode/griptape_nodes.py +9 -1
- griptape_nodes/retained_mode/managers/agent_manager.py +18 -24
- griptape_nodes/retained_mode/managers/event_manager.py +6 -9
- griptape_nodes/retained_mode/managers/flow_manager.py +63 -0
- griptape_nodes/retained_mode/managers/library_manager.py +55 -42
- griptape_nodes/retained_mode/managers/mcp_manager.py +14 -6
- griptape_nodes/retained_mode/managers/node_manager.py +232 -0
- griptape_nodes/retained_mode/managers/os_manager.py +346 -1
- griptape_nodes/retained_mode/managers/project_manager.py +617 -0
- griptape_nodes/retained_mode/managers/settings.py +6 -0
- griptape_nodes/retained_mode/managers/workflow_manager.py +17 -71
- griptape_nodes/traits/button.py +18 -0
- {griptape_nodes-0.60.3.dist-info → griptape_nodes-0.61.0.dist-info}/METADATA +5 -3
- {griptape_nodes-0.60.3.dist-info → griptape_nodes-0.61.0.dist-info}/RECORD +47 -31
- {griptape_nodes-0.60.3.dist-info → griptape_nodes-0.61.0.dist-info}/WHEEL +1 -1
- {griptape_nodes-0.60.3.dist-info → griptape_nodes-0.61.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
"""Events for project template management."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from enum import StrEnum
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from griptape_nodes.common.macro_parser import MacroMatchFailure, MacroParseFailure, VariableInfo
|
|
9
|
+
from griptape_nodes.common.project_templates import ProjectTemplate, ProjectValidationInfo
|
|
10
|
+
from griptape_nodes.retained_mode.events.base_events import (
|
|
11
|
+
RequestPayload,
|
|
12
|
+
ResultPayloadFailure,
|
|
13
|
+
ResultPayloadSuccess,
|
|
14
|
+
WorkflowNotAlteredMixin,
|
|
15
|
+
)
|
|
16
|
+
from griptape_nodes.retained_mode.events.payload_registry import PayloadRegistry
|
|
17
|
+
|
|
18
|
+
# Type alias for macro variable dictionaries (used by ParsedMacro)
|
|
19
|
+
MacroVariables = dict[str, str | int]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class PathResolutionFailureReason(StrEnum):
|
|
23
|
+
"""Reason why path resolution from macro failed."""
|
|
24
|
+
|
|
25
|
+
MISSING_REQUIRED_VARIABLES = "MISSING_REQUIRED_VARIABLES"
|
|
26
|
+
MACRO_RESOLUTION_ERROR = "MACRO_RESOLUTION_ERROR"
|
|
27
|
+
DIRECTORY_OVERRIDE_ATTEMPTED = "DIRECTORY_OVERRIDE_ATTEMPTED"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
@PayloadRegistry.register
|
|
32
|
+
class LoadProjectTemplateRequest(RequestPayload):
|
|
33
|
+
"""Load user's project.yml and merge with system defaults.
|
|
34
|
+
|
|
35
|
+
Use when: User opens a workspace, user creates new project, user modifies project.yml.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
project_path: Path to the project.yml file to load
|
|
39
|
+
|
|
40
|
+
Results: LoadProjectTemplateResultSuccess | LoadProjectTemplateResultFailure
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
project_path: Path
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
@PayloadRegistry.register
|
|
48
|
+
class LoadProjectTemplateResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
49
|
+
"""Project template loaded successfully.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
project_path: Path to the loaded project.yml
|
|
53
|
+
template: The merged ProjectTemplate (system defaults + user customizations)
|
|
54
|
+
validation: Validation info with status and any problems encountered
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
project_path: Path
|
|
58
|
+
template: ProjectTemplate
|
|
59
|
+
validation: ProjectValidationInfo
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass
|
|
63
|
+
@PayloadRegistry.register
|
|
64
|
+
class LoadProjectTemplateResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
65
|
+
"""Project template loading failed.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
project_path: Path to the project.yml that failed to load
|
|
69
|
+
validation: Validation info with error details
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
project_path: Path
|
|
73
|
+
validation: ProjectValidationInfo
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass
|
|
77
|
+
@PayloadRegistry.register
|
|
78
|
+
class GetProjectTemplateRequest(RequestPayload):
|
|
79
|
+
"""Get cached project template for a workspace path.
|
|
80
|
+
|
|
81
|
+
Use when: Querying current project configuration, checking validation status.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
project_path: Path to the project.yml file
|
|
85
|
+
|
|
86
|
+
Results: GetProjectTemplateResultSuccess | GetProjectTemplateResultFailure
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
project_path: Path
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@dataclass
|
|
93
|
+
@PayloadRegistry.register
|
|
94
|
+
class GetProjectTemplateResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
95
|
+
"""Project template retrieved from cache.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
template: The successfully loaded ProjectTemplate
|
|
99
|
+
validation: Validation info for the template
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
template: ProjectTemplate
|
|
103
|
+
validation: ProjectValidationInfo
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@dataclass
|
|
107
|
+
@PayloadRegistry.register
|
|
108
|
+
class GetProjectTemplateResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
109
|
+
"""Project template retrieval failed (not loaded yet)."""
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@dataclass
|
|
113
|
+
@PayloadRegistry.register
|
|
114
|
+
class GetMacroForSituationRequest(RequestPayload):
|
|
115
|
+
"""Get the macro schema for a specific situation.
|
|
116
|
+
|
|
117
|
+
Use when: Need to know what variables a situation requires, or get schema for custom resolution.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
project_path: Path to the project.yml to use
|
|
121
|
+
situation_name: Name of the situation template (e.g., "save_node_output")
|
|
122
|
+
|
|
123
|
+
Results: GetMacroForSituationResultSuccess | GetMacroForSituationResultFailure
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
project_path: Path
|
|
127
|
+
situation_name: str
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@dataclass
|
|
131
|
+
@PayloadRegistry.register
|
|
132
|
+
class GetMacroForSituationResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
133
|
+
"""Situation macro retrieved successfully.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
macro_schema: The macro template string (e.g., "{inputs}/{file_name}.{file_ext}")
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
macro_schema: str
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@dataclass
|
|
143
|
+
@PayloadRegistry.register
|
|
144
|
+
class GetMacroForSituationResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
145
|
+
"""Situation macro retrieval failed (situation not found or template not loaded)."""
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@dataclass
|
|
149
|
+
@PayloadRegistry.register
|
|
150
|
+
class GetPathForMacroRequest(RequestPayload):
|
|
151
|
+
"""Resolve ANY macro schema with variables to produce final file path.
|
|
152
|
+
|
|
153
|
+
Use when: Resolving paths, saving files. Works with any macro string, not tied to situations.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
project_path: Path to the project.yml (used for directory resolution)
|
|
157
|
+
macro_schema: The macro template string to resolve (e.g., "{inputs}/{file_name}.{file_ext}")
|
|
158
|
+
variables: Variable values for macro substitution (e.g., {"file_name": "output", "file_ext": "png"})
|
|
159
|
+
|
|
160
|
+
Results: GetPathForMacroResultSuccess | GetPathForMacroResultFailure
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
project_path: Path
|
|
164
|
+
macro_schema: str
|
|
165
|
+
variables: MacroVariables
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@dataclass
|
|
169
|
+
@PayloadRegistry.register
|
|
170
|
+
class GetPathForMacroResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
171
|
+
"""Path resolved successfully from macro.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
resolved_path: The final Path after macro substitution
|
|
175
|
+
"""
|
|
176
|
+
|
|
177
|
+
resolved_path: Path
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@dataclass
|
|
181
|
+
@PayloadRegistry.register
|
|
182
|
+
class GetPathForMacroResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
183
|
+
"""Path resolution failed.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
failure_reason: Specific reason for failure
|
|
187
|
+
missing_variables: List of required variable names that were not provided (for MISSING_REQUIRED_VARIABLES)
|
|
188
|
+
conflicting_variables: List of variables that conflict with directory names (for DIRECTORY_OVERRIDE_ATTEMPTED)
|
|
189
|
+
error_details: Additional error details from ParsedMacro (for MACRO_RESOLUTION_ERROR)
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
failure_reason: PathResolutionFailureReason
|
|
193
|
+
missing_variables: list[str] | None = None
|
|
194
|
+
conflicting_variables: list[str] | None = None
|
|
195
|
+
error_details: str | None = None
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
@dataclass
|
|
199
|
+
@PayloadRegistry.register
|
|
200
|
+
class SetCurrentProjectRequest(RequestPayload):
|
|
201
|
+
"""Set which project.yml user has currently selected.
|
|
202
|
+
|
|
203
|
+
Use when: User switches between projects, opens a new workspace.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
project_path: Path to the project.yml to set as current (None to clear)
|
|
207
|
+
|
|
208
|
+
Results: SetCurrentProjectResultSuccess
|
|
209
|
+
"""
|
|
210
|
+
|
|
211
|
+
project_path: Path | None
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
@dataclass
|
|
215
|
+
@PayloadRegistry.register
|
|
216
|
+
class SetCurrentProjectResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
217
|
+
"""Current project set successfully."""
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
@dataclass
|
|
221
|
+
@PayloadRegistry.register
|
|
222
|
+
class GetCurrentProjectRequest(RequestPayload):
|
|
223
|
+
"""Get the currently selected project path.
|
|
224
|
+
|
|
225
|
+
Use when: Need to know which project user is working with.
|
|
226
|
+
|
|
227
|
+
Results: GetCurrentProjectResultSuccess
|
|
228
|
+
"""
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
@dataclass
|
|
232
|
+
@PayloadRegistry.register
|
|
233
|
+
class GetCurrentProjectResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
234
|
+
"""Current project retrieved.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
project_path: The currently selected project path ("No Project" if None)
|
|
238
|
+
"""
|
|
239
|
+
|
|
240
|
+
project_path: Path | None
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
@dataclass
|
|
244
|
+
@PayloadRegistry.register
|
|
245
|
+
class SaveProjectTemplateRequest(RequestPayload):
|
|
246
|
+
"""Save user customizations to project.yml file.
|
|
247
|
+
|
|
248
|
+
Use when: User modifies project configuration, exports template.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
project_path: Path where project.yml should be saved
|
|
252
|
+
template_data: Dict representation of the template to save
|
|
253
|
+
|
|
254
|
+
Results: SaveProjectTemplateResultSuccess | SaveProjectTemplateResultFailure
|
|
255
|
+
"""
|
|
256
|
+
|
|
257
|
+
project_path: Path
|
|
258
|
+
template_data: dict[str, Any]
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
@dataclass
|
|
262
|
+
@PayloadRegistry.register
|
|
263
|
+
class SaveProjectTemplateResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
264
|
+
"""Project template saved successfully.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
project_path: Path where project.yml was saved
|
|
268
|
+
"""
|
|
269
|
+
|
|
270
|
+
project_path: Path
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
@dataclass
|
|
274
|
+
@PayloadRegistry.register
|
|
275
|
+
class SaveProjectTemplateResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
276
|
+
"""Project template save failed.
|
|
277
|
+
|
|
278
|
+
Common causes:
|
|
279
|
+
- Permission denied
|
|
280
|
+
- Invalid path
|
|
281
|
+
- Disk full
|
|
282
|
+
"""
|
|
283
|
+
|
|
284
|
+
project_path: Path
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
@dataclass
|
|
288
|
+
@PayloadRegistry.register
|
|
289
|
+
class MatchPathAgainstMacroRequest(RequestPayload):
|
|
290
|
+
"""Check if a path matches a macro schema and extract variables.
|
|
291
|
+
|
|
292
|
+
Use when: Validating paths, extracting info from file paths,
|
|
293
|
+
identifying which schema produced a file.
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
project_path: Path to project.yml (for directory resolution)
|
|
297
|
+
macro_schema: Macro template string
|
|
298
|
+
file_path: Path to test
|
|
299
|
+
known_variables: Variables we already know
|
|
300
|
+
|
|
301
|
+
Results: MatchPathAgainstMacroResultSuccess | MatchPathAgainstMacroResultFailure
|
|
302
|
+
"""
|
|
303
|
+
|
|
304
|
+
project_path: Path
|
|
305
|
+
macro_schema: str
|
|
306
|
+
file_path: str
|
|
307
|
+
known_variables: MacroVariables
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
@dataclass
|
|
311
|
+
@PayloadRegistry.register
|
|
312
|
+
class MatchPathAgainstMacroResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
313
|
+
"""Path matched the macro schema."""
|
|
314
|
+
|
|
315
|
+
extracted_variables: MacroVariables
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
@dataclass
|
|
319
|
+
@PayloadRegistry.register
|
|
320
|
+
class MatchPathAgainstMacroResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
321
|
+
"""Path did not match the macro schema."""
|
|
322
|
+
|
|
323
|
+
match_failure: MacroMatchFailure
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
@dataclass
|
|
327
|
+
@PayloadRegistry.register
|
|
328
|
+
class GetVariablesForMacroRequest(RequestPayload):
|
|
329
|
+
"""Get list of all variables in a macro schema.
|
|
330
|
+
|
|
331
|
+
Use when: Building UI forms, showing what variables a schema needs,
|
|
332
|
+
validating before resolution.
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
macro_schema: Macro template string to inspect
|
|
336
|
+
|
|
337
|
+
Results: GetVariablesForMacroResultSuccess | GetVariablesForMacroResultFailure
|
|
338
|
+
"""
|
|
339
|
+
|
|
340
|
+
macro_schema: str
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
@dataclass
|
|
344
|
+
@PayloadRegistry.register
|
|
345
|
+
class GetVariablesForMacroResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
346
|
+
"""Variables found in the macro schema."""
|
|
347
|
+
|
|
348
|
+
variables: list[VariableInfo]
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
@dataclass
|
|
352
|
+
@PayloadRegistry.register
|
|
353
|
+
class GetVariablesForMacroResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
354
|
+
"""Failed to parse macro schema."""
|
|
355
|
+
|
|
356
|
+
parse_failure: MacroParseFailure
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
@dataclass
|
|
360
|
+
@PayloadRegistry.register
|
|
361
|
+
class ValidateMacroSyntaxRequest(RequestPayload):
|
|
362
|
+
"""Validate a macro schema string for syntax errors.
|
|
363
|
+
|
|
364
|
+
Use when: User editing schemas in UI, before saving templates,
|
|
365
|
+
real-time validation.
|
|
366
|
+
|
|
367
|
+
Args:
|
|
368
|
+
macro_schema: Schema string to validate
|
|
369
|
+
|
|
370
|
+
Results: ValidateMacroSyntaxResultSuccess | ValidateMacroSyntaxResultFailure
|
|
371
|
+
"""
|
|
372
|
+
|
|
373
|
+
macro_schema: str
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
@dataclass
|
|
377
|
+
@PayloadRegistry.register
|
|
378
|
+
class ValidateMacroSyntaxResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
379
|
+
"""Syntax is valid."""
|
|
380
|
+
|
|
381
|
+
variables: list[VariableInfo]
|
|
382
|
+
warnings: list[str]
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
@dataclass
|
|
386
|
+
@PayloadRegistry.register
|
|
387
|
+
class ValidateMacroSyntaxResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
388
|
+
"""Syntax is invalid."""
|
|
389
|
+
|
|
390
|
+
parse_failure: MacroParseFailure
|
|
391
|
+
partial_variables: list[VariableInfo]
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
@dataclass
|
|
395
|
+
@PayloadRegistry.register
|
|
396
|
+
class GetAllSituationsForProjectRequest(RequestPayload):
|
|
397
|
+
"""Get all situation names and schemas from a project template."""
|
|
398
|
+
|
|
399
|
+
project_path: Path
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
@dataclass
|
|
403
|
+
@PayloadRegistry.register
|
|
404
|
+
class GetAllSituationsForProjectResultSuccess(WorkflowNotAlteredMixin, ResultPayloadSuccess):
|
|
405
|
+
"""Success result containing all situations."""
|
|
406
|
+
|
|
407
|
+
situations: dict[str, str]
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
@dataclass
|
|
411
|
+
@PayloadRegistry.register
|
|
412
|
+
class GetAllSituationsForProjectResultFailure(WorkflowNotAlteredMixin, ResultPayloadFailure):
|
|
413
|
+
"""Failure result when cannot get situations."""
|
|
@@ -10,6 +10,7 @@ from griptape_nodes.retained_mode.events.base_events import (
|
|
|
10
10
|
WorkflowAlteredMixin,
|
|
11
11
|
WorkflowNotAlteredMixin,
|
|
12
12
|
)
|
|
13
|
+
from griptape_nodes.retained_mode.events.execution_events import ExecutionPayload
|
|
13
14
|
from griptape_nodes.retained_mode.events.payload_registry import PayloadRegistry
|
|
14
15
|
|
|
15
16
|
if TYPE_CHECKING:
|
|
@@ -388,9 +389,11 @@ class PublishWorkflowRequest(RequestPayload):
|
|
|
388
389
|
|
|
389
390
|
workflow_name: str
|
|
390
391
|
publisher_name: str
|
|
391
|
-
|
|
392
|
+
# This can be removed after GUI release
|
|
393
|
+
execute_on_publish: bool | None = None
|
|
392
394
|
published_workflow_file_name: str | None = None
|
|
393
395
|
pickle_control_flow_result: bool = False
|
|
396
|
+
metadata: dict | None = None
|
|
394
397
|
|
|
395
398
|
|
|
396
399
|
@dataclass
|
|
@@ -403,6 +406,7 @@ class PublishWorkflowResultSuccess(ResultPayloadSuccess):
|
|
|
403
406
|
"""
|
|
404
407
|
|
|
405
408
|
published_workflow_file_path: str
|
|
409
|
+
metadata: dict | None = None
|
|
406
410
|
|
|
407
411
|
|
|
408
412
|
@dataclass
|
|
@@ -411,6 +415,20 @@ class PublishWorkflowResultFailure(ResultPayloadFailure):
|
|
|
411
415
|
"""Workflow publish failed. Common causes: workflow not found, publish error, file system error."""
|
|
412
416
|
|
|
413
417
|
|
|
418
|
+
@dataclass
|
|
419
|
+
@PayloadRegistry.register
|
|
420
|
+
class PublishWorkflowProgressEvent(ExecutionPayload):
|
|
421
|
+
"""Event emitted to indicate progress during workflow publishing.
|
|
422
|
+
|
|
423
|
+
Args:
|
|
424
|
+
progress: Progress percentage (0-100)
|
|
425
|
+
message: Optional progress message
|
|
426
|
+
"""
|
|
427
|
+
|
|
428
|
+
progress: float
|
|
429
|
+
message: str | None = None
|
|
430
|
+
|
|
431
|
+
|
|
414
432
|
@dataclass
|
|
415
433
|
@PayloadRegistry.register
|
|
416
434
|
class BranchWorkflowRequest(RequestPayload):
|
|
@@ -51,6 +51,7 @@ if TYPE_CHECKING:
|
|
|
51
51
|
OperationDepthManager,
|
|
52
52
|
)
|
|
53
53
|
from griptape_nodes.retained_mode.managers.os_manager import OSManager
|
|
54
|
+
from griptape_nodes.retained_mode.managers.project_manager import ProjectManager
|
|
54
55
|
from griptape_nodes.retained_mode.managers.resource_manager import ResourceManager
|
|
55
56
|
from griptape_nodes.retained_mode.managers.secrets_manager import SecretsManager
|
|
56
57
|
from griptape_nodes.retained_mode.managers.session_manager import SessionManager
|
|
@@ -95,8 +96,9 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
95
96
|
_resource_manager: ResourceManager
|
|
96
97
|
_sync_manager: SyncManager
|
|
97
98
|
_user_manager: UserManager
|
|
99
|
+
_project_manager: ProjectManager
|
|
98
100
|
|
|
99
|
-
def __init__(self) -> None:
|
|
101
|
+
def __init__(self) -> None: # noqa: PLR0915
|
|
100
102
|
from griptape_nodes.retained_mode.managers.agent_manager import AgentManager
|
|
101
103
|
from griptape_nodes.retained_mode.managers.arbitrary_code_exec_manager import (
|
|
102
104
|
ArbitraryCodeExecManager,
|
|
@@ -115,6 +117,7 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
115
117
|
OperationDepthManager,
|
|
116
118
|
)
|
|
117
119
|
from griptape_nodes.retained_mode.managers.os_manager import OSManager
|
|
120
|
+
from griptape_nodes.retained_mode.managers.project_manager import ProjectManager
|
|
118
121
|
from griptape_nodes.retained_mode.managers.resource_manager import ResourceManager
|
|
119
122
|
from griptape_nodes.retained_mode.managers.secrets_manager import SecretsManager
|
|
120
123
|
from griptape_nodes.retained_mode.managers.session_manager import SessionManager
|
|
@@ -160,6 +163,7 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
160
163
|
self._mcp_manager = MCPManager(self._event_manager, self._config_manager)
|
|
161
164
|
self._sync_manager = SyncManager(self._event_manager, self._config_manager)
|
|
162
165
|
self._user_manager = UserManager(self._secrets_manager)
|
|
166
|
+
self._project_manager = ProjectManager(self._event_manager, self._config_manager, self._secrets_manager)
|
|
163
167
|
|
|
164
168
|
# Assign handlers now that these are created.
|
|
165
169
|
self._event_manager.assign_manager_to_request_type(
|
|
@@ -330,6 +334,10 @@ class GriptapeNodes(metaclass=SingletonMeta):
|
|
|
330
334
|
def UserManager(cls) -> UserManager:
|
|
331
335
|
return GriptapeNodes.get_instance()._user_manager
|
|
332
336
|
|
|
337
|
+
@classmethod
|
|
338
|
+
def ProjectManager(cls) -> ProjectManager:
|
|
339
|
+
return GriptapeNodes.get_instance()._project_manager
|
|
340
|
+
|
|
333
341
|
@classmethod
|
|
334
342
|
def clear_data(cls) -> None:
|
|
335
343
|
# Get canvas
|
|
@@ -7,11 +7,11 @@ import uuid
|
|
|
7
7
|
from typing import TYPE_CHECKING, ClassVar
|
|
8
8
|
|
|
9
9
|
from attrs import define, field
|
|
10
|
-
from griptape.artifacts import ErrorArtifact, ImageUrlArtifact
|
|
10
|
+
from griptape.artifacts import ErrorArtifact, ImageUrlArtifact
|
|
11
11
|
from griptape.drivers.image_generation import BaseImageGenerationDriver
|
|
12
12
|
from griptape.drivers.image_generation.griptape_cloud import GriptapeCloudImageGenerationDriver
|
|
13
13
|
from griptape.drivers.prompt.griptape_cloud import GriptapeCloudPromptDriver
|
|
14
|
-
from griptape.events import
|
|
14
|
+
from griptape.events import TextChunkEvent
|
|
15
15
|
from griptape.loaders import ImageLoader
|
|
16
16
|
from griptape.memory.structure import ConversationMemory
|
|
17
17
|
from griptape.rules import Rule, Ruleset
|
|
@@ -20,6 +20,7 @@ from griptape.tools import BaseImageGenerationTool
|
|
|
20
20
|
from griptape.tools.mcp.tool import MCPTool
|
|
21
21
|
from griptape.utils.decorators import activity
|
|
22
22
|
from json_repair import repair_json
|
|
23
|
+
from pydantic import create_model
|
|
23
24
|
from schema import Literal, Schema
|
|
24
25
|
|
|
25
26
|
from griptape_nodes.retained_mode.events.agent_events import (
|
|
@@ -35,7 +36,6 @@ from griptape_nodes.retained_mode.events.agent_events import (
|
|
|
35
36
|
ResetAgentConversationMemoryResultSuccess,
|
|
36
37
|
RunAgentRequest,
|
|
37
38
|
RunAgentResultFailure,
|
|
38
|
-
RunAgentResultStarted,
|
|
39
39
|
RunAgentResultSuccess,
|
|
40
40
|
)
|
|
41
41
|
from griptape_nodes.retained_mode.events.app_events import AppInitializationComplete
|
|
@@ -202,15 +202,17 @@ class AgentManager:
|
|
|
202
202
|
self.image_tool = self._initialize_image_tool()
|
|
203
203
|
if self.mcp_tool is None:
|
|
204
204
|
self.mcp_tool = self._initialize_mcp_tool()
|
|
205
|
-
|
|
206
|
-
|
|
205
|
+
try:
|
|
206
|
+
return await asyncio.to_thread(self._on_handle_run_agent_request, request)
|
|
207
|
+
except Exception as e:
|
|
208
|
+
err_msg = f"Error handling run agent request: {e}"
|
|
209
|
+
return RunAgentResultFailure(error=ErrorArtifact(e).to_dict(), result_details=err_msg)
|
|
207
210
|
|
|
208
211
|
def _create_agent(self, additional_mcp_servers: list[str] | None = None) -> Agent:
|
|
209
|
-
output_schema =
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
212
|
+
output_schema = create_model(
|
|
213
|
+
"AgentOutputSchema",
|
|
214
|
+
conversation_output=(str, ...),
|
|
215
|
+
generated_image_urls=(list[str], ...),
|
|
214
216
|
)
|
|
215
217
|
|
|
216
218
|
tools = []
|
|
@@ -252,7 +254,6 @@ class AgentManager:
|
|
|
252
254
|
event_stream = agent.run_stream([request.input, *artifacts])
|
|
253
255
|
full_result = ""
|
|
254
256
|
last_conversation_output = ""
|
|
255
|
-
last_event = None
|
|
256
257
|
for event in event_stream:
|
|
257
258
|
if isinstance(event, TextChunkEvent):
|
|
258
259
|
full_result += event.token
|
|
@@ -274,19 +275,12 @@ class AgentManager:
|
|
|
274
275
|
last_conversation_output = new_conversation_output
|
|
275
276
|
except json.JSONDecodeError:
|
|
276
277
|
pass # Ignore incomplete JSON
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
if isinstance(last_event.task_output, JsonArtifact):
|
|
284
|
-
return RunAgentResultSuccess(
|
|
285
|
-
last_event.task_output.to_dict(), result_details="Agent execution completed successfully."
|
|
286
|
-
)
|
|
287
|
-
err_msg = f"Unexpected final event: {last_event}"
|
|
288
|
-
logger.error(err_msg)
|
|
289
|
-
return RunAgentResultFailure(error=ErrorArtifact(last_event).to_dict(), result_details=err_msg)
|
|
278
|
+
if isinstance(agent.output, ErrorArtifact):
|
|
279
|
+
return RunAgentResultFailure(error=agent.output.to_dict(), result_details=agent.output.to_json())
|
|
280
|
+
|
|
281
|
+
return RunAgentResultSuccess(
|
|
282
|
+
agent.output.to_dict(), result_details="Agent execution completed successfully."
|
|
283
|
+
)
|
|
290
284
|
except Exception as e:
|
|
291
285
|
err_msg = f"Error running agent: {e}"
|
|
292
286
|
logger.exception(err_msg)
|
|
@@ -7,6 +7,7 @@ from collections import defaultdict
|
|
|
7
7
|
from dataclasses import fields
|
|
8
8
|
from typing import TYPE_CHECKING, Any, cast
|
|
9
9
|
|
|
10
|
+
from asyncio_thread_runner import ThreadRunner
|
|
10
11
|
from typing_extensions import TypedDict, TypeVar
|
|
11
12
|
|
|
12
13
|
from griptape_nodes.retained_mode.events.base_events import (
|
|
@@ -276,8 +277,8 @@ class EventManager:
|
|
|
276
277
|
if inspect.iscoroutinefunction(callback):
|
|
277
278
|
try:
|
|
278
279
|
asyncio.get_running_loop()
|
|
279
|
-
|
|
280
|
-
|
|
280
|
+
with ThreadRunner() as runner:
|
|
281
|
+
result_payload: ResultPayload = runner.run(callback(request))
|
|
281
282
|
except RuntimeError:
|
|
282
283
|
# No event loop running, safe to use asyncio.run
|
|
283
284
|
result_payload: ResultPayload = asyncio.run(callback(request))
|
|
@@ -317,10 +318,6 @@ class EventManager:
|
|
|
317
318
|
if app_event_type in self._app_event_listeners:
|
|
318
319
|
listener_set = self._app_event_listeners[app_event_type]
|
|
319
320
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
for listener_callback in listener_set
|
|
324
|
-
],
|
|
325
|
-
return_exceptions=True,
|
|
326
|
-
)
|
|
321
|
+
async with asyncio.TaskGroup() as tg:
|
|
322
|
+
for listener_callback in listener_set:
|
|
323
|
+
tg.create_task(call_function(listener_callback, app_event))
|