langgraph-runtime-inmem 0.13.0__py3-none-any.whl → 0.14.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.
- langgraph_runtime_inmem/__init__.py +1 -1
- langgraph_runtime_inmem/inmem_stream.py +2 -1
- langgraph_runtime_inmem/ops.py +58 -90
- {langgraph_runtime_inmem-0.13.0.dist-info → langgraph_runtime_inmem-0.14.0.dist-info}/METADATA +1 -1
- {langgraph_runtime_inmem-0.13.0.dist-info → langgraph_runtime_inmem-0.14.0.dist-info}/RECORD +6 -6
- {langgraph_runtime_inmem-0.13.0.dist-info → langgraph_runtime_inmem-0.14.0.dist-info}/WHEEL +0 -0
|
@@ -108,9 +108,10 @@ class StreamManager:
|
|
|
108
108
|
thread_id = _ensure_uuid(thread_id)
|
|
109
109
|
|
|
110
110
|
message.id = _generate_ms_seq_id().encode()
|
|
111
|
+
# For resumable run streams, embed the generated message ID into the frame
|
|
112
|
+
topic = message.topic.decode()
|
|
111
113
|
if resumable:
|
|
112
114
|
self.message_stores[thread_id][run_id].append(message)
|
|
113
|
-
topic = message.topic.decode()
|
|
114
115
|
if "control" in topic:
|
|
115
116
|
self.control_keys[thread_id][run_id] = message
|
|
116
117
|
queues = self.control_queues[thread_id][run_id]
|
langgraph_runtime_inmem/ops.py
CHANGED
|
@@ -1720,6 +1720,9 @@ class Threads(Authenticated):
|
|
|
1720
1720
|
stream_modes: list[ThreadStreamMode],
|
|
1721
1721
|
) -> AsyncIterator[tuple[bytes, bytes, bytes | None]]:
|
|
1722
1722
|
"""Stream the thread output."""
|
|
1723
|
+
from langgraph_api.utils.stream_codec import (
|
|
1724
|
+
decode_stream_message,
|
|
1725
|
+
)
|
|
1723
1726
|
|
|
1724
1727
|
def should_filter_event(event_name: str, message_bytes: bytes) -> bool:
|
|
1725
1728
|
"""Check if an event should be filtered out based on stream_modes."""
|
|
@@ -1738,8 +1741,6 @@ class Threads(Authenticated):
|
|
|
1738
1741
|
pass
|
|
1739
1742
|
return True
|
|
1740
1743
|
|
|
1741
|
-
from langgraph_api.serde import json_loads
|
|
1742
|
-
|
|
1743
1744
|
stream_manager = get_stream_manager()
|
|
1744
1745
|
seen_runs: set[UUID] = set()
|
|
1745
1746
|
created_queues: list[tuple[UUID, asyncio.Queue]] = []
|
|
@@ -1768,35 +1769,26 @@ class Threads(Authenticated):
|
|
|
1768
1769
|
|
|
1769
1770
|
# Yield sorted events
|
|
1770
1771
|
for message, run_id in all_events:
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1772
|
+
decoded = decode_stream_message(
|
|
1773
|
+
message.data, channel=message.topic
|
|
1774
|
+
)
|
|
1775
|
+
event_bytes = decoded.event_bytes
|
|
1776
|
+
message_bytes = decoded.message_bytes
|
|
1774
1777
|
|
|
1775
|
-
if
|
|
1776
|
-
if
|
|
1778
|
+
if event_bytes == b"control":
|
|
1779
|
+
if message_bytes == b"done":
|
|
1777
1780
|
event_bytes = b"metadata"
|
|
1778
1781
|
message_bytes = orjson.dumps(
|
|
1779
1782
|
{"status": "run_done", "run_id": run_id}
|
|
1780
1783
|
)
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
)
|
|
1790
|
-
else:
|
|
1791
|
-
event_bytes = event_name.encode()
|
|
1792
|
-
message_bytes = base64.b64decode(message_content)
|
|
1793
|
-
# Filter events based on stream_modes
|
|
1794
|
-
if not should_filter_event(event_name, message_bytes):
|
|
1795
|
-
yield (
|
|
1796
|
-
event_bytes,
|
|
1797
|
-
message_bytes,
|
|
1798
|
-
message.id,
|
|
1799
|
-
)
|
|
1784
|
+
if not should_filter_event(
|
|
1785
|
+
event_bytes.decode("utf-8"), message_bytes
|
|
1786
|
+
):
|
|
1787
|
+
yield (
|
|
1788
|
+
event_bytes,
|
|
1789
|
+
message_bytes,
|
|
1790
|
+
message.id,
|
|
1791
|
+
)
|
|
1800
1792
|
|
|
1801
1793
|
# Listen for live messages from all queues
|
|
1802
1794
|
while True:
|
|
@@ -1813,40 +1805,27 @@ class Threads(Authenticated):
|
|
|
1813
1805
|
message = await asyncio.wait_for(
|
|
1814
1806
|
queue.get(), timeout=0.2
|
|
1815
1807
|
)
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
if not should_filter_event(
|
|
1831
|
-
"metadata", message_bytes
|
|
1832
|
-
):
|
|
1833
|
-
yield (
|
|
1834
|
-
event_bytes,
|
|
1835
|
-
message_bytes,
|
|
1836
|
-
message.id,
|
|
1837
|
-
)
|
|
1838
|
-
else:
|
|
1839
|
-
event_bytes = event_name.encode()
|
|
1840
|
-
message_bytes = base64.b64decode(message_content)
|
|
1841
|
-
# Filter events based on stream_modes
|
|
1808
|
+
decoded = decode_stream_message(
|
|
1809
|
+
message.data, channel=message.topic
|
|
1810
|
+
)
|
|
1811
|
+
event = decoded.event_bytes
|
|
1812
|
+
event_name = event.decode("utf-8")
|
|
1813
|
+
payload = decoded.message_bytes
|
|
1814
|
+
|
|
1815
|
+
if event == b"control" and payload == b"done":
|
|
1816
|
+
topic = message.topic.decode()
|
|
1817
|
+
run_id = topic.split("run:")[1].split(":")[0]
|
|
1818
|
+
meta_event = b"metadata"
|
|
1819
|
+
meta_payload = orjson.dumps(
|
|
1820
|
+
{"status": "run_done", "run_id": run_id}
|
|
1821
|
+
)
|
|
1842
1822
|
if not should_filter_event(
|
|
1843
|
-
|
|
1823
|
+
"metadata", meta_payload
|
|
1844
1824
|
):
|
|
1845
|
-
yield (
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
)
|
|
1825
|
+
yield (meta_event, meta_payload, message.id)
|
|
1826
|
+
else:
|
|
1827
|
+
if not should_filter_event(event_name, payload):
|
|
1828
|
+
yield (event, payload, message.id)
|
|
1850
1829
|
|
|
1851
1830
|
except TimeoutError:
|
|
1852
1831
|
continue
|
|
@@ -1882,18 +1861,12 @@ class Threads(Authenticated):
|
|
|
1882
1861
|
message: bytes,
|
|
1883
1862
|
) -> None:
|
|
1884
1863
|
"""Publish a thread-level event to the thread stream."""
|
|
1885
|
-
from langgraph_api.
|
|
1864
|
+
from langgraph_api.utils.stream_codec import STREAM_CODEC
|
|
1886
1865
|
|
|
1887
1866
|
topic = f"thread:{thread_id}:stream".encode()
|
|
1888
1867
|
|
|
1889
1868
|
stream_manager = get_stream_manager()
|
|
1890
|
-
|
|
1891
|
-
payload = json_dumpb(
|
|
1892
|
-
{
|
|
1893
|
-
"event": event,
|
|
1894
|
-
"message": message,
|
|
1895
|
-
}
|
|
1896
|
-
)
|
|
1869
|
+
payload = STREAM_CODEC.encode(event, message)
|
|
1897
1870
|
await stream_manager.put_thread(
|
|
1898
1871
|
str(thread_id), Message(topic=topic, data=payload)
|
|
1899
1872
|
)
|
|
@@ -2065,6 +2038,7 @@ class Runs(Authenticated):
|
|
|
2065
2038
|
This method should be called as a context manager by a worker executing a run.
|
|
2066
2039
|
"""
|
|
2067
2040
|
from langgraph_api.asyncio import SimpleTaskGroup, ValueEvent
|
|
2041
|
+
from langgraph_api.utils.stream_codec import STREAM_CODEC
|
|
2068
2042
|
|
|
2069
2043
|
stream_manager = get_stream_manager()
|
|
2070
2044
|
# Get control queue for this run (normal queue is created during run creation)
|
|
@@ -2084,10 +2058,10 @@ class Runs(Authenticated):
|
|
|
2084
2058
|
)
|
|
2085
2059
|
await stream_manager.put(run_id, thread_id, control_message)
|
|
2086
2060
|
|
|
2087
|
-
# Signal done to all subscribers
|
|
2061
|
+
# Signal done to all subscribers using stream codec
|
|
2088
2062
|
stream_message = Message(
|
|
2089
2063
|
topic=f"run:{run_id}:stream".encode(),
|
|
2090
|
-
data=
|
|
2064
|
+
data=STREAM_CODEC.encode("control", b"done"),
|
|
2091
2065
|
)
|
|
2092
2066
|
await stream_manager.put(
|
|
2093
2067
|
run_id, thread_id, stream_message, resumable=resumable
|
|
@@ -2658,7 +2632,8 @@ class Runs(Authenticated):
|
|
|
2658
2632
|
) -> AsyncIterator[tuple[bytes, bytes, bytes | None]]:
|
|
2659
2633
|
"""Stream the run output."""
|
|
2660
2634
|
from langgraph_api.asyncio import create_task
|
|
2661
|
-
from langgraph_api.serde import json_dumpb
|
|
2635
|
+
from langgraph_api.serde import json_dumpb
|
|
2636
|
+
from langgraph_api.utils.stream_codec import decode_stream_message
|
|
2662
2637
|
|
|
2663
2638
|
queue = stream_channel
|
|
2664
2639
|
try:
|
|
@@ -2673,13 +2648,12 @@ class Runs(Authenticated):
|
|
|
2673
2648
|
run_id, thread_id, last_event_id
|
|
2674
2649
|
):
|
|
2675
2650
|
data, id = message.data, message.id
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
message = data["message"]
|
|
2651
|
+
decoded = decode_stream_message(data, channel=message.topic)
|
|
2652
|
+
mode = decoded.event_bytes.decode("utf-8")
|
|
2653
|
+
payload = decoded.message_bytes
|
|
2680
2654
|
|
|
2681
2655
|
if mode == "control":
|
|
2682
|
-
if
|
|
2656
|
+
if payload == b"done":
|
|
2683
2657
|
return
|
|
2684
2658
|
elif (
|
|
2685
2659
|
not stream_mode
|
|
@@ -2692,7 +2666,7 @@ class Runs(Authenticated):
|
|
|
2692
2666
|
and mode.startswith("messages")
|
|
2693
2667
|
)
|
|
2694
2668
|
):
|
|
2695
|
-
yield mode.encode(),
|
|
2669
|
+
yield mode.encode(), payload, id
|
|
2696
2670
|
logger.debug(
|
|
2697
2671
|
"Replayed run event",
|
|
2698
2672
|
run_id=str(run_id),
|
|
@@ -2706,13 +2680,12 @@ class Runs(Authenticated):
|
|
|
2706
2680
|
# Wait for messages with a timeout
|
|
2707
2681
|
message = await asyncio.wait_for(queue.get(), timeout=0.5)
|
|
2708
2682
|
data, id = message.data, message.id
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
message = data["message"]
|
|
2683
|
+
decoded = decode_stream_message(data, channel=message.topic)
|
|
2684
|
+
mode = decoded.event_bytes.decode("utf-8")
|
|
2685
|
+
payload = decoded.message_bytes
|
|
2713
2686
|
|
|
2714
2687
|
if mode == "control":
|
|
2715
|
-
if
|
|
2688
|
+
if payload == b"done":
|
|
2716
2689
|
break
|
|
2717
2690
|
elif (
|
|
2718
2691
|
not stream_mode
|
|
@@ -2725,13 +2698,13 @@ class Runs(Authenticated):
|
|
|
2725
2698
|
and mode.startswith("messages")
|
|
2726
2699
|
)
|
|
2727
2700
|
):
|
|
2728
|
-
yield mode.encode(),
|
|
2701
|
+
yield mode.encode(), payload, id
|
|
2729
2702
|
logger.debug(
|
|
2730
2703
|
"Streamed run event",
|
|
2731
2704
|
run_id=str(run_id),
|
|
2732
2705
|
stream_mode=mode,
|
|
2733
2706
|
message_id=id,
|
|
2734
|
-
data=
|
|
2707
|
+
data=payload,
|
|
2735
2708
|
)
|
|
2736
2709
|
except TimeoutError:
|
|
2737
2710
|
# Check if the run is still pending
|
|
@@ -2794,18 +2767,13 @@ class Runs(Authenticated):
|
|
|
2794
2767
|
resumable: bool = False,
|
|
2795
2768
|
) -> None:
|
|
2796
2769
|
"""Publish a message to all subscribers of the run stream."""
|
|
2797
|
-
from langgraph_api.
|
|
2770
|
+
from langgraph_api.utils.stream_codec import STREAM_CODEC
|
|
2798
2771
|
|
|
2799
2772
|
topic = f"run:{run_id}:stream".encode()
|
|
2800
2773
|
|
|
2801
2774
|
stream_manager = get_stream_manager()
|
|
2802
|
-
# Send to all queues subscribed to this run_id
|
|
2803
|
-
payload =
|
|
2804
|
-
{
|
|
2805
|
-
"event": event,
|
|
2806
|
-
"message": message,
|
|
2807
|
-
}
|
|
2808
|
-
)
|
|
2775
|
+
# Send to all queues subscribed to this run_id using protocol frame
|
|
2776
|
+
payload = STREAM_CODEC.encode(event, message)
|
|
2809
2777
|
await stream_manager.put(
|
|
2810
2778
|
run_id, thread_id, Message(topic=topic, data=payload), resumable
|
|
2811
2779
|
)
|
{langgraph_runtime_inmem-0.13.0.dist-info → langgraph_runtime_inmem-0.14.0.dist-info}/RECORD
RENAMED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
langgraph_runtime_inmem/__init__.py,sha256=
|
|
1
|
+
langgraph_runtime_inmem/__init__.py,sha256=csu7K0Iyy69kpS21MCa9q3MkfeJLSBXmsT02eK_hGXc,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
|
-
langgraph_runtime_inmem/inmem_stream.py,sha256=
|
|
4
|
+
langgraph_runtime_inmem/inmem_stream.py,sha256=PFLWbsxU8RqbT5mYJgNk6v5q6TWJRIY1hkZWhJF8nkI,9094
|
|
5
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=
|
|
7
|
+
langgraph_runtime_inmem/ops.py,sha256=63uV88PijGnNxzgWGL_SljeXIeHd8dAwowBrWi9X4Xo,107645
|
|
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
|
-
langgraph_runtime_inmem-0.
|
|
13
|
-
langgraph_runtime_inmem-0.
|
|
11
|
+
langgraph_runtime_inmem-0.14.0.dist-info/METADATA,sha256=jegaYI5exlmydXtt4oxMbgFBCIrKaV7HawwHKNr2MrU,566
|
|
12
|
+
langgraph_runtime_inmem-0.14.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
13
|
+
langgraph_runtime_inmem-0.14.0.dist-info/RECORD,,
|
|
File without changes
|