griptape-nodes 0.34.3__py3-none-any.whl → 0.35.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 +56 -41
- griptape_nodes/app/app.py +3 -3
- griptape_nodes/bootstrap/bootstrap_script.py +5 -3
- griptape_nodes/drivers/__init__.py +1 -0
- griptape_nodes/drivers/storage/__init__.py +4 -0
- griptape_nodes/drivers/storage/base_storage_driver.py +38 -0
- griptape_nodes/drivers/storage/griptape_cloud_storage_driver.py +85 -0
- griptape_nodes/drivers/storage/local_storage_driver.py +49 -0
- griptape_nodes/exe_types/core_types.py +57 -1
- griptape_nodes/exe_types/flow.py +3 -1
- griptape_nodes/exe_types/node_types.py +34 -0
- griptape_nodes/machines/node_resolution.py +9 -1
- griptape_nodes/node_library/library_registry.py +2 -0
- griptape_nodes/retained_mode/events/execution_events.py +2 -0
- griptape_nodes/retained_mode/events/generate_request_payload_schemas.py +1 -1
- griptape_nodes/retained_mode/events/node_events.py +13 -16
- griptape_nodes/retained_mode/events/parameter_events.py +10 -3
- griptape_nodes/retained_mode/events/static_file_events.py +26 -0
- griptape_nodes/retained_mode/griptape_nodes.py +3 -1
- griptape_nodes/retained_mode/managers/context_manager.py +123 -87
- griptape_nodes/retained_mode/managers/flow_manager.py +126 -86
- griptape_nodes/retained_mode/managers/library_manager.py +279 -95
- griptape_nodes/retained_mode/managers/node_manager.py +230 -159
- griptape_nodes/retained_mode/managers/settings.py +6 -1
- griptape_nodes/retained_mode/managers/static_files_manager.py +77 -54
- griptape_nodes/retained_mode/managers/workflow_manager.py +51 -12
- {griptape_nodes-0.34.3.dist-info → griptape_nodes-0.35.0.dist-info}/METADATA +1 -1
- {griptape_nodes-0.34.3.dist-info → griptape_nodes-0.35.0.dist-info}/RECORD +31 -26
- {griptape_nodes-0.34.3.dist-info → griptape_nodes-0.35.0.dist-info}/WHEEL +0 -0
- {griptape_nodes-0.34.3.dist-info → griptape_nodes-0.35.0.dist-info}/entry_points.txt +0 -0
- {griptape_nodes-0.34.3.dist-info → griptape_nodes-0.35.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import importlib.util
|
|
4
4
|
import json
|
|
5
5
|
import logging
|
|
6
|
+
import os
|
|
6
7
|
import platform
|
|
7
8
|
import subprocess
|
|
8
9
|
import sys
|
|
@@ -24,9 +25,19 @@ from rich.text import Text
|
|
|
24
25
|
from xdg_base_dirs import xdg_data_home
|
|
25
26
|
|
|
26
27
|
from griptape_nodes.exe_types.node_types import BaseNode
|
|
27
|
-
from griptape_nodes.node_library.library_registry import
|
|
28
|
+
from griptape_nodes.node_library.library_registry import (
|
|
29
|
+
CategoryDefinition,
|
|
30
|
+
Library,
|
|
31
|
+
LibraryMetadata,
|
|
32
|
+
LibraryRegistry,
|
|
33
|
+
LibrarySchema,
|
|
34
|
+
NodeDefinition,
|
|
35
|
+
NodeMetadata,
|
|
36
|
+
)
|
|
28
37
|
from griptape_nodes.retained_mode.events.app_events import (
|
|
29
38
|
AppInitializationComplete,
|
|
39
|
+
GetEngineVersionRequest,
|
|
40
|
+
GetEngineVersionResultSuccess,
|
|
30
41
|
)
|
|
31
42
|
from griptape_nodes.retained_mode.events.config_events import (
|
|
32
43
|
GetConfigCategoryRequest,
|
|
@@ -69,6 +80,8 @@ from griptape_nodes.retained_mode.griptape_nodes import GriptapeNodes
|
|
|
69
80
|
from griptape_nodes.retained_mode.managers.os_manager import OSManager
|
|
70
81
|
|
|
71
82
|
if TYPE_CHECKING:
|
|
83
|
+
from types import ModuleType
|
|
84
|
+
|
|
72
85
|
from griptape_nodes.retained_mode.events.base_events import ResultPayload
|
|
73
86
|
from griptape_nodes.retained_mode.managers.event_manager import EventManager
|
|
74
87
|
|
|
@@ -342,7 +355,7 @@ class LibraryManager:
|
|
|
342
355
|
|
|
343
356
|
# Load the JSON
|
|
344
357
|
try:
|
|
345
|
-
with json_path.open("r") as f:
|
|
358
|
+
with json_path.open("r", encoding="utf-8") as f:
|
|
346
359
|
library_json = json.load(f)
|
|
347
360
|
except json.JSONDecodeError:
|
|
348
361
|
self._library_file_path_to_info[file_path] = LibraryManager.LibraryInfo(
|
|
@@ -444,13 +457,11 @@ class LibraryManager:
|
|
|
444
457
|
# Install node library dependencies
|
|
445
458
|
try:
|
|
446
459
|
site_packages = None
|
|
447
|
-
if library_data.metadata.dependencies:
|
|
460
|
+
if library_data.metadata.dependencies and library_data.metadata.dependencies.pip_dependencies:
|
|
448
461
|
pip_install_flags = library_data.metadata.dependencies.pip_install_flags
|
|
449
462
|
if pip_install_flags is None:
|
|
450
463
|
pip_install_flags = []
|
|
451
464
|
pip_dependencies = library_data.metadata.dependencies.pip_dependencies
|
|
452
|
-
if pip_dependencies is None:
|
|
453
|
-
pip_dependencies = []
|
|
454
465
|
|
|
455
466
|
# Create a virtual environment for the library
|
|
456
467
|
python_version = platform.python_version()
|
|
@@ -553,77 +564,33 @@ class LibraryManager:
|
|
|
553
564
|
continue # SKIP IT
|
|
554
565
|
|
|
555
566
|
# Attempt to load nodes from the library.
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
)
|
|
571
|
-
|
|
567
|
+
library_load_results = self._attempt_load_nodes_from_library(
|
|
568
|
+
library_data=library_data,
|
|
569
|
+
library=library,
|
|
570
|
+
base_dir=base_dir,
|
|
571
|
+
library_file_path=file_path,
|
|
572
|
+
library_version=library_version,
|
|
573
|
+
problems=problems,
|
|
574
|
+
)
|
|
575
|
+
self._library_file_path_to_info[file_path] = library_load_results
|
|
576
|
+
|
|
577
|
+
match library_load_results.status:
|
|
578
|
+
case LibraryManager.LibraryStatus.GOOD:
|
|
579
|
+
details = f"Successfully loaded Library '{library_data.name}' from JSON file at {json_path}"
|
|
580
|
+
logger.info(details)
|
|
581
|
+
return RegisterLibraryFromFileResultSuccess(library_name=library_data.name)
|
|
582
|
+
case LibraryManager.LibraryStatus.FLAWED:
|
|
583
|
+
details = f"Successfully loaded Library JSON file from '{json_path}', but one or more nodes failed to load. Check the log for more details."
|
|
584
|
+
logger.warning(details)
|
|
585
|
+
return RegisterLibraryFromFileResultSuccess(library_name=library_data.name)
|
|
586
|
+
case LibraryManager.LibraryStatus.UNUSABLE:
|
|
587
|
+
details = f"Attempted to load Library JSON file from '{json_path}'. Failed because no nodes were loaded. Check the log for more details."
|
|
572
588
|
logger.error(details)
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
# Register the node type with the library
|
|
577
|
-
forensics_string = library.register_new_node_type(node_class, metadata=node_definition.metadata)
|
|
578
|
-
if forensics_string is not None:
|
|
579
|
-
problems.append(forensics_string)
|
|
580
|
-
except Exception as err:
|
|
581
|
-
problems.append(
|
|
582
|
-
f"Failed to register node '{node_definition.class_name}' from '{node_file_path}' with error: {err}"
|
|
583
|
-
)
|
|
584
|
-
details = f"Attempted to load node '{node_definition.class_name}' from '{node_file_path}'. Failed because an exception occurred: {err}"
|
|
589
|
+
return RegisterLibraryFromFileResultFailure()
|
|
590
|
+
case _:
|
|
591
|
+
details = f"Attempted to load Library JSON file from '{json_path}'. Failed because an unknown/unexpected status '{library_load_results.status}' was returned."
|
|
585
592
|
logger.error(details)
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
# If we got here, at least one node came in.
|
|
589
|
-
any_nodes_loaded_successesfully = True
|
|
590
|
-
|
|
591
|
-
if not any_nodes_loaded_successesfully:
|
|
592
|
-
self._library_file_path_to_info[file_path] = LibraryManager.LibraryInfo(
|
|
593
|
-
library_path=file_path,
|
|
594
|
-
library_name=library_data.name,
|
|
595
|
-
library_version=library_version,
|
|
596
|
-
status=LibraryManager.LibraryStatus.UNUSABLE,
|
|
597
|
-
problems=problems,
|
|
598
|
-
)
|
|
599
|
-
details = f"Attempted to load Library JSON file from '{json_path}'. Failed because no nodes were loaded. Check the log for more details."
|
|
600
|
-
logger.error(details)
|
|
601
|
-
return RegisterLibraryFromFileResultFailure()
|
|
602
|
-
|
|
603
|
-
# Successes, but errors.
|
|
604
|
-
if problems:
|
|
605
|
-
self._library_file_path_to_info[file_path] = LibraryManager.LibraryInfo(
|
|
606
|
-
library_path=file_path,
|
|
607
|
-
library_name=library_data.name,
|
|
608
|
-
library_version=library_version,
|
|
609
|
-
status=LibraryManager.LibraryStatus.FLAWED,
|
|
610
|
-
problems=problems,
|
|
611
|
-
)
|
|
612
|
-
details = f"Successfully loaded Library JSON file from '{json_path}', but one or more nodes failed to load. Check the log for more details."
|
|
613
|
-
logger.warning(details)
|
|
614
|
-
else:
|
|
615
|
-
# Flawless victory.
|
|
616
|
-
self._library_file_path_to_info[file_path] = LibraryManager.LibraryInfo(
|
|
617
|
-
library_path=file_path,
|
|
618
|
-
library_name=library_data.name,
|
|
619
|
-
library_version=library_version,
|
|
620
|
-
status=LibraryManager.LibraryStatus.GOOD,
|
|
621
|
-
problems=problems,
|
|
622
|
-
)
|
|
623
|
-
details = f"Successfully loaded Library '{library_data.name}' from JSON file at {json_path}"
|
|
624
|
-
logger.info(details)
|
|
625
|
-
|
|
626
|
-
return RegisterLibraryFromFileResultSuccess(library_name=library_data.name)
|
|
593
|
+
return RegisterLibraryFromFileResultFailure()
|
|
627
594
|
|
|
628
595
|
def register_library_from_requirement_specifier_request(
|
|
629
596
|
self, request: RegisterLibraryFromRequirementSpecifierRequest
|
|
@@ -779,20 +746,17 @@ class LibraryManager:
|
|
|
779
746
|
)
|
|
780
747
|
return result
|
|
781
748
|
|
|
782
|
-
def
|
|
783
|
-
"""Dynamically load a
|
|
749
|
+
def _load_module_from_file(self, file_path: Path | str) -> ModuleType:
|
|
750
|
+
"""Dynamically load a module from a Python file with support for hot reloading.
|
|
784
751
|
|
|
785
752
|
Args:
|
|
786
753
|
file_path: Path to the Python file
|
|
787
|
-
class_name: Name of the class to load
|
|
788
754
|
|
|
789
755
|
Returns:
|
|
790
|
-
The loaded
|
|
756
|
+
The loaded module
|
|
791
757
|
|
|
792
758
|
Raises:
|
|
793
759
|
ImportError: If the module cannot be imported
|
|
794
|
-
AttributeError: If the class doesn't exist in the module
|
|
795
|
-
TypeError: If the loaded class isn't a BaseNode-derived class
|
|
796
760
|
"""
|
|
797
761
|
# Ensure file_path is a Path object
|
|
798
762
|
file_path = Path(file_path)
|
|
@@ -846,9 +810,32 @@ class LibraryManager:
|
|
|
846
810
|
try:
|
|
847
811
|
spec.loader.exec_module(module)
|
|
848
812
|
except Exception as err:
|
|
849
|
-
msg = f"
|
|
813
|
+
msg = f"Module at '{file_path}' failed to load with error: {err}"
|
|
850
814
|
raise ImportError(msg) from err
|
|
851
815
|
|
|
816
|
+
return module
|
|
817
|
+
|
|
818
|
+
def _load_class_from_file(self, file_path: Path | str, class_name: str) -> type[BaseNode]:
|
|
819
|
+
"""Dynamically load a class from a Python file with support for hot reloading.
|
|
820
|
+
|
|
821
|
+
Args:
|
|
822
|
+
file_path: Path to the Python file
|
|
823
|
+
class_name: Name of the class to load
|
|
824
|
+
|
|
825
|
+
Returns:
|
|
826
|
+
The loaded class
|
|
827
|
+
|
|
828
|
+
Raises:
|
|
829
|
+
ImportError: If the module cannot be imported
|
|
830
|
+
AttributeError: If the class doesn't exist in the module
|
|
831
|
+
TypeError: If the loaded class isn't a BaseNode-derived class
|
|
832
|
+
"""
|
|
833
|
+
try:
|
|
834
|
+
module = self._load_module_from_file(file_path)
|
|
835
|
+
except ImportError as err:
|
|
836
|
+
msg = f"Attempted to load class '{class_name}'. Error: {err}"
|
|
837
|
+
raise ImportError(msg) from err
|
|
838
|
+
|
|
852
839
|
# Get the class
|
|
853
840
|
try:
|
|
854
841
|
node_class = getattr(module, class_name)
|
|
@@ -867,7 +854,13 @@ class LibraryManager:
|
|
|
867
854
|
user_libraries_section = "app_events.on_app_initialization_complete.libraries_to_register"
|
|
868
855
|
self._load_libraries_from_config_category(config_category=user_libraries_section, load_as_default_library=False)
|
|
869
856
|
|
|
870
|
-
|
|
857
|
+
sandbox_library_section = "sandbox_library_directory"
|
|
858
|
+
self._attempt_generate_sandbox_library(config_category=sandbox_library_section)
|
|
859
|
+
|
|
860
|
+
# Print 'em all pretty
|
|
861
|
+
self.print_library_load_status()
|
|
862
|
+
|
|
863
|
+
# Remove any missing libraries AFTER we've printed them for the user.
|
|
871
864
|
self._remove_missing_libraries_from_config(config_category=user_libraries_section)
|
|
872
865
|
|
|
873
866
|
def on_app_initialization_complete(self, _payload: AppInitializationComplete) -> None:
|
|
@@ -909,25 +902,216 @@ class LibraryManager:
|
|
|
909
902
|
# Go tell the Workflow Manager that it's turn is now.
|
|
910
903
|
GriptapeNodes.WorkflowManager().on_libraries_initialization_complete()
|
|
911
904
|
|
|
905
|
+
def _attempt_load_nodes_from_library( # noqa: PLR0913
|
|
906
|
+
self,
|
|
907
|
+
library_data: LibrarySchema,
|
|
908
|
+
library: Library,
|
|
909
|
+
base_dir: Path,
|
|
910
|
+
library_file_path: str,
|
|
911
|
+
library_version: str | None,
|
|
912
|
+
problems: list[str],
|
|
913
|
+
) -> LibraryManager.LibraryInfo:
|
|
914
|
+
any_nodes_loaded_successfully = False
|
|
915
|
+
# Process each node in the metadata
|
|
916
|
+
for node_definition in library_data.nodes:
|
|
917
|
+
# Resolve relative path to absolute path
|
|
918
|
+
node_file_path = Path(node_definition.file_path)
|
|
919
|
+
if not node_file_path.is_absolute():
|
|
920
|
+
node_file_path = base_dir / node_file_path
|
|
921
|
+
|
|
922
|
+
try:
|
|
923
|
+
# Dynamically load the module containing the node class
|
|
924
|
+
node_class = self._load_class_from_file(node_file_path, node_definition.class_name)
|
|
925
|
+
except Exception as err:
|
|
926
|
+
problems.append(
|
|
927
|
+
f"Failed to load node '{node_definition.class_name}' from '{node_file_path}' with error: {err}"
|
|
928
|
+
)
|
|
929
|
+
details = f"Attempted to load node '{node_definition.class_name}' from '{node_file_path}'. Failed because an exception occurred: {err}"
|
|
930
|
+
logger.error(details)
|
|
931
|
+
continue # SKIP IT
|
|
932
|
+
|
|
933
|
+
try:
|
|
934
|
+
# Register the node type with the library
|
|
935
|
+
forensics_string = library.register_new_node_type(node_class, metadata=node_definition.metadata)
|
|
936
|
+
if forensics_string is not None:
|
|
937
|
+
problems.append(forensics_string)
|
|
938
|
+
except Exception as err:
|
|
939
|
+
problems.append(
|
|
940
|
+
f"Failed to register node '{node_definition.class_name}' from '{node_file_path}' with error: {err}"
|
|
941
|
+
)
|
|
942
|
+
details = f"Attempted to load node '{node_definition.class_name}' from '{node_file_path}'. Failed because an exception occurred: {err}"
|
|
943
|
+
logger.error(details)
|
|
944
|
+
continue # SKIP IT
|
|
945
|
+
|
|
946
|
+
# If we got here, at least one node came in.
|
|
947
|
+
any_nodes_loaded_successfully = True
|
|
948
|
+
|
|
949
|
+
# Create a LibraryInfo object based on load successes and problem count.
|
|
950
|
+
if not any_nodes_loaded_successfully:
|
|
951
|
+
status = LibraryManager.LibraryStatus.UNUSABLE
|
|
952
|
+
elif problems:
|
|
953
|
+
# Success, but errors.
|
|
954
|
+
status = LibraryManager.LibraryStatus.FLAWED
|
|
955
|
+
else:
|
|
956
|
+
# Flawless victory.
|
|
957
|
+
status = LibraryManager.LibraryStatus.GOOD
|
|
958
|
+
|
|
959
|
+
# Create a LibraryInfo object based on load successes and problem count.
|
|
960
|
+
return LibraryManager.LibraryInfo(
|
|
961
|
+
library_path=library_file_path,
|
|
962
|
+
library_name=library_data.name,
|
|
963
|
+
library_version=library_version,
|
|
964
|
+
status=status,
|
|
965
|
+
problems=problems,
|
|
966
|
+
)
|
|
967
|
+
|
|
968
|
+
def _attempt_generate_sandbox_library(self, config_category: str) -> None:
|
|
969
|
+
config_mgr = GriptapeNodes.ConfigManager()
|
|
970
|
+
sandbox_library_subdir = config_mgr.get_config_value(config_category)
|
|
971
|
+
if not sandbox_library_subdir:
|
|
972
|
+
logger.debug("No sandbox directory specified in config at key '%s'. Skipping.", config_category)
|
|
973
|
+
return
|
|
974
|
+
|
|
975
|
+
# Prepend the workflow directory; if the sandbox dir starts with a slash, the workflow dir will be ignored.
|
|
976
|
+
sandbox_library_dir = config_mgr.workspace_path / sandbox_library_subdir
|
|
977
|
+
sandbox_library_dir_as_posix = sandbox_library_dir.as_posix()
|
|
978
|
+
|
|
979
|
+
sandbox_node_candidates = self._find_files_in_dir(directory=sandbox_library_dir, extension=".py")
|
|
980
|
+
if not sandbox_node_candidates:
|
|
981
|
+
logger.debug("No candidate files found in sandbox directory '%s'. Skipping.", sandbox_library_dir)
|
|
982
|
+
return
|
|
983
|
+
|
|
984
|
+
sandbox_category = CategoryDefinition(
|
|
985
|
+
title="Sandbox",
|
|
986
|
+
description="Nodes loaded from the Sandbox Library.",
|
|
987
|
+
color="#ff0000",
|
|
988
|
+
icon="Folder",
|
|
989
|
+
)
|
|
990
|
+
|
|
991
|
+
problems = []
|
|
992
|
+
|
|
993
|
+
# Trawl through the Python files and find those that are nodes.
|
|
994
|
+
node_definitions = []
|
|
995
|
+
for candidate in sandbox_node_candidates:
|
|
996
|
+
try:
|
|
997
|
+
module = self._load_module_from_file(candidate)
|
|
998
|
+
except Exception as err:
|
|
999
|
+
problems.append(f"Could not load module in sandbox library '{candidate}': {err}")
|
|
1000
|
+
details = f"Attempted to load module in sandbox library '{candidate}'. Failed because an exception occurred: {err}."
|
|
1001
|
+
logger.warning(details)
|
|
1002
|
+
continue # SKIP IT
|
|
1003
|
+
|
|
1004
|
+
# Peek inside for any BaseNodes.
|
|
1005
|
+
for class_name, obj in vars(module).items():
|
|
1006
|
+
if (
|
|
1007
|
+
isinstance(obj, type)
|
|
1008
|
+
and issubclass(obj, BaseNode)
|
|
1009
|
+
and type(obj) is not BaseNode
|
|
1010
|
+
and obj.__module__ == module.__name__
|
|
1011
|
+
):
|
|
1012
|
+
details = f"Found node '{class_name}' in sandbox library '{candidate}'."
|
|
1013
|
+
logger.debug(details)
|
|
1014
|
+
node_metadata = NodeMetadata(
|
|
1015
|
+
category="Griptape Nodes Sandbox",
|
|
1016
|
+
description=f"'{class_name}' (loaded from the Sandbox Library).",
|
|
1017
|
+
display_name=class_name,
|
|
1018
|
+
)
|
|
1019
|
+
node_definition = NodeDefinition(
|
|
1020
|
+
class_name=class_name,
|
|
1021
|
+
file_path=str(candidate),
|
|
1022
|
+
metadata=node_metadata,
|
|
1023
|
+
)
|
|
1024
|
+
node_definitions.append(node_definition)
|
|
1025
|
+
|
|
1026
|
+
if not node_definitions:
|
|
1027
|
+
logger.info("No nodes found in sandbox library '%s'. Skipping.", sandbox_library_dir)
|
|
1028
|
+
return
|
|
1029
|
+
|
|
1030
|
+
# Create the library schema and metadata.
|
|
1031
|
+
engine_version = GriptapeNodes().handle_engine_version_request(request=GetEngineVersionRequest())
|
|
1032
|
+
if not isinstance(engine_version, GetEngineVersionResultSuccess):
|
|
1033
|
+
logger.error("Could not get engine version. Skipping sandbox library.")
|
|
1034
|
+
return
|
|
1035
|
+
engine_version_str = f"{engine_version.major}.{engine_version.minor}.{engine_version.patch}"
|
|
1036
|
+
library_metadata = LibraryMetadata(
|
|
1037
|
+
author="Author needs to be specified when library is published.",
|
|
1038
|
+
description="Nodes loaded from the sandbox library.",
|
|
1039
|
+
library_version=engine_version_str,
|
|
1040
|
+
engine_version=engine_version_str,
|
|
1041
|
+
tags=["sandbox"],
|
|
1042
|
+
is_griptape_nodes_searchable=False,
|
|
1043
|
+
)
|
|
1044
|
+
categories = [
|
|
1045
|
+
{"Griptape Nodes Sandbox": sandbox_category},
|
|
1046
|
+
]
|
|
1047
|
+
library_data = LibrarySchema(
|
|
1048
|
+
name="Sandbox Library",
|
|
1049
|
+
library_schema_version=LibrarySchema.LATEST_SCHEMA_VERSION,
|
|
1050
|
+
metadata=library_metadata,
|
|
1051
|
+
categories=categories,
|
|
1052
|
+
nodes=node_definitions,
|
|
1053
|
+
)
|
|
1054
|
+
|
|
1055
|
+
# Register the library.
|
|
1056
|
+
# Create or get the library
|
|
1057
|
+
try:
|
|
1058
|
+
# Try to create a new library
|
|
1059
|
+
library = LibraryRegistry.generate_new_library(
|
|
1060
|
+
library_data=library_data,
|
|
1061
|
+
mark_as_default_library=True,
|
|
1062
|
+
)
|
|
1063
|
+
|
|
1064
|
+
except KeyError as err:
|
|
1065
|
+
# Library already exists
|
|
1066
|
+
self._library_file_path_to_info[sandbox_library_dir_as_posix] = LibraryManager.LibraryInfo(
|
|
1067
|
+
library_path=sandbox_library_dir_as_posix,
|
|
1068
|
+
library_name=library_data.name,
|
|
1069
|
+
library_version=engine_version_str,
|
|
1070
|
+
status=LibraryManager.LibraryStatus.UNUSABLE,
|
|
1071
|
+
problems=["Failed because a library with this name was already registered."],
|
|
1072
|
+
)
|
|
1073
|
+
|
|
1074
|
+
details = f"Attempted to load Library JSON file from '{sandbox_library_dir}'. Failed because a Library '{library_data.name}' already exists. Error: {err}."
|
|
1075
|
+
logger.error(details)
|
|
1076
|
+
return
|
|
1077
|
+
|
|
1078
|
+
# Attempt to load nodes from the library.
|
|
1079
|
+
library_load_results = self._attempt_load_nodes_from_library(
|
|
1080
|
+
library_data=library_data,
|
|
1081
|
+
library=library,
|
|
1082
|
+
base_dir=sandbox_library_dir_as_posix,
|
|
1083
|
+
library_file_path=sandbox_library_dir_as_posix,
|
|
1084
|
+
library_version=engine_version_str,
|
|
1085
|
+
problems=problems,
|
|
1086
|
+
)
|
|
1087
|
+
self._library_file_path_to_info[sandbox_library_dir_as_posix] = library_load_results
|
|
1088
|
+
|
|
1089
|
+
def _find_files_in_dir(self, directory: Path, extension: str) -> list[Path]:
|
|
1090
|
+
ret_val = []
|
|
1091
|
+
for root, _, files_found in os.walk(directory):
|
|
1092
|
+
for file in files_found:
|
|
1093
|
+
if file.endswith(extension):
|
|
1094
|
+
file_path = Path(root) / file
|
|
1095
|
+
ret_val.append(file_path)
|
|
1096
|
+
return ret_val
|
|
1097
|
+
|
|
912
1098
|
def _load_libraries_from_config_category(self, config_category: str, *, load_as_default_library: bool) -> None:
|
|
913
1099
|
config_mgr = GriptapeNodes.ConfigManager()
|
|
914
1100
|
libraries_to_register_category: list[str] = config_mgr.get_config_value(config_category)
|
|
915
1101
|
|
|
916
1102
|
if libraries_to_register_category is not None:
|
|
917
1103
|
for library_to_register in libraries_to_register_category:
|
|
918
|
-
if library_to_register
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
# Print 'em all pretty
|
|
930
|
-
self.print_library_load_status()
|
|
1104
|
+
if library_to_register:
|
|
1105
|
+
if library_to_register.endswith(".json"):
|
|
1106
|
+
library_load_request = RegisterLibraryFromFileRequest(
|
|
1107
|
+
file_path=library_to_register,
|
|
1108
|
+
load_as_default_library=load_as_default_library,
|
|
1109
|
+
)
|
|
1110
|
+
else:
|
|
1111
|
+
library_load_request = RegisterLibraryFromRequirementSpecifierRequest(
|
|
1112
|
+
requirement_specifier=library_to_register
|
|
1113
|
+
)
|
|
1114
|
+
GriptapeNodes.handle_request(library_load_request)
|
|
931
1115
|
|
|
932
1116
|
def _remove_missing_libraries_from_config(self, config_category: str) -> None:
|
|
933
1117
|
# Now remove all libraries that were missing from the user's config.
|