langgraph-runtime-inmem 0.12.0__py3-none-any.whl → 0.13.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.
@@ -9,7 +9,7 @@ from langgraph_runtime_inmem import (
9
9
  store,
10
10
  )
11
11
 
12
- __version__ = "0.12.0"
12
+ __version__ = "0.13.0"
13
13
  __all__ = [
14
14
  "ops",
15
15
  "database",
@@ -17,6 +17,7 @@ logger = structlog.stdlib.get_logger(__name__)
17
17
  @asynccontextmanager
18
18
  async def lifespan(
19
19
  app: Starlette | None = None,
20
+ cancel_event: asyncio.Event | None = None,
20
21
  taskset: set[asyncio.Task] | None = None,
21
22
  **kwargs: Any,
22
23
  ):
@@ -47,7 +48,7 @@ async def lifespan(
47
48
  try:
48
49
  async with SimpleTaskGroup(
49
50
  cancel=True,
50
- taskset=taskset,
51
+ cancel_event=cancel_event,
51
52
  taskgroup_name="Lifespan",
52
53
  ) as tg:
53
54
  tg.create_task(metadata_loop())
@@ -11,7 +11,6 @@ import uuid
11
11
  from collections import defaultdict
12
12
  from collections.abc import AsyncIterator, Sequence
13
13
  from contextlib import asynccontextmanager
14
- from copy import deepcopy
15
14
  from datetime import UTC, datetime, timedelta
16
15
  from typing import Any, Literal, cast
17
16
  from uuid import UUID, uuid4
@@ -63,9 +62,9 @@ if typing.TYPE_CHECKING:
63
62
  ThreadUpdateResponse,
64
63
  )
65
64
  from langgraph_api.schema import Interrupt as InterruptSchema
66
- from langgraph_api.serde import Fragment
67
65
  from langgraph_api.utils import AsyncConnectionProto
68
66
 
67
+ StreamHandler = ContextQueue
69
68
 
70
69
  logger = structlog.stdlib.get_logger(__name__)
71
70
 
@@ -230,7 +229,7 @@ class Assistants(Authenticated):
230
229
  if assistant["assistant_id"] == assistant_id and (
231
230
  not filters or _check_filter_match(assistant["metadata"], filters)
232
231
  ):
233
- yield assistant
232
+ yield copy.deepcopy(assistant)
234
233
 
235
234
  return _yield_result()
236
235
 
@@ -1256,7 +1255,7 @@ class Threads(Authenticated):
1256
1255
  "thread_id": new_thread_id,
1257
1256
  "created_at": datetime.now(tz=UTC),
1258
1257
  "updated_at": datetime.now(tz=UTC),
1259
- "metadata": deepcopy(original_thread["metadata"]),
1258
+ "metadata": copy.deepcopy(original_thread["metadata"]),
1260
1259
  "status": "idle",
1261
1260
  "config": {},
1262
1261
  }
@@ -2400,66 +2399,6 @@ class Runs(Authenticated):
2400
2399
 
2401
2400
  return _yield_deleted()
2402
2401
 
2403
- @staticmethod
2404
- async def join(
2405
- run_id: UUID,
2406
- *,
2407
- thread_id: UUID,
2408
- ctx: Auth.types.BaseAuthContext | None = None,
2409
- ) -> Fragment:
2410
- """Wait for a run to complete. If already done, return immediately.
2411
-
2412
- Returns:
2413
- the final state of the run.
2414
- """
2415
- from langgraph_api.serde import Fragment
2416
- from langgraph_api.utils import fetchone
2417
-
2418
- async with connect() as conn:
2419
- # Validate ownership
2420
- thread_iter = await Threads.get(conn, thread_id, ctx=ctx)
2421
- await fetchone(thread_iter)
2422
- last_chunk: bytes | None = None
2423
- # wait for the run to complete
2424
- # Rely on this join's auth
2425
- async for mode, chunk, _ in Runs.Stream.join(
2426
- run_id,
2427
- thread_id=thread_id,
2428
- ctx=ctx,
2429
- ignore_404=True,
2430
- stream_mode=["values", "updates", "error"],
2431
- ):
2432
- if mode == b"values":
2433
- last_chunk = chunk
2434
- elif mode == b"updates" and b"__interrupt__" in chunk:
2435
- last_chunk = chunk
2436
- elif mode == b"error":
2437
- last_chunk = orjson.dumps({"__error__": orjson.Fragment(chunk)})
2438
- # if we received a final chunk, return it
2439
- if last_chunk is not None:
2440
- # ie. if the run completed while we were waiting for it
2441
- return Fragment(last_chunk)
2442
- else:
2443
- # otherwise, the run had already finished, so fetch the state from thread
2444
- async with connect() as conn:
2445
- thread_iter = await Threads.get(conn, thread_id, ctx=ctx)
2446
- thread = await fetchone(thread_iter)
2447
- if thread["status"] == "error":
2448
- return Fragment(
2449
- orjson.dumps({"__error__": orjson.Fragment(thread["error"])})
2450
- )
2451
- if thread["status"] == "interrupted":
2452
- # Get an interrupt for the thread. There is the case where there are multiple interrupts for the same run and we may not show the same
2453
- # interrupt, but we'll always show one. Long term we should show all of them.
2454
- try:
2455
- interrupt_map = thread["interrupts"]
2456
- interrupt = [next(iter(interrupt_map.values()))[0]]
2457
- return Fragment(orjson.dumps({"__interrupt__": interrupt}))
2458
- except Exception:
2459
- # No interrupt, but status is interrupted from a before/after block. Default back to values.
2460
- pass
2461
- return thread["values"]
2462
-
2463
2402
  @staticmethod
2464
2403
  async def cancel(
2465
2404
  conn: InMemConnectionProto | AsyncConnectionProto,
@@ -2709,41 +2648,25 @@ class Runs(Authenticated):
2709
2648
  async def join(
2710
2649
  run_id: UUID,
2711
2650
  *,
2651
+ stream_channel: asyncio.Queue,
2712
2652
  thread_id: UUID,
2713
2653
  ignore_404: bool = False,
2714
2654
  cancel_on_disconnect: bool = False,
2715
- stream_channel: asyncio.Queue | None = None,
2716
2655
  stream_mode: list[StreamMode] | StreamMode | None = None,
2717
2656
  last_event_id: str | None = None,
2718
2657
  ctx: Auth.types.BaseAuthContext | None = None,
2719
2658
  ) -> AsyncIterator[tuple[bytes, bytes, bytes | None]]:
2720
2659
  """Stream the run output."""
2721
2660
  from langgraph_api.asyncio import create_task
2722
- from langgraph_api.serde import json_loads
2723
-
2724
- queue = (
2725
- stream_channel
2726
- if stream_channel
2727
- else await Runs.Stream.subscribe(run_id, thread_id)
2728
- )
2661
+ from langgraph_api.serde import json_dumpb, json_loads
2729
2662
 
2663
+ queue = stream_channel
2730
2664
  try:
2731
2665
  async with connect() as conn:
2732
- filters = await Runs.handle_event(
2733
- ctx,
2734
- "read",
2735
- Auth.types.ThreadsRead(thread_id=thread_id),
2736
- )
2737
- if filters:
2738
- thread = await Threads._get_with_filters(
2739
- cast(InMemConnectionProto, conn), thread_id, filters
2740
- )
2741
- if not thread:
2742
- raise WrappedHTTPException(
2743
- HTTPException(
2744
- status_code=404, detail="Thread not found"
2745
- )
2746
- )
2666
+ try:
2667
+ await Runs.Stream.check_run_stream_auth(run_id, thread_id, ctx)
2668
+ except HTTPException as e:
2669
+ raise WrappedHTTPException(e) from None
2747
2670
  run = await Runs.get(conn, run_id, thread_id=thread_id, ctx=ctx)
2748
2671
 
2749
2672
  for message in get_stream_manager().restore_messages(
@@ -2822,8 +2745,10 @@ class Runs(Authenticated):
2822
2745
  elif run is None:
2823
2746
  yield (
2824
2747
  b"error",
2825
- HTTPException(
2826
- status_code=404, detail="Run not found"
2748
+ json_dumpb(
2749
+ HTTPException(
2750
+ status_code=404, detail="Run not found"
2751
+ )
2827
2752
  ),
2828
2753
  None,
2829
2754
  )
@@ -2840,6 +2765,25 @@ class Runs(Authenticated):
2840
2765
  stream_manager = get_stream_manager()
2841
2766
  await stream_manager.remove_queue(run_id, thread_id, queue)
2842
2767
 
2768
+ @staticmethod
2769
+ async def check_run_stream_auth(
2770
+ run_id: UUID,
2771
+ thread_id: UUID,
2772
+ ctx: Auth.types.BaseAuthContext | None = None,
2773
+ ) -> None:
2774
+ async with connect() as conn:
2775
+ filters = await Runs.handle_event(
2776
+ ctx,
2777
+ "read",
2778
+ Auth.types.ThreadsRead(thread_id=thread_id),
2779
+ )
2780
+ if filters:
2781
+ thread = await Threads._get_with_filters(
2782
+ cast(InMemConnectionProto, conn), thread_id, filters
2783
+ )
2784
+ if not thread:
2785
+ raise HTTPException(status_code=404, detail="Thread not found")
2786
+
2843
2787
  @staticmethod
2844
2788
  async def publish(
2845
2789
  run_id: UUID | str,
@@ -3041,6 +2985,7 @@ async def _empty_generator():
3041
2985
 
3042
2986
 
3043
2987
  __all__ = [
2988
+ "StreamHandler",
3044
2989
  "Assistants",
3045
2990
  "Crons",
3046
2991
  "Runs",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-runtime-inmem
3
- Version: 0.12.0
3
+ Version: 0.13.0
4
4
  Summary: Inmem implementation for the LangGraph API server.
5
5
  Author-email: Will Fu-Hinthorn <will@langchain.dev>
6
6
  License: Elastic-2.0
@@ -1,13 +1,13 @@
1
- langgraph_runtime_inmem/__init__.py,sha256=dhduOBpM_s6pggB0_Ux-yEmf0dxOA4ZN9R8tMNmC_gA,311
1
+ langgraph_runtime_inmem/__init__.py,sha256=BfkPnL0o38bb46SxdkPISETcTeuk3iLRkwBytAH1XJk,311
2
2
  langgraph_runtime_inmem/checkpoint.py,sha256=nc1G8DqVdIu-ibjKTqXfbPfMbAsKjPObKqegrSzo6Po,4432
3
3
  langgraph_runtime_inmem/database.py,sha256=QgaA_WQo1IY6QioYd8r-e6-0B0rnC5anS0muIEJWby0,6364
4
4
  langgraph_runtime_inmem/inmem_stream.py,sha256=utL1OlOJsy6VDkSGAA6eX9nETreZlM6K6nhfNoubmRQ,9011
5
- langgraph_runtime_inmem/lifespan.py,sha256=t0w2MX2dGxe8yNtSX97Z-d2pFpllSLS4s1rh2GJDw5M,3557
5
+ langgraph_runtime_inmem/lifespan.py,sha256=tngIYHMhDwTFd2zgpq9CZOxcBLONYYnkhwv2d2T5WWQ,3614
6
6
  langgraph_runtime_inmem/metrics.py,sha256=HhO0RC2bMDTDyGBNvnd2ooLebLA8P1u5oq978Kp_nAA,392
7
- langgraph_runtime_inmem/ops.py,sha256=5fUNLHBrz09TtbK901xdB9CbWV9GZQgw1Z5p0wdqjsY,111320
7
+ langgraph_runtime_inmem/ops.py,sha256=62xhcMEXY2Ijpe_jPqavOaY5EGSlm8p2j7BDKCoAYhM,108891
8
8
  langgraph_runtime_inmem/queue.py,sha256=33qfFKPhQicZ1qiibllYb-bTFzUNSN2c4bffPACP5es,9952
9
9
  langgraph_runtime_inmem/retry.py,sha256=XmldOP4e_H5s264CagJRVnQMDFcEJR_dldVR1Hm5XvM,763
10
10
  langgraph_runtime_inmem/store.py,sha256=rTfL1JJvd-j4xjTrL8qDcynaWF6gUJ9-GDVwH0NBD_I,3506
11
- langgraph_runtime_inmem-0.12.0.dist-info/METADATA,sha256=EpU5xdG2OeTNbvlP286ilVcy8nssuMvsvOGwMgejasw,566
12
- langgraph_runtime_inmem-0.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
13
- langgraph_runtime_inmem-0.12.0.dist-info/RECORD,,
11
+ langgraph_runtime_inmem-0.13.0.dist-info/METADATA,sha256=HSj4R2J9De58icVXoVx2b1tN0zxPDmkjj16r3q5Bvlw,566
12
+ langgraph_runtime_inmem-0.13.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
13
+ langgraph_runtime_inmem-0.13.0.dist-info/RECORD,,