griptape-nodes 0.40.0__py3-none-any.whl → 0.42.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/app/__init__.py +1 -5
- griptape_nodes/app/app.py +12 -9
- griptape_nodes/app/app_sessions.py +132 -36
- griptape_nodes/app/watch.py +3 -1
- griptape_nodes/drivers/storage/local_storage_driver.py +3 -2
- griptape_nodes/exe_types/flow.py +68 -368
- griptape_nodes/machines/control_flow.py +16 -13
- griptape_nodes/machines/node_resolution.py +16 -14
- griptape_nodes/node_library/workflow_registry.py +2 -2
- griptape_nodes/retained_mode/events/agent_events.py +70 -8
- griptape_nodes/retained_mode/events/app_events.py +132 -11
- griptape_nodes/retained_mode/events/arbitrary_python_events.py +23 -0
- griptape_nodes/retained_mode/events/base_events.py +7 -25
- griptape_nodes/retained_mode/events/config_events.py +87 -11
- griptape_nodes/retained_mode/events/connection_events.py +56 -5
- griptape_nodes/retained_mode/events/context_events.py +27 -4
- griptape_nodes/retained_mode/events/execution_events.py +99 -14
- griptape_nodes/retained_mode/events/flow_events.py +165 -7
- griptape_nodes/retained_mode/events/library_events.py +193 -15
- griptape_nodes/retained_mode/events/logger_events.py +11 -0
- griptape_nodes/retained_mode/events/node_events.py +243 -22
- griptape_nodes/retained_mode/events/object_events.py +40 -4
- griptape_nodes/retained_mode/events/os_events.py +13 -2
- griptape_nodes/retained_mode/events/parameter_events.py +212 -8
- griptape_nodes/retained_mode/events/secrets_events.py +59 -7
- griptape_nodes/retained_mode/events/static_file_events.py +57 -4
- griptape_nodes/retained_mode/events/validation_events.py +39 -4
- griptape_nodes/retained_mode/events/workflow_events.py +188 -17
- griptape_nodes/retained_mode/griptape_nodes.py +46 -323
- griptape_nodes/retained_mode/managers/agent_manager.py +1 -1
- griptape_nodes/retained_mode/managers/engine_identity_manager.py +146 -0
- griptape_nodes/retained_mode/managers/event_manager.py +14 -2
- griptape_nodes/retained_mode/managers/flow_manager.py +749 -64
- griptape_nodes/retained_mode/managers/library_manager.py +112 -2
- griptape_nodes/retained_mode/managers/node_manager.py +35 -32
- griptape_nodes/retained_mode/managers/object_manager.py +11 -3
- griptape_nodes/retained_mode/managers/os_manager.py +70 -1
- griptape_nodes/retained_mode/managers/secrets_manager.py +4 -0
- griptape_nodes/retained_mode/managers/session_manager.py +328 -0
- griptape_nodes/retained_mode/managers/settings.py +7 -0
- griptape_nodes/retained_mode/managers/workflow_manager.py +523 -454
- griptape_nodes/retained_mode/retained_mode.py +44 -0
- griptape_nodes/retained_mode/utils/engine_identity.py +141 -27
- {griptape_nodes-0.40.0.dist-info → griptape_nodes-0.42.0.dist-info}/METADATA +2 -2
- {griptape_nodes-0.40.0.dist-info → griptape_nodes-0.42.0.dist-info}/RECORD +48 -47
- griptape_nodes/retained_mode/utils/session_persistence.py +0 -105
- {griptape_nodes-0.40.0.dist-info → griptape_nodes-0.42.0.dist-info}/WHEEL +0 -0
- {griptape_nodes-0.40.0.dist-info → griptape_nodes-0.42.0.dist-info}/entry_points.txt +0 -0
- {griptape_nodes-0.40.0.dist-info → griptape_nodes-0.42.0.dist-info}/licenses/LICENSE +0 -0
griptape_nodes/app/__init__.py
CHANGED
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
|
-
if os.getenv("GTN_USE_SESSIONS", "
|
|
6
|
-
# Sessions are only available in the staging environment
|
|
7
|
-
os.environ["GRIPTAPE_NODES_API_BASE_URL"] = os.getenv(
|
|
8
|
-
"GRIPTAPE_NODES_API_BASE_URL", "https://api.nodes-staging.griptape.ai"
|
|
9
|
-
)
|
|
5
|
+
if os.getenv("GTN_USE_SESSIONS", "True").lower() == "true":
|
|
10
6
|
from griptape_nodes.app.app_sessions import start_app
|
|
11
7
|
else:
|
|
12
8
|
from griptape_nodes.app.app import start_app
|
griptape_nodes/app/app.py
CHANGED
|
@@ -149,28 +149,31 @@ def _serve_static_server() -> None:
|
|
|
149
149
|
|
|
150
150
|
return {"url": url}
|
|
151
151
|
|
|
152
|
-
@app.put("/static-uploads/{
|
|
153
|
-
async def create_static_file(request: Request,
|
|
152
|
+
@app.put("/static-uploads/{file_path:path}")
|
|
153
|
+
async def create_static_file(request: Request, file_path: str) -> dict:
|
|
154
154
|
"""Upload a static file to the static server."""
|
|
155
155
|
if not STATIC_SERVER_ENABLED:
|
|
156
156
|
msg = "Static server is not enabled. Please set STATIC_SERVER_ENABLED to True."
|
|
157
157
|
raise ValueError(msg)
|
|
158
158
|
|
|
159
|
-
|
|
160
|
-
|
|
159
|
+
file_full_path = Path(static_dir / file_path)
|
|
160
|
+
|
|
161
|
+
# Create parent directories if they don't exist
|
|
162
|
+
file_full_path.parent.mkdir(parents=True, exist_ok=True)
|
|
163
|
+
|
|
161
164
|
data = await request.body()
|
|
162
165
|
try:
|
|
163
|
-
|
|
166
|
+
file_full_path.write_bytes(data)
|
|
164
167
|
except binascii.Error as e:
|
|
165
|
-
msg = f"Invalid base64 encoding for file {
|
|
168
|
+
msg = f"Invalid base64 encoding for file {file_path}."
|
|
166
169
|
logger.error(msg)
|
|
167
170
|
raise HTTPException(status_code=400, detail=msg) from e
|
|
168
171
|
except (OSError, PermissionError) as e:
|
|
169
|
-
msg = f"Failed to write file {
|
|
172
|
+
msg = f"Failed to write file {file_path} to {config_manager.workspace_path}: {e}"
|
|
170
173
|
logger.error(msg)
|
|
171
174
|
raise HTTPException(status_code=500, detail=msg) from e
|
|
172
175
|
|
|
173
|
-
static_url = f"http://{STATIC_SERVER_HOST}:{STATIC_SERVER_PORT}{STATIC_SERVER_URL}/{
|
|
176
|
+
static_url = f"http://{STATIC_SERVER_HOST}:{STATIC_SERVER_PORT}{STATIC_SERVER_URL}/{file_path}"
|
|
174
177
|
return {"url": static_url}
|
|
175
178
|
|
|
176
179
|
@app.post("/engines/request")
|
|
@@ -422,7 +425,7 @@ def __broadcast_app_initialization_complete(nodes_app_url: str) -> None:
|
|
|
422
425
|
# Broadcast this to anybody who wants a callback on "hey, the app's ready to roll"
|
|
423
426
|
payload = app_events.AppInitializationComplete()
|
|
424
427
|
app_event = AppEvent(payload=payload)
|
|
425
|
-
|
|
428
|
+
event_queue.put(app_event)
|
|
426
429
|
|
|
427
430
|
engine_version_request = app_events.GetEngineVersionRequest()
|
|
428
431
|
engine_version_result = GriptapeNodes.get_instance().handle_engine_version_request(engine_version_request)
|
|
@@ -30,6 +30,7 @@ from websockets.exceptions import ConnectionClosed, WebSocketException
|
|
|
30
30
|
|
|
31
31
|
# This import is necessary to register all events, even if not technically used
|
|
32
32
|
from griptape_nodes.retained_mode.events import app_events, execution_events
|
|
33
|
+
from griptape_nodes.retained_mode.events.app_events import AppEndSessionResultSuccess, AppStartSessionResultSuccess
|
|
33
34
|
from griptape_nodes.retained_mode.events.base_events import (
|
|
34
35
|
AppEvent,
|
|
35
36
|
EventRequest,
|
|
@@ -149,35 +150,37 @@ def _serve_static_server() -> None:
|
|
|
149
150
|
|
|
150
151
|
return {"url": url}
|
|
151
152
|
|
|
152
|
-
@app.put("/static-uploads/{
|
|
153
|
-
async def create_static_file(request: Request,
|
|
153
|
+
@app.put("/static-uploads/{file_path:path}")
|
|
154
|
+
async def create_static_file(request: Request, file_path: str) -> dict:
|
|
154
155
|
"""Upload a static file to the static server."""
|
|
155
156
|
if not STATIC_SERVER_ENABLED:
|
|
156
157
|
msg = "Static server is not enabled. Please set STATIC_SERVER_ENABLED to True."
|
|
157
158
|
raise ValueError(msg)
|
|
158
159
|
|
|
159
|
-
|
|
160
|
-
|
|
160
|
+
file_full_path = Path(static_dir / file_path)
|
|
161
|
+
|
|
162
|
+
# Create parent directories if they don't exist
|
|
163
|
+
file_full_path.parent.mkdir(parents=True, exist_ok=True)
|
|
164
|
+
|
|
161
165
|
data = await request.body()
|
|
162
166
|
try:
|
|
163
|
-
|
|
167
|
+
file_full_path.write_bytes(data)
|
|
164
168
|
except binascii.Error as e:
|
|
165
|
-
msg = f"Invalid base64 encoding for file {
|
|
169
|
+
msg = f"Invalid base64 encoding for file {file_path}."
|
|
166
170
|
logger.error(msg)
|
|
167
171
|
raise HTTPException(status_code=400, detail=msg) from e
|
|
168
172
|
except (OSError, PermissionError) as e:
|
|
169
|
-
msg = f"Failed to write file {
|
|
173
|
+
msg = f"Failed to write file {file_path} to {config_manager.workspace_path}: {e}"
|
|
170
174
|
logger.error(msg)
|
|
171
175
|
raise HTTPException(status_code=500, detail=msg) from e
|
|
172
176
|
|
|
173
|
-
static_url = f"http://{STATIC_SERVER_HOST}:{STATIC_SERVER_PORT}{STATIC_SERVER_URL}/{
|
|
177
|
+
static_url = f"http://{STATIC_SERVER_HOST}:{STATIC_SERVER_PORT}{STATIC_SERVER_URL}/{file_path}"
|
|
174
178
|
return {"url": static_url}
|
|
175
179
|
|
|
176
180
|
@app.post("/engines/request")
|
|
177
181
|
async def create_event(request: Request) -> None:
|
|
178
182
|
body = await request.json()
|
|
179
|
-
|
|
180
|
-
__process_api_event(body["payload"])
|
|
183
|
+
__process_api_event(body)
|
|
181
184
|
|
|
182
185
|
logging.getLogger("uvicorn").addHandler(
|
|
183
186
|
RichHandler(show_time=True, show_path=False, markup=True, rich_tracebacks=True)
|
|
@@ -229,16 +232,19 @@ async def _alisten_for_api_requests() -> None:
|
|
|
229
232
|
async for ws_connection in connection_stream:
|
|
230
233
|
try:
|
|
231
234
|
ws_connection_for_sending = ws_connection # Store for sending events
|
|
235
|
+
|
|
232
236
|
if not initialized:
|
|
233
237
|
__broadcast_app_initialization_complete(nodes_app_url)
|
|
234
238
|
initialized = True
|
|
235
239
|
|
|
240
|
+
# Subscribe to engine ID and session ID on every new connection
|
|
241
|
+
await __subscribe_to_engine_and_session(ws_connection)
|
|
242
|
+
|
|
236
243
|
async for message in ws_connection:
|
|
237
244
|
try:
|
|
238
245
|
data = json.loads(message)
|
|
239
246
|
|
|
240
|
-
|
|
241
|
-
__process_api_event(payload)
|
|
247
|
+
__process_api_event(data)
|
|
242
248
|
except Exception:
|
|
243
249
|
logger.exception("Error processing event, skipping.")
|
|
244
250
|
except ConnectionClosed:
|
|
@@ -259,6 +265,8 @@ def __process_node_event(event: GriptapeNodeEvent) -> None:
|
|
|
259
265
|
result_event = event.wrapped_event
|
|
260
266
|
if isinstance(result_event, EventResultSuccess):
|
|
261
267
|
dest_socket = "success_result"
|
|
268
|
+
# Handle session start events specially
|
|
269
|
+
__handle_session_events(result_event)
|
|
262
270
|
elif isinstance(result_event, EventResultFailure):
|
|
263
271
|
dest_socket = "failure_result"
|
|
264
272
|
else:
|
|
@@ -266,8 +274,28 @@ def __process_node_event(event: GriptapeNodeEvent) -> None:
|
|
|
266
274
|
raise TypeError(msg) from None
|
|
267
275
|
|
|
268
276
|
# Don't send events over the wire that don't have a request_id set (e.g. engine-internal events)
|
|
269
|
-
|
|
270
|
-
|
|
277
|
+
__schedule_async_task(__emit_message(dest_socket, result_event.json(), topic=result_event.response_topic))
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def __handle_session_events(result_event: EventResultSuccess) -> None:
|
|
281
|
+
"""Handle session start/end events by managing subscriptions."""
|
|
282
|
+
global ws_connection_for_sending # noqa: PLW0602
|
|
283
|
+
|
|
284
|
+
if isinstance(result_event.result, AppStartSessionResultSuccess):
|
|
285
|
+
# Subscribe to the new session topic
|
|
286
|
+
session_id = result_event.result.session_id
|
|
287
|
+
if session_id and ws_connection_for_sending:
|
|
288
|
+
topic = f"sessions/{session_id}/request"
|
|
289
|
+
__schedule_async_task(__subscribe_to_topic(ws_connection_for_sending, topic))
|
|
290
|
+
logger.info("Subscribed to new session topic: %s", topic)
|
|
291
|
+
|
|
292
|
+
elif isinstance(result_event.result, AppEndSessionResultSuccess):
|
|
293
|
+
# Unsubscribe from the ended session topic
|
|
294
|
+
session_id = result_event.result.session_id
|
|
295
|
+
if session_id and ws_connection_for_sending:
|
|
296
|
+
topic = f"sessions/{session_id}/request"
|
|
297
|
+
__schedule_async_task(__unsubscribe_from_topic(ws_connection_for_sending, topic))
|
|
298
|
+
logger.info("Unsubscribed from ended session topic: %s", topic)
|
|
271
299
|
|
|
272
300
|
|
|
273
301
|
def __process_execution_node_event(event: ExecutionGriptapeNodeEvent) -> None:
|
|
@@ -275,7 +303,6 @@ def __process_execution_node_event(event: ExecutionGriptapeNodeEvent) -> None:
|
|
|
275
303
|
result_event = event.wrapped_event
|
|
276
304
|
if type(result_event.payload).__name__ == "NodeStartProcessEvent":
|
|
277
305
|
GriptapeNodes.EventManager().current_active_node = result_event.payload.node_name
|
|
278
|
-
event_json = result_event.json()
|
|
279
306
|
|
|
280
307
|
if type(result_event.payload).__name__ == "ResumeNodeProcessingEvent":
|
|
281
308
|
node_name = result_event.payload.node_name
|
|
@@ -289,7 +316,7 @@ def __process_execution_node_event(event: ExecutionGriptapeNodeEvent) -> None:
|
|
|
289
316
|
msg = "Node start and finish do not match."
|
|
290
317
|
raise KeyError(msg) from None
|
|
291
318
|
GriptapeNodes.EventManager().current_active_node = None
|
|
292
|
-
__schedule_async_task(__emit_message("execution_event",
|
|
319
|
+
__schedule_async_task(__emit_message("execution_event", result_event.json()))
|
|
293
320
|
|
|
294
321
|
|
|
295
322
|
def __process_progress_event(gt_event: ProgressEvent) -> None:
|
|
@@ -321,7 +348,9 @@ def _process_event_queue() -> None:
|
|
|
321
348
|
event = event_queue.get(block=True)
|
|
322
349
|
if isinstance(event, EventRequest):
|
|
323
350
|
request_payload = event.request
|
|
324
|
-
GriptapeNodes.handle_request(
|
|
351
|
+
GriptapeNodes.handle_request(
|
|
352
|
+
request_payload, response_topic=event.response_topic, request_id=event.request_id
|
|
353
|
+
)
|
|
325
354
|
elif isinstance(event, AppEvent):
|
|
326
355
|
__process_app_event(event)
|
|
327
356
|
else:
|
|
@@ -350,7 +379,7 @@ def __create_async_websocket_connection() -> Any:
|
|
|
350
379
|
|
|
351
380
|
endpoint = urljoin(
|
|
352
381
|
os.getenv("GRIPTAPE_NODES_API_BASE_URL", "https://api.nodes.griptape.ai").replace("http", "ws"),
|
|
353
|
-
"/ws/engines/events?
|
|
382
|
+
"/ws/engines/events?version=v2",
|
|
354
383
|
)
|
|
355
384
|
|
|
356
385
|
return connect(
|
|
@@ -359,7 +388,7 @@ def __create_async_websocket_connection() -> Any:
|
|
|
359
388
|
)
|
|
360
389
|
|
|
361
390
|
|
|
362
|
-
async def __emit_message(event_type: str, payload: str) -> None:
|
|
391
|
+
async def __emit_message(event_type: str, payload: str, topic: str | None = None) -> None:
|
|
363
392
|
"""Send a message via WebSocket asynchronously."""
|
|
364
393
|
global ws_connection_for_sending # noqa: PLW0602
|
|
365
394
|
if ws_connection_for_sending is None:
|
|
@@ -367,7 +396,12 @@ async def __emit_message(event_type: str, payload: str) -> None:
|
|
|
367
396
|
return
|
|
368
397
|
|
|
369
398
|
try:
|
|
370
|
-
|
|
399
|
+
# Determine topic based on session_id and engine_id in the payload
|
|
400
|
+
if topic is None:
|
|
401
|
+
topic = _determine_response_topic()
|
|
402
|
+
|
|
403
|
+
body = {"type": event_type, "payload": json.loads(payload), "topic": topic}
|
|
404
|
+
|
|
371
405
|
await ws_connection_for_sending.send(json.dumps(body))
|
|
372
406
|
except WebSocketException as e:
|
|
373
407
|
logger.error("Error sending event to Nodes API: %s", e)
|
|
@@ -375,6 +409,78 @@ async def __emit_message(event_type: str, payload: str) -> None:
|
|
|
375
409
|
logger.error("Unexpected error while sending event to Nodes API: %s", e)
|
|
376
410
|
|
|
377
411
|
|
|
412
|
+
def _determine_response_topic() -> str | None:
|
|
413
|
+
"""Determine the response topic based on session_id and engine_id in the payload."""
|
|
414
|
+
engine_id = GriptapeNodes.get_engine_id()
|
|
415
|
+
session_id = GriptapeNodes.get_session_id()
|
|
416
|
+
|
|
417
|
+
# Normal topic determination logic
|
|
418
|
+
# Check for session_id first (highest priority)
|
|
419
|
+
if session_id:
|
|
420
|
+
return f"sessions/{session_id}/response"
|
|
421
|
+
|
|
422
|
+
# Check for engine_id if no session_id
|
|
423
|
+
if engine_id:
|
|
424
|
+
return f"engines/{engine_id}/response"
|
|
425
|
+
|
|
426
|
+
# Default to generic response topic
|
|
427
|
+
return "response"
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
async def __subscribe_to_topic(ws_connection: Any, topic: str) -> None:
|
|
431
|
+
"""Subscribe to a specific topic in the message bus."""
|
|
432
|
+
if ws_connection is None:
|
|
433
|
+
logger.warning("WebSocket connection not available for subscribing to topic")
|
|
434
|
+
return
|
|
435
|
+
|
|
436
|
+
try:
|
|
437
|
+
body = {"type": "subscribe", "topic": topic, "payload": {}}
|
|
438
|
+
await ws_connection.send(json.dumps(body))
|
|
439
|
+
logger.info("Subscribed to topic: %s", topic)
|
|
440
|
+
except WebSocketException as e:
|
|
441
|
+
logger.error("Error subscribing to topic %s: %s", topic, e)
|
|
442
|
+
except Exception as e:
|
|
443
|
+
logger.error("Unexpected error while subscribing to topic %s: %s", topic, e)
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
async def __unsubscribe_from_topic(ws_connection: Any, topic: str) -> None:
|
|
447
|
+
"""Unsubscribe from a specific topic in the message bus."""
|
|
448
|
+
if ws_connection is None:
|
|
449
|
+
logger.warning("WebSocket connection not available for unsubscribing from topic")
|
|
450
|
+
return
|
|
451
|
+
|
|
452
|
+
try:
|
|
453
|
+
body = {"type": "unsubscribe", "topic": topic, "payload": {}}
|
|
454
|
+
await ws_connection.send(json.dumps(body))
|
|
455
|
+
logger.info("Unsubscribed from topic: %s", topic)
|
|
456
|
+
except WebSocketException as e:
|
|
457
|
+
logger.error("Error unsubscribing from topic %s: %s", topic, e)
|
|
458
|
+
except Exception as e:
|
|
459
|
+
logger.error("Unexpected error while unsubscribing from topic %s: %s", topic, e)
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
async def __subscribe_to_engine_and_session(ws_connection: Any) -> None:
|
|
463
|
+
"""Subscribe to engine ID, session ID, and request topics on WebSocket connection."""
|
|
464
|
+
# Subscribe to request topic (engine discovery)
|
|
465
|
+
await __subscribe_to_topic(ws_connection, "request")
|
|
466
|
+
|
|
467
|
+
# Get engine ID and subscribe to engine_id/request
|
|
468
|
+
engine_id = GriptapeNodes.get_engine_id()
|
|
469
|
+
if engine_id:
|
|
470
|
+
await __subscribe_to_topic(ws_connection, f"engines/{engine_id}/request")
|
|
471
|
+
else:
|
|
472
|
+
logger.warning("Engine ID not available for subscription")
|
|
473
|
+
|
|
474
|
+
# Get session ID and subscribe to session_id/request if available
|
|
475
|
+
session_id = GriptapeNodes.get_session_id()
|
|
476
|
+
if session_id:
|
|
477
|
+
topic = f"sessions/{session_id}/request"
|
|
478
|
+
await __subscribe_to_topic(ws_connection, topic)
|
|
479
|
+
logger.info("Subscribed to session topic: %s", topic)
|
|
480
|
+
else:
|
|
481
|
+
logger.info("No session ID available for subscription")
|
|
482
|
+
|
|
483
|
+
|
|
378
484
|
def __schedule_async_task(coro: Any) -> None:
|
|
379
485
|
"""Schedule an async coroutine to run in the event loop from a sync context."""
|
|
380
486
|
if event_loop and event_loop.is_running():
|
|
@@ -388,12 +494,6 @@ def __broadcast_app_initialization_complete(nodes_app_url: str) -> None:
|
|
|
388
494
|
|
|
389
495
|
This is used to notify the GUI that the app is ready to receive events.
|
|
390
496
|
"""
|
|
391
|
-
# Initialize engine ID and persistent data
|
|
392
|
-
from griptape_nodes.retained_mode.events.base_events import BaseEvent
|
|
393
|
-
|
|
394
|
-
BaseEvent.initialize_engine_id()
|
|
395
|
-
BaseEvent.initialize_session_id()
|
|
396
|
-
|
|
397
497
|
# Broadcast this to anybody who wants a callback on "hey, the app's ready to roll"
|
|
398
498
|
payload = app_events.AppInitializationComplete()
|
|
399
499
|
app_event = AppEvent(payload=payload)
|
|
@@ -424,16 +524,18 @@ def __broadcast_app_initialization_complete(nodes_app_url: str) -> None:
|
|
|
424
524
|
console.print(message)
|
|
425
525
|
|
|
426
526
|
|
|
427
|
-
def __process_api_event(
|
|
527
|
+
def __process_api_event(event: dict) -> None:
|
|
428
528
|
"""Process API events and send them to the event queue."""
|
|
529
|
+
payload = event.get("payload", {})
|
|
530
|
+
|
|
429
531
|
try:
|
|
430
|
-
|
|
532
|
+
payload["request"]
|
|
431
533
|
except KeyError:
|
|
432
534
|
msg = "Error: 'request' was expected but not found."
|
|
433
535
|
raise RuntimeError(msg) from None
|
|
434
536
|
|
|
435
537
|
try:
|
|
436
|
-
event_type =
|
|
538
|
+
event_type = payload["event_type"]
|
|
437
539
|
if event_type != "EventRequest":
|
|
438
540
|
msg = "Error: 'event_type' was found on request, but did not match 'EventRequest' as expected."
|
|
439
541
|
raise RuntimeError(msg) from None
|
|
@@ -443,16 +545,10 @@ def __process_api_event(data: dict) -> None:
|
|
|
443
545
|
|
|
444
546
|
# Now attempt to convert it into an EventRequest.
|
|
445
547
|
try:
|
|
446
|
-
request_event: EventRequest = cast("EventRequest", deserialize_event(json_data=
|
|
548
|
+
request_event: EventRequest = cast("EventRequest", deserialize_event(json_data=payload))
|
|
447
549
|
except Exception as e:
|
|
448
550
|
msg = f"Unable to convert request JSON into a valid EventRequest object. Error Message: '{e}'"
|
|
449
551
|
raise RuntimeError(msg) from None
|
|
450
552
|
|
|
451
|
-
# Add a request_id to the payload
|
|
452
|
-
request_id = request_event.request.request_id
|
|
453
|
-
request_event.request.request_id = request_id
|
|
454
|
-
|
|
455
553
|
# Add the event to the queue
|
|
456
554
|
event_queue.put(request_event)
|
|
457
|
-
|
|
458
|
-
return request_id
|
griptape_nodes/app/watch.py
CHANGED
|
@@ -52,7 +52,9 @@ if __name__ == "__main__":
|
|
|
52
52
|
event_handler = ReloadHandler(patterns=["*.py"], ignore_patterns=["*.pyc", "*.pyo"], ignore_directories=True)
|
|
53
53
|
|
|
54
54
|
observer = Observer()
|
|
55
|
-
observer.schedule(event_handler, path="
|
|
55
|
+
observer.schedule(event_handler, path="src", recursive=True)
|
|
56
|
+
observer.schedule(event_handler, path="libraries", recursive=True)
|
|
57
|
+
observer.schedule(event_handler, path="tests", recursive=True)
|
|
56
58
|
observer.start()
|
|
57
59
|
|
|
58
60
|
try:
|
|
@@ -47,7 +47,8 @@ class LocalStorageDriver(BaseStorageDriver):
|
|
|
47
47
|
return {"url": url, "headers": response_data.get("headers", {}), "method": "PUT"}
|
|
48
48
|
|
|
49
49
|
def create_signed_download_url(self, file_name: str) -> str:
|
|
50
|
-
|
|
50
|
+
# The base_url already includes the /static path, so just append the filename
|
|
51
|
+
url = f"{self.base_url}/{file_name}"
|
|
51
52
|
# Add a cache-busting query parameter to the URL so that the browser always reloads the file
|
|
52
|
-
cache_busted_url =
|
|
53
|
+
cache_busted_url = f"{url}?t={int(time.time())}"
|
|
53
54
|
return cache_busted_url
|