griptape-nodes 0.51.2__py3-none-any.whl → 0.52.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.
Files changed (46) hide show
  1. griptape_nodes/__init__.py +5 -4
  2. griptape_nodes/app/api.py +27 -24
  3. griptape_nodes/app/app.py +243 -221
  4. griptape_nodes/app/watch.py +17 -2
  5. griptape_nodes/bootstrap/workflow_executors/local_workflow_executor.py +66 -103
  6. griptape_nodes/bootstrap/workflow_executors/workflow_executor.py +16 -4
  7. griptape_nodes/exe_types/core_types.py +16 -4
  8. griptape_nodes/exe_types/node_types.py +74 -16
  9. griptape_nodes/machines/control_flow.py +21 -26
  10. griptape_nodes/machines/fsm.py +16 -16
  11. griptape_nodes/machines/node_resolution.py +30 -119
  12. griptape_nodes/mcp_server/server.py +14 -10
  13. griptape_nodes/mcp_server/ws_request_manager.py +2 -2
  14. griptape_nodes/node_library/workflow_registry.py +5 -0
  15. griptape_nodes/retained_mode/events/base_events.py +12 -7
  16. griptape_nodes/retained_mode/events/execution_events.py +0 -6
  17. griptape_nodes/retained_mode/events/node_events.py +38 -0
  18. griptape_nodes/retained_mode/events/parameter_events.py +11 -0
  19. griptape_nodes/retained_mode/events/variable_events.py +361 -0
  20. griptape_nodes/retained_mode/events/workflow_events.py +35 -0
  21. griptape_nodes/retained_mode/griptape_nodes.py +61 -26
  22. griptape_nodes/retained_mode/managers/agent_manager.py +8 -9
  23. griptape_nodes/retained_mode/managers/event_manager.py +215 -74
  24. griptape_nodes/retained_mode/managers/flow_manager.py +39 -33
  25. griptape_nodes/retained_mode/managers/library_lifecycle/library_directory.py +14 -14
  26. griptape_nodes/retained_mode/managers/library_lifecycle/library_fsm.py +20 -20
  27. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/base.py +1 -1
  28. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/github.py +1 -1
  29. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/local_file.py +4 -3
  30. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/package.py +1 -1
  31. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/sandbox.py +1 -1
  32. griptape_nodes/retained_mode/managers/library_manager.py +20 -19
  33. griptape_nodes/retained_mode/managers/node_manager.py +83 -8
  34. griptape_nodes/retained_mode/managers/object_manager.py +4 -0
  35. griptape_nodes/retained_mode/managers/settings.py +1 -0
  36. griptape_nodes/retained_mode/managers/sync_manager.py +3 -9
  37. griptape_nodes/retained_mode/managers/variable_manager.py +529 -0
  38. griptape_nodes/retained_mode/managers/workflow_manager.py +156 -50
  39. griptape_nodes/retained_mode/variable_types.py +18 -0
  40. griptape_nodes/utils/__init__.py +4 -0
  41. griptape_nodes/utils/async_utils.py +89 -0
  42. {griptape_nodes-0.51.2.dist-info → griptape_nodes-0.52.0.dist-info}/METADATA +2 -3
  43. {griptape_nodes-0.51.2.dist-info → griptape_nodes-0.52.0.dist-info}/RECORD +45 -42
  44. {griptape_nodes-0.51.2.dist-info → griptape_nodes-0.52.0.dist-info}/WHEEL +1 -1
  45. griptape_nodes/bootstrap/workflow_executors/subprocess_workflow_executor.py +0 -90
  46. {griptape_nodes-0.51.2.dist-info → griptape_nodes-0.52.0.dist-info}/entry_points.txt +0 -0
@@ -6,6 +6,7 @@ console = Console()
6
6
 
7
7
  with console.status("Loading Griptape Nodes...") as status:
8
8
  import argparse
9
+ import asyncio
9
10
  import json
10
11
  import os
11
12
  import shutil
@@ -113,7 +114,7 @@ def _run_init(config: InitConfig) -> None:
113
114
 
114
115
  # Sync libraries
115
116
  if config.libraries_sync is not False:
116
- _sync_libraries()
117
+ asyncio.run(_sync_libraries())
117
118
 
118
119
  console.print("[bold green]Initialization complete![/bold green]")
119
120
 
@@ -683,7 +684,7 @@ def _update_self() -> None:
683
684
  os_manager.replace_process([sys.executable, "-m", "griptape_nodes.updater"])
684
685
 
685
686
 
686
- def _sync_libraries() -> None:
687
+ async def _sync_libraries() -> None:
687
688
  """Download and sync Griptape Nodes libraries, copying only directories from synced libraries."""
688
689
  install_source, _ = get_install_source()
689
690
  # Unless we're installed from PyPi, grab libraries from the 'latest' tag
@@ -737,7 +738,7 @@ def _sync_libraries() -> None:
737
738
  # Re-initialize all libraries from config
738
739
  console.print("[bold cyan]Initializing libraries...[/bold cyan]")
739
740
  try:
740
- GriptapeNodes.LibraryManager().load_all_libraries_from_config()
741
+ await GriptapeNodes.LibraryManager().load_all_libraries_from_config()
741
742
  console.print("[bold green]Libraries Initialized successfully.[/bold green]")
742
743
  except Exception as e:
743
744
  console.print(f"[red]Error initializing libraries: {e}[/red]")
@@ -904,7 +905,7 @@ def _process_args(args: argparse.Namespace) -> None: # noqa: C901, PLR0912
904
905
  _print_current_version()
905
906
  elif args.command == "libraries":
906
907
  if args.subcommand == "sync":
907
- _sync_libraries()
908
+ asyncio.run(_sync_libraries())
908
909
  else:
909
910
  msg = f"Unknown command: {args.command}"
910
911
  raise ValueError(msg)
griptape_nodes/app/api.py CHANGED
@@ -4,7 +4,7 @@ import binascii
4
4
  import logging
5
5
  import os
6
6
  from pathlib import Path
7
- from typing import TYPE_CHECKING, Annotated
7
+ from typing import Annotated
8
8
  from urllib.parse import urljoin
9
9
 
10
10
  import uvicorn
@@ -13,9 +13,6 @@ from fastapi.middleware.cors import CORSMiddleware
13
13
  from fastapi.staticfiles import StaticFiles
14
14
  from rich.logging import RichHandler
15
15
 
16
- if TYPE_CHECKING:
17
- from queue import Queue
18
-
19
16
  # Whether to enable the static server
20
17
  STATIC_SERVER_ENABLED = os.getenv("STATIC_SERVER_ENABLED", "true").lower() == "true"
21
18
  # Host of the static server
@@ -31,21 +28,10 @@ logger = logging.getLogger("griptape_nodes_api")
31
28
  logging.getLogger("uvicorn").addHandler(RichHandler(show_time=True, show_path=False, markup=True, rich_tracebacks=True))
32
29
 
33
30
 
34
- # Global event queue - initialized as None and set when starting the API
35
- event_queue: Queue | None = None
36
-
37
31
  # Global static directory - initialized as None and set when starting the API
38
32
  static_dir: Path | None = None
39
33
 
40
34
 
41
- def get_event_queue() -> Queue:
42
- """FastAPI dependency to get the event queue."""
43
- if event_queue is None:
44
- msg = "Event queue is not initialized"
45
- raise HTTPException(status_code=500, detail=msg)
46
- return event_queue
47
-
48
-
49
35
  def get_static_dir() -> Path:
50
36
  """FastAPI dependency to get the static directory."""
51
37
  if static_dir is None:
@@ -156,17 +142,19 @@ async def _delete_static_file(file_path: str, static_directory: Annotated[Path,
156
142
 
157
143
 
158
144
  @app.post("/engines/request")
159
- async def _create_event(request: Request, queue: Annotated[Queue, Depends(get_event_queue)]) -> None:
145
+ async def _create_event(request: Request) -> None:
146
+ """Create event using centralized event utilities."""
160
147
  from .app import _process_api_event
161
148
 
162
149
  body = await request.json()
163
- _process_api_event(body, queue)
164
150
 
151
+ # Use centralized event processing
152
+ await _process_api_event(body)
165
153
 
166
- def start_api(static_directory: Path, queue: Queue) -> None:
167
- """Run FastAPI with Uvicorn in order to serve static files produced by nodes."""
168
- global event_queue, static_dir # noqa: PLW0603
169
- event_queue = queue
154
+
155
+ def _setup_app(static_directory: Path) -> None:
156
+ """Setup FastAPI app with middleware and static files."""
157
+ global static_dir # noqa: PLW0603
170
158
  static_dir = static_directory
171
159
 
172
160
  if not static_dir.exists():
@@ -190,6 +178,21 @@ def start_api(static_directory: Path, queue: Queue) -> None:
190
178
  name="static",
191
179
  )
192
180
 
193
- uvicorn.run(
194
- app, host=STATIC_SERVER_HOST, port=STATIC_SERVER_PORT, log_level=STATIC_SERVER_LOG_LEVEL, log_config=None
195
- )
181
+
182
+ def start_api(static_directory: Path) -> None:
183
+ """Run uvicorn server synchronously using uvicorn.run."""
184
+ # Setup the FastAPI app
185
+ _setup_app(static_directory)
186
+
187
+ try:
188
+ # Run server using uvicorn.run
189
+ uvicorn.run(
190
+ app,
191
+ host=STATIC_SERVER_HOST,
192
+ port=STATIC_SERVER_PORT,
193
+ log_level=STATIC_SERVER_LOG_LEVEL,
194
+ log_config=None,
195
+ )
196
+ except Exception as e:
197
+ logger.error("API server failed: %s", e)
198
+ raise