griptape-nodes 0.62.3__py3-none-any.whl → 0.63.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/cli/commands/libraries.py +6 -21
- griptape_nodes/drivers/thread_storage/__init__.py +15 -0
- griptape_nodes/drivers/thread_storage/base_thread_storage_driver.py +106 -0
- griptape_nodes/drivers/thread_storage/griptape_cloud_thread_storage_driver.py +213 -0
- griptape_nodes/drivers/thread_storage/local_thread_storage_driver.py +137 -0
- griptape_nodes/drivers/thread_storage/thread_storage_backend.py +10 -0
- griptape_nodes/node_library/library_registry.py +16 -9
- griptape_nodes/node_library/workflow_registry.py +1 -1
- griptape_nodes/retained_mode/events/agent_events.py +232 -9
- griptape_nodes/retained_mode/events/library_events.py +32 -3
- griptape_nodes/retained_mode/events/os_events.py +101 -1
- griptape_nodes/retained_mode/managers/agent_manager.py +335 -135
- griptape_nodes/retained_mode/managers/fitness_problems/__init__.py +1 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/__init__.py +59 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/advanced_library_load_failure_problem.py +33 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/after_library_callback_problem.py +32 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/before_library_callback_problem.py +32 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/create_config_category_problem.py +32 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/dependency_installation_failed_problem.py +32 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/deprecated_node_warning_problem.py +83 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/duplicate_library_problem.py +28 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/duplicate_node_registration_problem.py +44 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/engine_version_error_problem.py +28 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/insufficient_disk_space_problem.py +33 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/invalid_version_string_problem.py +32 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/library_json_decode_problem.py +28 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/library_load_exception_problem.py +32 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/library_not_found_problem.py +30 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/library_problem.py +20 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/library_schema_exception_problem.py +32 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/library_schema_validation_problem.py +38 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/modified_parameters_set_deprecation_warning_problem.py +44 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/modified_parameters_set_removed_problem.py +44 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/node_class_not_base_node_problem.py +40 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/node_class_not_found_problem.py +38 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/node_module_import_problem.py +53 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/sandbox_directory_missing_problem.py +28 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/ui_options_field_modified_incompatible_problem.py +44 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/ui_options_field_modified_warning_problem.py +35 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/update_config_category_problem.py +32 -0
- griptape_nodes/retained_mode/managers/fitness_problems/libraries/venv_creation_failed_problem.py +32 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/__init__.py +75 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/deprecated_node_in_workflow_problem.py +83 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/invalid_dependency_version_string_problem.py +38 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/invalid_library_version_string_problem.py +38 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/invalid_metadata_schema_problem.py +31 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/invalid_metadata_section_count_problem.py +31 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/invalid_toml_format_problem.py +30 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/library_not_registered_problem.py +35 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/library_version_below_required_problem.py +41 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/library_version_large_difference_problem.py +41 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/library_version_major_mismatch_problem.py +41 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/library_version_minor_difference_problem.py +41 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/missing_creation_date_problem.py +30 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/missing_last_modified_date_problem.py +30 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/missing_toml_section_problem.py +30 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/node_type_not_found_problem.py +51 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/workflow_not_found_problem.py +27 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/workflow_problem.py +20 -0
- griptape_nodes/retained_mode/managers/fitness_problems/workflows/workflow_schema_version_problem.py +39 -0
- griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/local_file.py +17 -3
- griptape_nodes/retained_mode/managers/library_manager.py +159 -75
- griptape_nodes/retained_mode/managers/os_manager.py +172 -1
- griptape_nodes/retained_mode/managers/settings.py +5 -0
- griptape_nodes/retained_mode/managers/version_compatibility_manager.py +76 -51
- griptape_nodes/retained_mode/managers/workflow_manager.py +154 -137
- griptape_nodes/servers/static.py +18 -19
- griptape_nodes/version_compatibility/versions/v0_39_0/modified_parameters_set_removal.py +16 -12
- griptape_nodes/version_compatibility/workflow_versions/v0_7_0/local_executor_argument_addition.py +6 -3
- {griptape_nodes-0.62.3.dist-info → griptape_nodes-0.63.0.dist-info}/METADATA +2 -1
- {griptape_nodes-0.62.3.dist-info → griptape_nodes-0.63.0.dist-info}/RECORD +73 -20
- {griptape_nodes-0.62.3.dist-info → griptape_nodes-0.63.0.dist-info}/WHEEL +0 -0
- {griptape_nodes-0.62.3.dist-info → griptape_nodes-0.63.0.dist-info}/entry_points.txt +0 -0
|
@@ -9,6 +9,7 @@ import platform
|
|
|
9
9
|
import subprocess
|
|
10
10
|
import sys
|
|
11
11
|
import sysconfig
|
|
12
|
+
from collections import defaultdict
|
|
12
13
|
from dataclasses import dataclass, field
|
|
13
14
|
from importlib.resources import files
|
|
14
15
|
from pathlib import Path
|
|
@@ -75,6 +76,9 @@ from griptape_nodes.retained_mode.events.library_events import (
|
|
|
75
76
|
ListNodeTypesInLibraryResultSuccess,
|
|
76
77
|
ListRegisteredLibrariesRequest,
|
|
77
78
|
ListRegisteredLibrariesResultSuccess,
|
|
79
|
+
LoadLibrariesRequest,
|
|
80
|
+
LoadLibrariesResultFailure,
|
|
81
|
+
LoadLibrariesResultSuccess,
|
|
78
82
|
LoadLibraryMetadataFromFileRequest,
|
|
79
83
|
LoadLibraryMetadataFromFileResultFailure,
|
|
80
84
|
LoadLibraryMetadataFromFileResultSuccess,
|
|
@@ -96,6 +100,29 @@ from griptape_nodes.retained_mode.events.library_events import (
|
|
|
96
100
|
from griptape_nodes.retained_mode.events.object_events import ClearAllObjectStateRequest
|
|
97
101
|
from griptape_nodes.retained_mode.events.payload_registry import PayloadRegistry
|
|
98
102
|
from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
103
|
+
from griptape_nodes.retained_mode.managers.fitness_problems.libraries import (
|
|
104
|
+
AdvancedLibraryLoadFailureProblem,
|
|
105
|
+
AfterLibraryCallbackProblem,
|
|
106
|
+
BeforeLibraryCallbackProblem,
|
|
107
|
+
CreateConfigCategoryProblem,
|
|
108
|
+
DependencyInstallationFailedProblem,
|
|
109
|
+
DuplicateLibraryProblem,
|
|
110
|
+
EngineVersionErrorProblem,
|
|
111
|
+
InsufficientDiskSpaceProblem,
|
|
112
|
+
InvalidVersionStringProblem,
|
|
113
|
+
LibraryJsonDecodeProblem,
|
|
114
|
+
LibraryLoadExceptionProblem,
|
|
115
|
+
LibraryNotFoundProblem,
|
|
116
|
+
LibraryProblem,
|
|
117
|
+
LibrarySchemaExceptionProblem,
|
|
118
|
+
LibrarySchemaValidationProblem,
|
|
119
|
+
NodeClassNotBaseNodeProblem,
|
|
120
|
+
NodeClassNotFoundProblem,
|
|
121
|
+
NodeModuleImportProblem,
|
|
122
|
+
SandboxDirectoryMissingProblem,
|
|
123
|
+
UpdateConfigCategoryProblem,
|
|
124
|
+
VenvCreationFailedProblem,
|
|
125
|
+
)
|
|
99
126
|
from griptape_nodes.retained_mode.managers.library_lifecycle.library_directory import LibraryDirectory
|
|
100
127
|
from griptape_nodes.retained_mode.managers.library_lifecycle.library_provenance.local_file import (
|
|
101
128
|
LibraryProvenanceLocalFile,
|
|
@@ -134,7 +161,7 @@ class LibraryManager:
|
|
|
134
161
|
library_path: str
|
|
135
162
|
library_name: str | None = None
|
|
136
163
|
library_version: str | None = None
|
|
137
|
-
problems: list[
|
|
164
|
+
problems: list[LibraryProblem] = field(default_factory=list)
|
|
138
165
|
|
|
139
166
|
_library_file_path_to_info: dict[str, LibraryInfo]
|
|
140
167
|
|
|
@@ -216,7 +243,8 @@ class LibraryManager:
|
|
|
216
243
|
event_manager.assign_manager_to_request_type(
|
|
217
244
|
UnloadLibraryFromRegistryRequest, self.unload_library_from_registry_request
|
|
218
245
|
)
|
|
219
|
-
event_manager.assign_manager_to_request_type(ReloadAllLibrariesRequest, self.
|
|
246
|
+
event_manager.assign_manager_to_request_type(ReloadAllLibrariesRequest, self.reload_libraries_request)
|
|
247
|
+
event_manager.assign_manager_to_request_type(LoadLibrariesRequest, self.load_libraries_request)
|
|
220
248
|
|
|
221
249
|
event_manager.add_listener_to_app_event(
|
|
222
250
|
AppInitializationComplete,
|
|
@@ -240,14 +268,10 @@ class LibraryManager:
|
|
|
240
268
|
console.print(panel)
|
|
241
269
|
return
|
|
242
270
|
|
|
243
|
-
# Create a table with
|
|
244
|
-
# Using SQUARE box style which includes row dividers
|
|
271
|
+
# Create a table with two columns and row dividers
|
|
245
272
|
table = Table(show_header=True, box=HEAVY_EDGE, show_lines=True, expand=True)
|
|
246
|
-
table.add_column("Library
|
|
247
|
-
table.add_column("
|
|
248
|
-
table.add_column("Version", style="green")
|
|
249
|
-
table.add_column("File Path", style="cyan")
|
|
250
|
-
table.add_column("Problems", style="yellow")
|
|
273
|
+
table.add_column("Library", style="green", ratio=1)
|
|
274
|
+
table.add_column("Problems", style="yellow", ratio=1)
|
|
251
275
|
|
|
252
276
|
# Status emojis mapping
|
|
253
277
|
status_emoji = {
|
|
@@ -257,17 +281,20 @@ class LibraryManager:
|
|
|
257
281
|
LibraryStatus.MISSING: "[red]?[/red]",
|
|
258
282
|
}
|
|
259
283
|
|
|
284
|
+
# Status text mapping (colored)
|
|
285
|
+
status_text = {
|
|
286
|
+
LibraryStatus.GOOD: "[green](GOOD)[/green]",
|
|
287
|
+
LibraryStatus.FLAWED: "[yellow](FLAWED)[/yellow]",
|
|
288
|
+
LibraryStatus.UNUSABLE: "[red](UNUSABLE)[/red]",
|
|
289
|
+
LibraryStatus.MISSING: "[red](MISSING)[/red]",
|
|
290
|
+
}
|
|
291
|
+
|
|
260
292
|
# Add rows for each library info
|
|
261
293
|
for lib_info in library_infos:
|
|
262
|
-
#
|
|
263
|
-
file_path = lib_info.library_path
|
|
264
|
-
file_path_text = Text(file_path, style="cyan")
|
|
265
|
-
file_path_text.overflow = "fold" # Force wrapping
|
|
266
|
-
|
|
267
|
-
# Library name column with emoji based on status
|
|
294
|
+
# Library column with emoji, name, version, colored status, and file path underneath
|
|
268
295
|
emoji = status_emoji.get(lib_info.status, "ERROR: Unknown/Unexpected Library Status")
|
|
296
|
+
colored_status = status_text.get(lib_info.status, "(UNKNOWN)")
|
|
269
297
|
name = lib_info.library_name if lib_info.library_name else "*UNKNOWN*"
|
|
270
|
-
library_name = f"{emoji} - {name}"
|
|
271
298
|
|
|
272
299
|
library_version = lib_info.library_version
|
|
273
300
|
if library_version:
|
|
@@ -275,17 +302,36 @@ class LibraryManager:
|
|
|
275
302
|
else:
|
|
276
303
|
version_str = "*UNKNOWN*"
|
|
277
304
|
|
|
278
|
-
|
|
305
|
+
file_path = lib_info.library_path
|
|
306
|
+
library_name_with_details = Text.from_markup(
|
|
307
|
+
f"{emoji} - {name} v{version_str} {colored_status}\n[cyan dim]{file_path}[/cyan dim]"
|
|
308
|
+
)
|
|
309
|
+
library_name_with_details.overflow = "fold"
|
|
310
|
+
|
|
311
|
+
# Problems column - collate by type then format
|
|
279
312
|
if not lib_info.problems:
|
|
280
313
|
problems = "No problems detected."
|
|
281
|
-
elif len(lib_info.problems) == 1:
|
|
282
|
-
problems = lib_info.problems[0]
|
|
283
314
|
else:
|
|
284
|
-
#
|
|
285
|
-
|
|
315
|
+
# Group problems by type
|
|
316
|
+
problems_by_type = defaultdict(list)
|
|
317
|
+
for problem in lib_info.problems:
|
|
318
|
+
problems_by_type[type(problem)].append(problem)
|
|
319
|
+
|
|
320
|
+
# Collate each group
|
|
321
|
+
collated_strings = []
|
|
322
|
+
for problem_class, instances in problems_by_type.items():
|
|
323
|
+
collated_display = problem_class.collate_problems_for_display(instances)
|
|
324
|
+
collated_strings.append(collated_display)
|
|
325
|
+
|
|
326
|
+
# Format for display
|
|
327
|
+
if len(collated_strings) == 1:
|
|
328
|
+
problems = collated_strings[0]
|
|
329
|
+
else:
|
|
330
|
+
# Number the problems when there's more than one
|
|
331
|
+
problems = "\n".join([f"{j + 1}. {problem}" for j, problem in enumerate(collated_strings)])
|
|
286
332
|
|
|
287
333
|
# Add the row to the table
|
|
288
|
-
table.add_row(
|
|
334
|
+
table.add_row(library_name_with_details, problems)
|
|
289
335
|
|
|
290
336
|
# Create a panel containing the table
|
|
291
337
|
panel = Panel(table, title="Library Information", border_style="blue")
|
|
@@ -407,9 +453,7 @@ class LibraryManager:
|
|
|
407
453
|
library_path=file_path,
|
|
408
454
|
library_name=None,
|
|
409
455
|
status=LibraryStatus.MISSING,
|
|
410
|
-
problems=[
|
|
411
|
-
"Library could not be found at the file path specified. It will be removed from the configuration."
|
|
412
|
-
],
|
|
456
|
+
problems=[LibraryNotFoundProblem(library_path=str(json_path))],
|
|
413
457
|
result_details=details,
|
|
414
458
|
)
|
|
415
459
|
|
|
@@ -424,7 +468,7 @@ class LibraryManager:
|
|
|
424
468
|
library_path=file_path,
|
|
425
469
|
library_name=None,
|
|
426
470
|
status=LibraryStatus.UNUSABLE,
|
|
427
|
-
problems=[
|
|
471
|
+
problems=[LibraryJsonDecodeProblem()],
|
|
428
472
|
result_details=details,
|
|
429
473
|
)
|
|
430
474
|
except Exception as err:
|
|
@@ -434,7 +478,7 @@ class LibraryManager:
|
|
|
434
478
|
library_path=file_path,
|
|
435
479
|
library_name=None,
|
|
436
480
|
status=LibraryStatus.UNUSABLE,
|
|
437
|
-
problems=[
|
|
481
|
+
problems=[LibraryLoadExceptionProblem(error_message=str(err))],
|
|
438
482
|
result_details=details,
|
|
439
483
|
)
|
|
440
484
|
|
|
@@ -451,7 +495,7 @@ class LibraryManager:
|
|
|
451
495
|
loc = " -> ".join(map(str, error["loc"]))
|
|
452
496
|
msg = error["msg"]
|
|
453
497
|
error_type = error["type"]
|
|
454
|
-
problem =
|
|
498
|
+
problem = LibrarySchemaValidationProblem(location=loc, error_type=error_type, message=msg)
|
|
455
499
|
problems.append(problem)
|
|
456
500
|
details = f"Attempted to load Library JSON file. Failed because the file at path '{json_path}' failed to match the library schema due to: {err}"
|
|
457
501
|
logger.error(details)
|
|
@@ -469,7 +513,7 @@ class LibraryManager:
|
|
|
469
513
|
library_path=file_path,
|
|
470
514
|
library_name=library_name,
|
|
471
515
|
status=LibraryStatus.UNUSABLE,
|
|
472
|
-
problems=[
|
|
516
|
+
problems=[LibrarySchemaExceptionProblem(error_message=str(err))],
|
|
473
517
|
result_details=details,
|
|
474
518
|
)
|
|
475
519
|
|
|
@@ -540,7 +584,7 @@ class LibraryManager:
|
|
|
540
584
|
library_path=sandbox_library_dir_as_posix,
|
|
541
585
|
library_name=LibraryManager.SANDBOX_LIBRARY_NAME,
|
|
542
586
|
status=LibraryStatus.MISSING,
|
|
543
|
-
problems=[
|
|
587
|
+
problems=[SandboxDirectoryMissingProblem()],
|
|
544
588
|
result_details=ResultDetails(message=details, level=logging.INFO),
|
|
545
589
|
)
|
|
546
590
|
|
|
@@ -597,7 +641,7 @@ class LibraryManager:
|
|
|
597
641
|
library_path=sandbox_library_dir_as_posix,
|
|
598
642
|
library_name=LibraryManager.SANDBOX_LIBRARY_NAME,
|
|
599
643
|
status=LibraryStatus.UNUSABLE,
|
|
600
|
-
problems=[
|
|
644
|
+
problems=[EngineVersionErrorProblem()],
|
|
601
645
|
result_details=details,
|
|
602
646
|
)
|
|
603
647
|
|
|
@@ -632,8 +676,6 @@ class LibraryManager:
|
|
|
632
676
|
library = LibraryRegistry.get_library(name=request.library)
|
|
633
677
|
except KeyError:
|
|
634
678
|
details = f"Attempted to get node metadata for a node type '{request.node_type}' in a Library named '{request.library}'. Failed because no Library with that name was registered."
|
|
635
|
-
logger.error(details)
|
|
636
|
-
|
|
637
679
|
result = GetNodeMetadataFromLibraryResultFailure(result_details=details)
|
|
638
680
|
return result
|
|
639
681
|
|
|
@@ -642,8 +684,6 @@ class LibraryManager:
|
|
|
642
684
|
metadata = library.get_node_metadata(node_type=request.node_type)
|
|
643
685
|
except KeyError:
|
|
644
686
|
details = f"Attempted to get node metadata for a node type '{request.node_type}' in a Library named '{request.library}'. Failed because no node type of that name could be found in the Library."
|
|
645
|
-
logger.error(details)
|
|
646
|
-
|
|
647
687
|
result = GetNodeMetadataFromLibraryResultFailure(result_details=details)
|
|
648
688
|
return result
|
|
649
689
|
|
|
@@ -683,9 +723,7 @@ class LibraryManager:
|
|
|
683
723
|
library_path=file_path,
|
|
684
724
|
library_name=None,
|
|
685
725
|
status=LibraryStatus.MISSING,
|
|
686
|
-
problems=[
|
|
687
|
-
"Library could not be found at the file path specified. It will be removed from the configuration."
|
|
688
|
-
],
|
|
726
|
+
problems=[LibraryNotFoundProblem(library_path=file_path)],
|
|
689
727
|
)
|
|
690
728
|
details = f"Attempted to load Library JSON file. Failed because no file could be found at the specified path: {json_path}"
|
|
691
729
|
logger.error(details)
|
|
@@ -717,9 +755,7 @@ class LibraryManager:
|
|
|
717
755
|
library_path=file_path,
|
|
718
756
|
library_name=library_data.name,
|
|
719
757
|
status=LibraryStatus.UNUSABLE,
|
|
720
|
-
problems=[
|
|
721
|
-
f"Library's version string '{library_data.metadata.library_version}' wasn't valid. Must be in major.minor.patch format."
|
|
722
|
-
],
|
|
758
|
+
problems=[InvalidVersionStringProblem(version_string=str(library_data.metadata.library_version))],
|
|
723
759
|
)
|
|
724
760
|
details = f"Attempted to load Library '{library_data.name}' JSON file from '{json_path}'. Failed because version string '{library_data.metadata.library_version}' wasn't valid. Must be in major.minor.patch format."
|
|
725
761
|
logger.error(details)
|
|
@@ -745,7 +781,9 @@ class LibraryManager:
|
|
|
745
781
|
library_version=library_version,
|
|
746
782
|
status=LibraryStatus.UNUSABLE,
|
|
747
783
|
problems=[
|
|
748
|
-
|
|
784
|
+
AdvancedLibraryLoadFailureProblem(
|
|
785
|
+
advanced_library_path=library_data.advanced_library_path, error_message=str(err)
|
|
786
|
+
)
|
|
749
787
|
],
|
|
750
788
|
)
|
|
751
789
|
details = f"Attempted to load Library '{library_data.name}' from '{json_path}'. Failed to load Advanced Library module: {err}"
|
|
@@ -768,9 +806,7 @@ class LibraryManager:
|
|
|
768
806
|
library_name=library_data.name,
|
|
769
807
|
library_version=library_version,
|
|
770
808
|
status=LibraryStatus.UNUSABLE,
|
|
771
|
-
problems=[
|
|
772
|
-
"Failed because a library with this name was already registered. Check the Settings to ensure duplicate libraries are not being loaded."
|
|
773
|
-
],
|
|
809
|
+
problems=[DuplicateLibraryProblem()],
|
|
774
810
|
)
|
|
775
811
|
|
|
776
812
|
details = f"Attempted to load Library JSON file from '{json_path}'. Failed because a Library '{library_data.name}' already exists. Error: {err}."
|
|
@@ -797,7 +833,7 @@ class LibraryManager:
|
|
|
797
833
|
library_name=library_data.name,
|
|
798
834
|
library_version=library_version,
|
|
799
835
|
status=LibraryStatus.UNUSABLE,
|
|
800
|
-
problems=[str(e)],
|
|
836
|
+
problems=[VenvCreationFailedProblem(error_message=str(e))],
|
|
801
837
|
)
|
|
802
838
|
details = f"Attempted to load Library JSON file from '{json_path}'. Failed when creating the virtual environment: {e}."
|
|
803
839
|
logger.error(details)
|
|
@@ -815,9 +851,7 @@ class LibraryManager:
|
|
|
815
851
|
library_name=library_data.name,
|
|
816
852
|
library_version=library_version,
|
|
817
853
|
status=LibraryStatus.UNUSABLE,
|
|
818
|
-
problems=[
|
|
819
|
-
f"Insufficient disk space for dependencies (requires {min_space_gb} GB): {error_msg}"
|
|
820
|
-
],
|
|
854
|
+
problems=[InsufficientDiskSpaceProblem(min_space_gb=min_space_gb, error_message=error_msg)],
|
|
821
855
|
)
|
|
822
856
|
return RegisterLibraryFromFileResultFailure(result_details=details)
|
|
823
857
|
|
|
@@ -857,7 +891,7 @@ class LibraryManager:
|
|
|
857
891
|
library_name=library_data.name,
|
|
858
892
|
library_version=library_version,
|
|
859
893
|
status=LibraryStatus.UNUSABLE,
|
|
860
|
-
problems=[
|
|
894
|
+
problems=[DependencyInstallationFailedProblem(error_details=error_details)],
|
|
861
895
|
)
|
|
862
896
|
details = f"Attempted to load Library JSON file from '{json_path}'. Failed when installing dependencies: {error_details}"
|
|
863
897
|
logger.error(details)
|
|
@@ -881,7 +915,7 @@ class LibraryManager:
|
|
|
881
915
|
)
|
|
882
916
|
create_new_category_result = GriptapeNodes.handle_request(create_new_category_request)
|
|
883
917
|
if not isinstance(create_new_category_result, SetConfigCategoryResultSuccess):
|
|
884
|
-
problems.append(
|
|
918
|
+
problems.append(CreateConfigCategoryProblem(category_name=library_data_setting.category))
|
|
885
919
|
details = f"Failed attempting to create new config category '{library_data_setting.category}' for library '{library_data.name}'."
|
|
886
920
|
logger.error(details)
|
|
887
921
|
continue # SKIP IT
|
|
@@ -895,7 +929,7 @@ class LibraryManager:
|
|
|
895
929
|
)
|
|
896
930
|
set_category_result = GriptapeNodes.handle_request(set_category_request)
|
|
897
931
|
if not isinstance(set_category_result, SetConfigCategoryResultSuccess):
|
|
898
|
-
problems.append(
|
|
932
|
+
problems.append(UpdateConfigCategoryProblem(category_name=library_data_setting.category))
|
|
899
933
|
details = f"Failed attempting to update config category '{library_data_setting.category}' for library '{library_data.name}'."
|
|
900
934
|
logger.error(details)
|
|
901
935
|
continue # SKIP IT
|
|
@@ -1397,6 +1431,21 @@ class LibraryManager:
|
|
|
1397
1431
|
"""
|
|
1398
1432
|
return module_name.startswith("gtn_dynamic_module_")
|
|
1399
1433
|
|
|
1434
|
+
@staticmethod
|
|
1435
|
+
def _get_root_cause_from_exception(exception: BaseException) -> BaseException:
|
|
1436
|
+
"""Walk the exception chain to find the root cause.
|
|
1437
|
+
|
|
1438
|
+
Args:
|
|
1439
|
+
exception: The exception to walk
|
|
1440
|
+
|
|
1441
|
+
Returns:
|
|
1442
|
+
The root cause exception (the innermost exception in the chain)
|
|
1443
|
+
"""
|
|
1444
|
+
current = exception
|
|
1445
|
+
while current.__cause__ is not None:
|
|
1446
|
+
current = current.__cause__
|
|
1447
|
+
return current
|
|
1448
|
+
|
|
1400
1449
|
def _load_module_from_file(self, file_path: Path | str, library_name: str) -> ModuleType:
|
|
1401
1450
|
"""Dynamically load a module from a Python file with support for hot reloading.
|
|
1402
1451
|
|
|
@@ -1847,7 +1896,7 @@ class LibraryManager:
|
|
|
1847
1896
|
base_dir: Path,
|
|
1848
1897
|
library_file_path: str,
|
|
1849
1898
|
library_version: str | None,
|
|
1850
|
-
problems: list[
|
|
1899
|
+
problems: list[LibraryProblem],
|
|
1851
1900
|
) -> LibraryManager.LibraryInfo:
|
|
1852
1901
|
any_nodes_loaded_successfully = False
|
|
1853
1902
|
|
|
@@ -1855,7 +1904,7 @@ class LibraryManager:
|
|
|
1855
1904
|
version_issues = GriptapeNodes.VersionCompatibilityManager().check_library_version_compatibility(library_data)
|
|
1856
1905
|
has_disqualifying_issues = False
|
|
1857
1906
|
for issue in version_issues:
|
|
1858
|
-
problems.append(issue.
|
|
1907
|
+
problems.append(issue.problem)
|
|
1859
1908
|
if issue.severity == LibraryStatus.UNUSABLE:
|
|
1860
1909
|
has_disqualifying_issues = True
|
|
1861
1910
|
|
|
@@ -1877,8 +1926,7 @@ class LibraryManager:
|
|
|
1877
1926
|
details = f"Successfully called before_library_nodes_loaded callback for library '{library_data.name}'"
|
|
1878
1927
|
logger.debug(details)
|
|
1879
1928
|
except Exception as err:
|
|
1880
|
-
|
|
1881
|
-
problems.append(problem)
|
|
1929
|
+
problems.append(BeforeLibraryCallbackProblem(error_message=str(err)))
|
|
1882
1930
|
details = (
|
|
1883
1931
|
f"Failed to call before_library_nodes_loaded callback for library '{library_data.name}': {err}"
|
|
1884
1932
|
)
|
|
@@ -1894,27 +1942,39 @@ class LibraryManager:
|
|
|
1894
1942
|
try:
|
|
1895
1943
|
# Dynamically load the module containing the node class
|
|
1896
1944
|
node_class = self._load_class_from_file(node_file_path, node_definition.class_name, library_data.name)
|
|
1897
|
-
except
|
|
1945
|
+
except ImportError as err:
|
|
1946
|
+
root_cause = self._get_root_cause_from_exception(err)
|
|
1898
1947
|
problems.append(
|
|
1899
|
-
|
|
1948
|
+
NodeModuleImportProblem(
|
|
1949
|
+
class_name=node_definition.class_name,
|
|
1950
|
+
file_path=str(node_file_path),
|
|
1951
|
+
error_message=str(err),
|
|
1952
|
+
root_cause=str(root_cause),
|
|
1953
|
+
)
|
|
1900
1954
|
)
|
|
1901
|
-
details = f"Attempted to load node '{node_definition.class_name}' from '{node_file_path}'. Failed because
|
|
1955
|
+
details = f"Attempted to load node '{node_definition.class_name}' from '{node_file_path}'. Failed because module could not be imported: {err}"
|
|
1902
1956
|
logger.error(details)
|
|
1903
1957
|
continue # SKIP IT
|
|
1904
|
-
|
|
1905
|
-
try:
|
|
1906
|
-
# Register the node type with the library
|
|
1907
|
-
forensics_string = library.register_new_node_type(node_class, metadata=node_definition.metadata)
|
|
1908
|
-
if forensics_string is not None:
|
|
1909
|
-
problems.append(forensics_string)
|
|
1910
|
-
except Exception as err:
|
|
1958
|
+
except AttributeError:
|
|
1911
1959
|
problems.append(
|
|
1912
|
-
|
|
1960
|
+
NodeClassNotFoundProblem(class_name=node_definition.class_name, file_path=str(node_file_path))
|
|
1913
1961
|
)
|
|
1914
|
-
details = f"Attempted to load node '{node_definition.class_name}' from '{node_file_path}'. Failed because
|
|
1962
|
+
details = f"Attempted to load node '{node_definition.class_name}' from '{node_file_path}'. Failed because class not found in module"
|
|
1963
|
+
logger.error(details)
|
|
1964
|
+
continue # SKIP IT
|
|
1965
|
+
except TypeError:
|
|
1966
|
+
problems.append(
|
|
1967
|
+
NodeClassNotBaseNodeProblem(class_name=node_definition.class_name, file_path=str(node_file_path))
|
|
1968
|
+
)
|
|
1969
|
+
details = f"Attempted to load node '{node_definition.class_name}' from '{node_file_path}'. Failed because class doesn't inherit from BaseNode"
|
|
1915
1970
|
logger.error(details)
|
|
1916
1971
|
continue # SKIP IT
|
|
1917
1972
|
|
|
1973
|
+
# Register the node type with the library
|
|
1974
|
+
library_problem = library.register_new_node_type(node_class, metadata=node_definition.metadata)
|
|
1975
|
+
if library_problem is not None:
|
|
1976
|
+
problems.append(library_problem)
|
|
1977
|
+
|
|
1918
1978
|
# If we got here, at least one node came in.
|
|
1919
1979
|
any_nodes_loaded_successfully = True
|
|
1920
1980
|
|
|
@@ -1925,8 +1985,7 @@ class LibraryManager:
|
|
|
1925
1985
|
details = f"Successfully called after_library_nodes_loaded callback for library '{library_data.name}'"
|
|
1926
1986
|
logger.debug(details)
|
|
1927
1987
|
except Exception as err:
|
|
1928
|
-
|
|
1929
|
-
problems.append(problem)
|
|
1988
|
+
problems.append(AfterLibraryCallbackProblem(error_message=str(err)))
|
|
1930
1989
|
details = f"Failed to call after_library_nodes_loaded callback for library '{library_data.name}': {err}"
|
|
1931
1990
|
logger.error(details)
|
|
1932
1991
|
|
|
@@ -1965,7 +2024,15 @@ class LibraryManager:
|
|
|
1965
2024
|
try:
|
|
1966
2025
|
module = self._load_module_from_file(candidate_path, LibraryManager.SANDBOX_LIBRARY_NAME)
|
|
1967
2026
|
except Exception as err:
|
|
1968
|
-
|
|
2027
|
+
root_cause = self._get_root_cause_from_exception(err)
|
|
2028
|
+
problems.append(
|
|
2029
|
+
NodeModuleImportProblem(
|
|
2030
|
+
class_name=node_def.class_name,
|
|
2031
|
+
file_path=str(candidate_path),
|
|
2032
|
+
error_message=str(err),
|
|
2033
|
+
root_cause=str(root_cause),
|
|
2034
|
+
)
|
|
2035
|
+
)
|
|
1969
2036
|
details = f"Attempted to load module in sandbox library '{candidate_path}'. Failed because an exception occurred: {err}."
|
|
1970
2037
|
logger.warning(details)
|
|
1971
2038
|
continue # SKIP IT
|
|
@@ -2031,9 +2098,7 @@ class LibraryManager:
|
|
|
2031
2098
|
library_name=library_data.name,
|
|
2032
2099
|
library_version=library_data.metadata.library_version,
|
|
2033
2100
|
status=LibraryStatus.UNUSABLE,
|
|
2034
|
-
problems=[
|
|
2035
|
-
"Failed because a library with this name was already registered. Check the Settings to ensure duplicate libraries are not being loaded."
|
|
2036
|
-
],
|
|
2101
|
+
problems=[DuplicateLibraryProblem()],
|
|
2037
2102
|
)
|
|
2038
2103
|
|
|
2039
2104
|
details = f"Attempted to load Library JSON file from '{sandbox_library_dir}'. Failed because a Library '{library_data.name}' already exists. Error: {err}."
|
|
@@ -2078,7 +2143,7 @@ class LibraryManager:
|
|
|
2078
2143
|
]
|
|
2079
2144
|
config_mgr.set_config_value(config_category, libraries_to_register_category)
|
|
2080
2145
|
|
|
2081
|
-
async def
|
|
2146
|
+
async def reload_libraries_request(self, request: ReloadAllLibrariesRequest) -> ResultPayload: # noqa: ARG002
|
|
2082
2147
|
# Start with a clean slate.
|
|
2083
2148
|
clear_all_request = ClearAllObjectStateRequest(i_know_what_im_doing=True)
|
|
2084
2149
|
clear_all_result = await GriptapeNodes.ahandle_request(clear_all_request)
|
|
@@ -2111,6 +2176,25 @@ class LibraryManager:
|
|
|
2111
2176
|
)
|
|
2112
2177
|
return ReloadAllLibrariesResultSuccess(result_details=ResultDetails(message=details, level=logging.INFO))
|
|
2113
2178
|
|
|
2179
|
+
async def load_libraries_request(self, request: LoadLibrariesRequest) -> ResultPayload: # noqa: ARG002
|
|
2180
|
+
# Check if there are any new libraries in config that haven't been loaded yet
|
|
2181
|
+
discovered_libraries = {str(path) for path in self._discover_library_files()}
|
|
2182
|
+
loaded_libraries = set(self._library_file_path_to_info.keys())
|
|
2183
|
+
unloaded_libraries = discovered_libraries - loaded_libraries
|
|
2184
|
+
|
|
2185
|
+
if not unloaded_libraries:
|
|
2186
|
+
details = "All configured libraries are already loaded, no action needed."
|
|
2187
|
+
return LoadLibrariesResultSuccess(result_details=ResultDetails(message=details, level=logging.INFO))
|
|
2188
|
+
|
|
2189
|
+
try:
|
|
2190
|
+
await self.load_all_libraries_from_config()
|
|
2191
|
+
details = "Successfully loaded all libraries from configuration."
|
|
2192
|
+
return LoadLibrariesResultSuccess(result_details=ResultDetails(message=details, level=logging.INFO))
|
|
2193
|
+
except Exception as e:
|
|
2194
|
+
details = f"Failed to load libraries from configuration: {e}"
|
|
2195
|
+
logger.error(details)
|
|
2196
|
+
return LoadLibrariesResultFailure(result_details=details)
|
|
2197
|
+
|
|
2114
2198
|
def _discover_library_files(self) -> list[Path]:
|
|
2115
2199
|
"""Discover library JSON files from config and workspace recursively.
|
|
2116
2200
|
|