griptape-nodes 0.42.0__py3-none-any.whl → 0.43.1__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 (132) hide show
  1. griptape_nodes/__init__.py +0 -0
  2. griptape_nodes/app/.python-version +0 -0
  3. griptape_nodes/app/__init__.py +1 -6
  4. griptape_nodes/app/api.py +199 -0
  5. griptape_nodes/app/app.py +140 -225
  6. griptape_nodes/app/watch.py +1 -1
  7. griptape_nodes/bootstrap/__init__.py +0 -0
  8. griptape_nodes/bootstrap/bootstrap_script.py +0 -0
  9. griptape_nodes/bootstrap/register_libraries_script.py +0 -0
  10. griptape_nodes/bootstrap/structure_config.yaml +0 -0
  11. griptape_nodes/bootstrap/workflow_executors/__init__.py +0 -0
  12. griptape_nodes/bootstrap/workflow_executors/local_workflow_executor.py +0 -0
  13. griptape_nodes/bootstrap/workflow_executors/workflow_executor.py +0 -0
  14. griptape_nodes/bootstrap/workflow_runners/__init__.py +0 -0
  15. griptape_nodes/bootstrap/workflow_runners/bootstrap_workflow_runner.py +0 -0
  16. griptape_nodes/bootstrap/workflow_runners/local_workflow_runner.py +0 -0
  17. griptape_nodes/bootstrap/workflow_runners/subprocess_workflow_runner.py +6 -2
  18. griptape_nodes/bootstrap/workflow_runners/workflow_runner.py +0 -0
  19. griptape_nodes/drivers/__init__.py +0 -0
  20. griptape_nodes/drivers/storage/__init__.py +0 -0
  21. griptape_nodes/drivers/storage/base_storage_driver.py +0 -0
  22. griptape_nodes/drivers/storage/griptape_cloud_storage_driver.py +0 -0
  23. griptape_nodes/drivers/storage/local_storage_driver.py +2 -1
  24. griptape_nodes/drivers/storage/storage_backend.py +0 -0
  25. griptape_nodes/exe_types/__init__.py +0 -0
  26. griptape_nodes/exe_types/connections.py +0 -0
  27. griptape_nodes/exe_types/core_types.py +0 -0
  28. griptape_nodes/exe_types/flow.py +0 -0
  29. griptape_nodes/exe_types/node_types.py +17 -1
  30. griptape_nodes/exe_types/type_validator.py +0 -0
  31. griptape_nodes/machines/__init__.py +0 -0
  32. griptape_nodes/machines/control_flow.py +41 -12
  33. griptape_nodes/machines/fsm.py +16 -2
  34. griptape_nodes/machines/node_resolution.py +0 -0
  35. griptape_nodes/mcp_server/__init__.py +1 -0
  36. griptape_nodes/mcp_server/server.py +126 -0
  37. griptape_nodes/mcp_server/ws_request_manager.py +268 -0
  38. griptape_nodes/node_library/__init__.py +0 -0
  39. griptape_nodes/node_library/advanced_node_library.py +0 -0
  40. griptape_nodes/node_library/library_registry.py +0 -0
  41. griptape_nodes/node_library/workflow_registry.py +1 -1
  42. griptape_nodes/py.typed +0 -0
  43. griptape_nodes/retained_mode/__init__.py +0 -0
  44. griptape_nodes/retained_mode/events/__init__.py +0 -0
  45. griptape_nodes/retained_mode/events/agent_events.py +0 -0
  46. griptape_nodes/retained_mode/events/app_events.py +6 -2
  47. griptape_nodes/retained_mode/events/arbitrary_python_events.py +0 -0
  48. griptape_nodes/retained_mode/events/base_events.py +6 -6
  49. griptape_nodes/retained_mode/events/config_events.py +0 -0
  50. griptape_nodes/retained_mode/events/connection_events.py +0 -0
  51. griptape_nodes/retained_mode/events/context_events.py +0 -0
  52. griptape_nodes/retained_mode/events/execution_events.py +0 -0
  53. griptape_nodes/retained_mode/events/flow_events.py +0 -0
  54. griptape_nodes/retained_mode/events/generate_request_payload_schemas.py +0 -0
  55. griptape_nodes/retained_mode/events/library_events.py +2 -2
  56. griptape_nodes/retained_mode/events/logger_events.py +0 -0
  57. griptape_nodes/retained_mode/events/node_events.py +0 -0
  58. griptape_nodes/retained_mode/events/object_events.py +0 -0
  59. griptape_nodes/retained_mode/events/os_events.py +104 -2
  60. griptape_nodes/retained_mode/events/parameter_events.py +0 -0
  61. griptape_nodes/retained_mode/events/payload_registry.py +0 -0
  62. griptape_nodes/retained_mode/events/secrets_events.py +0 -0
  63. griptape_nodes/retained_mode/events/static_file_events.py +0 -0
  64. griptape_nodes/retained_mode/events/validation_events.py +0 -0
  65. griptape_nodes/retained_mode/events/workflow_events.py +0 -0
  66. griptape_nodes/retained_mode/griptape_nodes.py +43 -40
  67. griptape_nodes/retained_mode/managers/__init__.py +0 -0
  68. griptape_nodes/retained_mode/managers/agent_manager.py +48 -22
  69. griptape_nodes/retained_mode/managers/arbitrary_code_exec_manager.py +0 -0
  70. griptape_nodes/retained_mode/managers/config_manager.py +0 -0
  71. griptape_nodes/retained_mode/managers/context_manager.py +0 -0
  72. griptape_nodes/retained_mode/managers/engine_identity_manager.py +0 -0
  73. griptape_nodes/retained_mode/managers/event_manager.py +0 -0
  74. griptape_nodes/retained_mode/managers/flow_manager.py +2 -0
  75. griptape_nodes/retained_mode/managers/library_lifecycle/__init__.py +45 -0
  76. griptape_nodes/retained_mode/managers/library_lifecycle/data_models.py +191 -0
  77. griptape_nodes/retained_mode/managers/library_lifecycle/library_directory.py +346 -0
  78. griptape_nodes/retained_mode/managers/library_lifecycle/library_fsm.py +439 -0
  79. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/__init__.py +17 -0
  80. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/base.py +82 -0
  81. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/github.py +116 -0
  82. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/local_file.py +352 -0
  83. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/package.py +104 -0
  84. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance/sandbox.py +155 -0
  85. griptape_nodes/retained_mode/managers/library_lifecycle/library_provenance.py +18 -0
  86. griptape_nodes/retained_mode/managers/library_lifecycle/library_status.py +12 -0
  87. griptape_nodes/retained_mode/managers/library_manager.py +144 -39
  88. griptape_nodes/retained_mode/managers/node_manager.py +86 -72
  89. griptape_nodes/retained_mode/managers/object_manager.py +0 -0
  90. griptape_nodes/retained_mode/managers/operation_manager.py +0 -0
  91. griptape_nodes/retained_mode/managers/os_manager.py +517 -12
  92. griptape_nodes/retained_mode/managers/secrets_manager.py +0 -0
  93. griptape_nodes/retained_mode/managers/session_manager.py +0 -0
  94. griptape_nodes/retained_mode/managers/settings.py +0 -0
  95. griptape_nodes/retained_mode/managers/static_files_manager.py +0 -0
  96. griptape_nodes/retained_mode/managers/version_compatibility_manager.py +2 -2
  97. griptape_nodes/retained_mode/managers/workflow_manager.py +199 -2
  98. griptape_nodes/retained_mode/retained_mode.py +0 -0
  99. griptape_nodes/retained_mode/utils/__init__.py +0 -0
  100. griptape_nodes/retained_mode/utils/engine_identity.py +0 -0
  101. griptape_nodes/retained_mode/utils/name_generator.py +0 -0
  102. griptape_nodes/traits/__init__.py +0 -0
  103. griptape_nodes/traits/add_param_button.py +0 -0
  104. griptape_nodes/traits/button.py +0 -0
  105. griptape_nodes/traits/clamp.py +0 -0
  106. griptape_nodes/traits/compare.py +0 -0
  107. griptape_nodes/traits/compare_images.py +0 -0
  108. griptape_nodes/traits/file_system_picker.py +127 -0
  109. griptape_nodes/traits/minmax.py +0 -0
  110. griptape_nodes/traits/options.py +0 -0
  111. griptape_nodes/traits/slider.py +0 -0
  112. griptape_nodes/traits/trait_registry.py +0 -0
  113. griptape_nodes/traits/traits.json +0 -0
  114. griptape_nodes/updater/__init__.py +2 -2
  115. griptape_nodes/updater/__main__.py +0 -0
  116. griptape_nodes/utils/__init__.py +0 -0
  117. griptape_nodes/utils/dict_utils.py +0 -0
  118. griptape_nodes/utils/image_preview.py +128 -0
  119. griptape_nodes/utils/metaclasses.py +0 -0
  120. griptape_nodes/version_compatibility/__init__.py +0 -0
  121. griptape_nodes/version_compatibility/versions/__init__.py +0 -0
  122. griptape_nodes/version_compatibility/versions/v0_39_0/__init__.py +0 -0
  123. griptape_nodes/version_compatibility/versions/v0_39_0/modified_parameters_set_removal.py +5 -5
  124. griptape_nodes-0.43.1.dist-info/METADATA +90 -0
  125. griptape_nodes-0.43.1.dist-info/RECORD +129 -0
  126. griptape_nodes-0.43.1.dist-info/WHEEL +4 -0
  127. {griptape_nodes-0.42.0.dist-info → griptape_nodes-0.43.1.dist-info}/entry_points.txt +1 -0
  128. griptape_nodes/app/app_sessions.py +0 -554
  129. griptape_nodes-0.42.0.dist-info/METADATA +0 -78
  130. griptape_nodes-0.42.0.dist-info/RECORD +0 -113
  131. griptape_nodes-0.42.0.dist-info/WHEEL +0 -4
  132. griptape_nodes-0.42.0.dist-info/licenses/LICENSE +0 -201
File without changes
File without changes
@@ -1,10 +1,5 @@
1
1
  """App package."""
2
2
 
3
- import os
4
-
5
- if os.getenv("GTN_USE_SESSIONS", "True").lower() == "true":
6
- from griptape_nodes.app.app_sessions import start_app
7
- else:
8
- from griptape_nodes.app.app import start_app
3
+ from griptape_nodes.app.app import start_app
9
4
 
10
5
  __all__ = ["start_app"]
@@ -0,0 +1,199 @@
1
+ from __future__ import annotations
2
+
3
+ import binascii
4
+ import logging
5
+ import os
6
+ from pathlib import Path
7
+ from typing import TYPE_CHECKING, Annotated
8
+ from urllib.parse import urljoin
9
+
10
+ import uvicorn
11
+ from fastapi import Depends, FastAPI, HTTPException, Request
12
+ from fastapi.middleware.cors import CORSMiddleware
13
+ from fastapi.staticfiles import StaticFiles
14
+ from rich.logging import RichHandler
15
+
16
+ from griptape_nodes.retained_mode.events.base_events import EventRequest, deserialize_event
17
+
18
+ if TYPE_CHECKING:
19
+ from queue import Queue
20
+
21
+ # Whether to enable the static server
22
+ STATIC_SERVER_ENABLED = os.getenv("STATIC_SERVER_ENABLED", "true").lower() == "true"
23
+ # Host of the static server
24
+ STATIC_SERVER_HOST = os.getenv("STATIC_SERVER_HOST", "localhost")
25
+ # Port of the static server
26
+ STATIC_SERVER_PORT = int(os.getenv("STATIC_SERVER_PORT", "8124"))
27
+ # URL path for the static server
28
+ STATIC_SERVER_URL = os.getenv("STATIC_SERVER_URL", "/static")
29
+ # Log level for the static server
30
+ STATIC_SERVER_LOG_LEVEL = os.getenv("STATIC_SERVER_LOG_LEVEL", "info").lower()
31
+
32
+ logger = logging.getLogger("griptape_nodes_api")
33
+
34
+ # Global event queue - initialized as None and set when starting the API
35
+ event_queue: Queue | None = None
36
+
37
+ # Global static directory - initialized as None and set when starting the API
38
+ static_dir: Path | None = None
39
+
40
+
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
+ def get_static_dir() -> Path:
50
+ """FastAPI dependency to get the static directory."""
51
+ if static_dir is None:
52
+ msg = "Static directory is not initialized"
53
+ raise HTTPException(status_code=500, detail=msg)
54
+ return static_dir
55
+
56
+
57
+ """Create and configure the FastAPI application."""
58
+ app = FastAPI()
59
+
60
+
61
+ @app.post("/static-upload-urls")
62
+ async def _create_static_file_upload_url(request: Request) -> dict:
63
+ """Create a URL for uploading a static file.
64
+
65
+ Similar to a presigned URL, but for uploading files to the static server.
66
+ """
67
+ base_url = request.base_url
68
+ body = await request.json()
69
+ file_name = body["file_name"]
70
+ url = urljoin(str(base_url), f"/static-uploads/{file_name}")
71
+
72
+ return {"url": url}
73
+
74
+
75
+ @app.put("/static-uploads/{file_path:path}")
76
+ async def _create_static_file(
77
+ request: Request, file_path: str, static_directory: Annotated[Path, Depends(get_static_dir)]
78
+ ) -> dict:
79
+ """Upload a static file to the static server."""
80
+ if not STATIC_SERVER_ENABLED:
81
+ msg = "Static server is not enabled. Please set STATIC_SERVER_ENABLED to True."
82
+ raise ValueError(msg)
83
+
84
+ file_full_path = Path(static_directory / file_path)
85
+
86
+ # Create parent directories if they don't exist
87
+ file_full_path.parent.mkdir(parents=True, exist_ok=True)
88
+
89
+ data = await request.body()
90
+ try:
91
+ file_full_path.write_bytes(data)
92
+ except binascii.Error as e:
93
+ msg = f"Invalid base64 encoding for file {file_path}."
94
+ logger.error(msg)
95
+ raise HTTPException(status_code=400, detail=msg) from e
96
+ except (OSError, PermissionError) as e:
97
+ msg = f"Failed to write file {file_path} to {static_dir}: {e}"
98
+ logger.error(msg)
99
+ raise HTTPException(status_code=500, detail=msg) from e
100
+
101
+ static_url = f"http://{STATIC_SERVER_HOST}:{STATIC_SERVER_PORT}{STATIC_SERVER_URL}/{file_path}"
102
+ return {"url": static_url}
103
+
104
+
105
+ @app.get("/static-uploads/")
106
+ async def _list_static_files(static_directory: Annotated[Path, Depends(get_static_dir)]) -> dict:
107
+ """List all static files in the static server."""
108
+ if not STATIC_SERVER_ENABLED:
109
+ msg = "Static server is not enabled. Please set STATIC_SERVER_ENABLED to True."
110
+ raise HTTPException(status_code=500, detail=msg)
111
+
112
+ try:
113
+ file_names = []
114
+ if static_directory.exists():
115
+ for file_path in static_directory.rglob("*"):
116
+ if file_path.is_file():
117
+ relative_path = file_path.relative_to(static_directory)
118
+ file_names.append(str(relative_path))
119
+ except (OSError, PermissionError) as e:
120
+ msg = f"Failed to list files in static directory: {e}"
121
+ logger.error(msg)
122
+ raise HTTPException(status_code=500, detail=msg) from e
123
+ else:
124
+ return {"files": file_names}
125
+
126
+
127
+ @app.post("/engines/request")
128
+ async def _create_event(request: Request, queue: Annotated[Queue, Depends(get_event_queue)]) -> None:
129
+ body = await request.json()
130
+ _process_api_event(body, queue)
131
+
132
+
133
+ def start_api(static_directory: Path, queue: Queue) -> None:
134
+ """Run FastAPI with Uvicorn in order to serve static files produced by nodes."""
135
+ global event_queue, static_dir # noqa: PLW0603
136
+ event_queue = queue
137
+ static_dir = static_directory
138
+
139
+ logging.getLogger("uvicorn").addHandler(
140
+ RichHandler(show_time=True, show_path=False, markup=True, rich_tracebacks=True)
141
+ )
142
+
143
+ if not static_dir.exists():
144
+ static_dir.mkdir(parents=True, exist_ok=True)
145
+
146
+ app.add_middleware(
147
+ CORSMiddleware,
148
+ allow_origins=[
149
+ os.getenv("GRIPTAPE_NODES_UI_BASE_URL", "https://app.nodes.griptape.ai"),
150
+ "https://app.nodes-staging.griptape.ai",
151
+ "http://localhost:5173",
152
+ ],
153
+ allow_credentials=True,
154
+ allow_methods=["OPTIONS", "GET", "POST", "PUT"],
155
+ allow_headers=["*"],
156
+ )
157
+
158
+ app.mount(
159
+ STATIC_SERVER_URL,
160
+ StaticFiles(directory=static_directory),
161
+ name="static",
162
+ )
163
+
164
+ uvicorn.run(
165
+ app, host=STATIC_SERVER_HOST, port=STATIC_SERVER_PORT, log_level=STATIC_SERVER_LOG_LEVEL, log_config=None
166
+ )
167
+
168
+
169
+ def _process_api_event(event: dict, event_queue: Queue) -> None:
170
+ """Process API events and send them to the event queue."""
171
+ payload = event.get("payload", {})
172
+
173
+ try:
174
+ payload["request"]
175
+ except KeyError:
176
+ msg = "Error: 'request' was expected but not found."
177
+ raise RuntimeError(msg) from None
178
+
179
+ try:
180
+ event_type = payload["event_type"]
181
+ if event_type != "EventRequest":
182
+ msg = "Error: 'event_type' was found on request, but did not match 'EventRequest' as expected."
183
+ raise RuntimeError(msg) from None
184
+ except KeyError:
185
+ msg = "Error: 'event_type' not found in request."
186
+ raise RuntimeError(msg) from None
187
+
188
+ # Now attempt to convert it into an EventRequest.
189
+ try:
190
+ request_event = deserialize_event(json_data=payload)
191
+ if not isinstance(request_event, EventRequest):
192
+ msg = f"Deserialized event is not an EventRequest: {type(request_event)}"
193
+ raise TypeError(msg) # noqa: TRY301
194
+ except Exception as e:
195
+ msg = f"Unable to convert request JSON into a valid EventRequest object. Error Message: '{e}'"
196
+ raise RuntimeError(msg) from None
197
+
198
+ # Add the event to the queue
199
+ event_queue.put(request_event)