griptape-nodes 0.58.1__py3-none-any.whl → 0.59.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/utils/python_subprocess_executor.py +2 -2
- griptape_nodes/bootstrap/workflow_executors/local_session_workflow_executor.py +0 -5
- griptape_nodes/bootstrap/workflow_executors/local_workflow_executor.py +9 -5
- griptape_nodes/bootstrap/workflow_executors/subprocess_workflow_executor.py +0 -1
- griptape_nodes/bootstrap/workflow_executors/workflow_executor.py +1 -3
- griptape_nodes/bootstrap/workflow_publishers/local_workflow_publisher.py +1 -1
- griptape_nodes/cli/commands/init.py +53 -7
- griptape_nodes/cli/shared.py +1 -0
- griptape_nodes/common/node_executor.py +216 -40
- griptape_nodes/exe_types/core_types.py +46 -0
- griptape_nodes/exe_types/node_types.py +272 -0
- griptape_nodes/machines/control_flow.py +222 -16
- griptape_nodes/machines/dag_builder.py +212 -1
- griptape_nodes/machines/parallel_resolution.py +237 -4
- griptape_nodes/node_library/workflow_registry.py +1 -1
- griptape_nodes/retained_mode/events/execution_events.py +5 -4
- griptape_nodes/retained_mode/events/flow_events.py +17 -67
- griptape_nodes/retained_mode/events/parameter_events.py +122 -1
- griptape_nodes/retained_mode/managers/event_manager.py +17 -13
- griptape_nodes/retained_mode/managers/flow_manager.py +316 -573
- griptape_nodes/retained_mode/managers/library_manager.py +32 -20
- griptape_nodes/retained_mode/managers/model_manager.py +19 -8
- griptape_nodes/retained_mode/managers/node_manager.py +463 -3
- griptape_nodes/retained_mode/managers/object_manager.py +2 -2
- griptape_nodes/retained_mode/managers/workflow_manager.py +37 -46
- griptape_nodes/retained_mode/retained_mode.py +297 -3
- {griptape_nodes-0.58.1.dist-info → griptape_nodes-0.59.0.dist-info}/METADATA +3 -2
- {griptape_nodes-0.58.1.dist-info → griptape_nodes-0.59.0.dist-info}/RECORD +30 -30
- {griptape_nodes-0.58.1.dist-info → griptape_nodes-0.59.0.dist-info}/WHEEL +1 -1
- {griptape_nodes-0.58.1.dist-info → griptape_nodes-0.59.0.dist-info}/entry_points.txt +0 -0
|
@@ -169,6 +169,8 @@ class LibraryManager:
|
|
|
169
169
|
self._library_event_handler_mappings: dict[type[Payload], dict[str, LibraryManager.RegisteredEventHandler]] = {}
|
|
170
170
|
# LibraryDirectory owns the FSMs and manages library lifecycle
|
|
171
171
|
self._library_directory = LibraryDirectory()
|
|
172
|
+
# Lock for synchronizing sys.path modifications during parallel library installation
|
|
173
|
+
self._sys_path_lock = asyncio.Lock()
|
|
172
174
|
|
|
173
175
|
event_manager.assign_manager_to_request_type(
|
|
174
176
|
ListRegisteredLibrariesRequest, self.on_list_registered_libraries_request
|
|
@@ -724,7 +726,8 @@ class LibraryManager:
|
|
|
724
726
|
# Get the directory containing the JSON file to resolve relative paths
|
|
725
727
|
base_dir = json_path.parent.absolute()
|
|
726
728
|
# Add the directory to the Python path to allow for relative imports
|
|
727
|
-
|
|
729
|
+
async with self._sys_path_lock:
|
|
730
|
+
sys.path.insert(0, str(base_dir))
|
|
728
731
|
|
|
729
732
|
# Load the advanced library module if specified
|
|
730
733
|
advanced_library_instance = None
|
|
@@ -1057,7 +1060,8 @@ class LibraryManager:
|
|
|
1057
1060
|
)
|
|
1058
1061
|
)
|
|
1059
1062
|
)
|
|
1060
|
-
|
|
1063
|
+
async with self._sys_path_lock:
|
|
1064
|
+
sys.path.insert(0, site_packages)
|
|
1061
1065
|
|
|
1062
1066
|
return library_venv_python_path
|
|
1063
1067
|
|
|
@@ -1499,6 +1503,27 @@ class LibraryManager:
|
|
|
1499
1503
|
|
|
1500
1504
|
return node_class
|
|
1501
1505
|
|
|
1506
|
+
async def _register_single_library(self, library_result: LoadLibraryMetadataFromFileResultSuccess) -> None:
|
|
1507
|
+
"""Register a single library (sandbox or config-based) and handle errors.
|
|
1508
|
+
|
|
1509
|
+
Args:
|
|
1510
|
+
library_result: The metadata result for the library to register
|
|
1511
|
+
"""
|
|
1512
|
+
try:
|
|
1513
|
+
if library_result.library_schema.name == LibraryManager.SANDBOX_LIBRARY_NAME:
|
|
1514
|
+
await self._attempt_generate_sandbox_library_from_schema(
|
|
1515
|
+
library_schema=library_result.library_schema, sandbox_directory=library_result.file_path
|
|
1516
|
+
)
|
|
1517
|
+
else:
|
|
1518
|
+
register_request = RegisterLibraryFromFileRequest(
|
|
1519
|
+
file_path=library_result.file_path, load_as_default_library=False
|
|
1520
|
+
)
|
|
1521
|
+
register_result = await self.register_library_from_file_request(register_request)
|
|
1522
|
+
if isinstance(register_result, RegisterLibraryFromFileResultFailure):
|
|
1523
|
+
logger.warning("Failed to register library from %s", library_result.file_path)
|
|
1524
|
+
except Exception as e:
|
|
1525
|
+
logger.warning("Failed to register library from %s with exception: %s", library_result.file_path, e)
|
|
1526
|
+
|
|
1502
1527
|
async def load_all_libraries_from_config(self) -> None:
|
|
1503
1528
|
# Load metadata for all libraries to determine which ones can be safely loaded
|
|
1504
1529
|
metadata_request = LoadMetadataForAllLibrariesRequest()
|
|
@@ -1518,23 +1543,10 @@ class LibraryManager:
|
|
|
1518
1543
|
problems=failed_library.problems,
|
|
1519
1544
|
)
|
|
1520
1545
|
|
|
1521
|
-
# Use
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
await self._attempt_generate_sandbox_library_from_schema(
|
|
1526
|
-
library_schema=library_result.library_schema, sandbox_directory=library_result.file_path
|
|
1527
|
-
)
|
|
1528
|
-
else:
|
|
1529
|
-
# Handle config-based library - register it directly using the file path
|
|
1530
|
-
register_request = RegisterLibraryFromFileRequest(
|
|
1531
|
-
file_path=library_result.file_path, load_as_default_library=False
|
|
1532
|
-
)
|
|
1533
|
-
register_result = await self.register_library_from_file_request(register_request)
|
|
1534
|
-
if isinstance(register_result, RegisterLibraryFromFileResultFailure):
|
|
1535
|
-
# Registration failed - the failure info is already recorded in _library_file_path_to_info
|
|
1536
|
-
# by register_library_from_file_request, so we just log it here for visibility
|
|
1537
|
-
logger.warning("Failed to register library from %s", library_result.file_path)
|
|
1546
|
+
# Use task group for parallel library loading
|
|
1547
|
+
async with asyncio.TaskGroup() as tg:
|
|
1548
|
+
for library_result in metadata_result.successful_libraries:
|
|
1549
|
+
tg.create_task(self._register_single_library(library_result))
|
|
1538
1550
|
|
|
1539
1551
|
# Print 'em all pretty
|
|
1540
1552
|
self.print_library_load_status()
|
|
@@ -2004,7 +2016,7 @@ class LibraryManager:
|
|
|
2004
2016
|
async def reload_all_libraries_request(self, request: ReloadAllLibrariesRequest) -> ResultPayload: # noqa: ARG002
|
|
2005
2017
|
# Start with a clean slate.
|
|
2006
2018
|
clear_all_request = ClearAllObjectStateRequest(i_know_what_im_doing=True)
|
|
2007
|
-
clear_all_result = GriptapeNodes.
|
|
2019
|
+
clear_all_result = await GriptapeNodes.ahandle_request(clear_all_request)
|
|
2008
2020
|
if not clear_all_result.succeeded():
|
|
2009
2021
|
details = "Failed to clear the existing object state when preparing to reload all libraries."
|
|
2010
2022
|
logger.error(details)
|
|
@@ -121,6 +121,7 @@ class ModelDownloadTracker(tqdm):
|
|
|
121
121
|
def close(self) -> None:
|
|
122
122
|
"""Override close to log download completion."""
|
|
123
123
|
super().close()
|
|
124
|
+
self._update_status_file() # Write final state to status file
|
|
124
125
|
logger.debug(
|
|
125
126
|
"ModelDownloadTracker close - model_id: %s, self.n: %s, total: %s", self.model_id, self.n, self.total
|
|
126
127
|
)
|
|
@@ -190,13 +191,21 @@ class ModelDownloadTracker(tqdm):
|
|
|
190
191
|
progress_percent,
|
|
191
192
|
)
|
|
192
193
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
194
|
+
# Check if download is complete
|
|
195
|
+
is_complete = self.total > 0 and self.n >= self.total
|
|
196
|
+
|
|
197
|
+
update_data = {
|
|
198
|
+
"downloaded_files": self.n,
|
|
199
|
+
"progress_percent": progress_percent,
|
|
200
|
+
"updated_at": current_time,
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
# Update status to completed if all files are downloaded
|
|
204
|
+
if is_complete:
|
|
205
|
+
update_data["status"] = "completed"
|
|
206
|
+
update_data["completed_at"] = current_time
|
|
207
|
+
|
|
208
|
+
data.update(update_data)
|
|
200
209
|
|
|
201
210
|
with status_file.open("w") as f:
|
|
202
211
|
json.dump(data, f, indent=2)
|
|
@@ -426,9 +435,11 @@ class ModelManager:
|
|
|
426
435
|
# Store process for cancellation
|
|
427
436
|
self._download_processes[model_id] = process
|
|
428
437
|
|
|
429
|
-
stdout,
|
|
438
|
+
stdout, stderr = await process.communicate()
|
|
430
439
|
|
|
431
440
|
if process.returncode == 0:
|
|
441
|
+
logger.debug(stdout.decode().strip())
|
|
442
|
+
logger.debug(stderr.decode().strip())
|
|
432
443
|
logger.info("Successfully downloaded model '%s'", model_id)
|
|
433
444
|
else:
|
|
434
445
|
raise ValueError(stdout.decode().strip())
|