langgraph-runtime-inmem 0.6.12__py3-none-any.whl → 0.6.13__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/ops.py +72 -29
- langgraph_runtime_inmem/queue.py +1 -2
- {langgraph_runtime_inmem-0.6.12.dist-info → langgraph_runtime_inmem-0.6.13.dist-info}/METADATA +1 -1
- {langgraph_runtime_inmem-0.6.12.dist-info → langgraph_runtime_inmem-0.6.13.dist-info}/RECORD +6 -6
- {langgraph_runtime_inmem-0.6.12.dist-info → langgraph_runtime_inmem-0.6.13.dist-info}/WHEEL +0 -0
langgraph_runtime_inmem/ops.py
CHANGED
|
@@ -1001,6 +1001,7 @@ class Threads(Authenticated):
|
|
|
1001
1001
|
thread_id: UUID,
|
|
1002
1002
|
run_id: UUID,
|
|
1003
1003
|
run_status: RunStatus | Literal["rollback"],
|
|
1004
|
+
graph_id: str,
|
|
1004
1005
|
checkpoint: CheckpointPayload | None = None,
|
|
1005
1006
|
exception: BaseException | None = None,
|
|
1006
1007
|
) -> None:
|
|
@@ -1080,6 +1081,7 @@ class Threads(Authenticated):
|
|
|
1080
1081
|
final_thread_status = "busy"
|
|
1081
1082
|
else:
|
|
1082
1083
|
final_thread_status = base_thread_status
|
|
1084
|
+
thread["metadata"]["graph_id"] = graph_id
|
|
1083
1085
|
thread.update(
|
|
1084
1086
|
{
|
|
1085
1087
|
"updated_at": now,
|
|
@@ -1273,7 +1275,15 @@ class Threads(Authenticated):
|
|
|
1273
1275
|
metadata = thread.get("metadata", {})
|
|
1274
1276
|
thread_config = thread.get("config", {})
|
|
1275
1277
|
|
|
1276
|
-
|
|
1278
|
+
# Fallback to graph_id from run if not in thread metadata
|
|
1279
|
+
graph_id = metadata.get("graph_id")
|
|
1280
|
+
if not graph_id:
|
|
1281
|
+
for run in conn.store["runs"]:
|
|
1282
|
+
if run["thread_id"] == thread_id:
|
|
1283
|
+
graph_id = run["kwargs"]["config"]["configurable"]["graph_id"]
|
|
1284
|
+
break
|
|
1285
|
+
|
|
1286
|
+
if graph_id:
|
|
1277
1287
|
# format latest checkpoint for response
|
|
1278
1288
|
checkpointer.latest_iter = checkpoint
|
|
1279
1289
|
async with get_graph(
|
|
@@ -1351,7 +1361,15 @@ class Threads(Authenticated):
|
|
|
1351
1361
|
detail=f"Thread {thread_id} has in-flight runs: {pending_runs}",
|
|
1352
1362
|
)
|
|
1353
1363
|
|
|
1354
|
-
|
|
1364
|
+
# Fallback to graph_id from run if not in thread metadata
|
|
1365
|
+
graph_id = metadata.get("graph_id")
|
|
1366
|
+
if not graph_id:
|
|
1367
|
+
for run in conn.store["runs"]:
|
|
1368
|
+
if run["thread_id"] == thread_id:
|
|
1369
|
+
graph_id = run["kwargs"]["config"]["configurable"]["graph_id"]
|
|
1370
|
+
break
|
|
1371
|
+
|
|
1372
|
+
if graph_id:
|
|
1355
1373
|
config["configurable"].setdefault("graph_id", graph_id)
|
|
1356
1374
|
|
|
1357
1375
|
checkpointer.latest_iter = checkpoint
|
|
@@ -1389,7 +1407,11 @@ class Threads(Authenticated):
|
|
|
1389
1407
|
checkpoint_id=next_config["configurable"]["checkpoint_id"],
|
|
1390
1408
|
)
|
|
1391
1409
|
else:
|
|
1392
|
-
raise HTTPException(
|
|
1410
|
+
raise HTTPException(
|
|
1411
|
+
status_code=400,
|
|
1412
|
+
detail=f"Thread '{thread['thread_id']}' has no assigned graph ID. This usually occurs when no runs have been made on this particular thread."
|
|
1413
|
+
" This operation requires a graph ID. Please ensure a run has been made for the thread or manually update the thread metadata (by setting the 'graph_id' field) before running this operation.",
|
|
1414
|
+
)
|
|
1393
1415
|
|
|
1394
1416
|
@staticmethod
|
|
1395
1417
|
async def bulk(
|
|
@@ -1471,7 +1493,11 @@ class Threads(Authenticated):
|
|
|
1471
1493
|
checkpoint=next_config["configurable"],
|
|
1472
1494
|
)
|
|
1473
1495
|
else:
|
|
1474
|
-
raise HTTPException(
|
|
1496
|
+
raise HTTPException(
|
|
1497
|
+
status_code=400,
|
|
1498
|
+
detail=f"Thread '{thread['thread_id']}' has no assigned graph ID. This usually occurs when no runs have been made on this particular thread."
|
|
1499
|
+
" This operation requires a graph ID. Please ensure a run has been made for the thread or manually update the thread metadata (by setting the 'graph_id' field) before running this operation.",
|
|
1500
|
+
)
|
|
1475
1501
|
|
|
1476
1502
|
@staticmethod
|
|
1477
1503
|
async def list(
|
|
@@ -1678,9 +1704,9 @@ class Runs(Authenticated):
|
|
|
1678
1704
|
await stream_manager.remove_control_queue(run_id, queue)
|
|
1679
1705
|
|
|
1680
1706
|
@staticmethod
|
|
1681
|
-
async def sweep(
|
|
1707
|
+
async def sweep() -> None:
|
|
1682
1708
|
"""Sweep runs that are no longer running"""
|
|
1683
|
-
|
|
1709
|
+
pass
|
|
1684
1710
|
|
|
1685
1711
|
@staticmethod
|
|
1686
1712
|
def _merge_jsonb(*objects: dict) -> dict:
|
|
@@ -1714,6 +1740,7 @@ class Runs(Authenticated):
|
|
|
1714
1740
|
ctx: Auth.types.BaseAuthContext | None = None,
|
|
1715
1741
|
) -> AsyncIterator[Run]:
|
|
1716
1742
|
"""Create a run."""
|
|
1743
|
+
from langgraph_api.config import FF_RICH_THREADS
|
|
1717
1744
|
from langgraph_api.schema import Run, Thread
|
|
1718
1745
|
|
|
1719
1746
|
assistant_id = _ensure_uuid(assistant_id)
|
|
@@ -1759,34 +1786,50 @@ class Runs(Authenticated):
|
|
|
1759
1786
|
# Create new thread
|
|
1760
1787
|
if thread_id is None:
|
|
1761
1788
|
thread_id = uuid4()
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
config=Runs._merge_jsonb(
|
|
1772
|
-
assistant["config"],
|
|
1773
|
-
config,
|
|
1774
|
-
{
|
|
1775
|
-
"configurable": Runs._merge_jsonb(
|
|
1776
|
-
Runs._get_configurable(assistant["config"]),
|
|
1777
|
-
Runs._get_configurable(config),
|
|
1778
|
-
)
|
|
1789
|
+
if FF_RICH_THREADS:
|
|
1790
|
+
thread = Thread(
|
|
1791
|
+
thread_id=thread_id,
|
|
1792
|
+
status="busy",
|
|
1793
|
+
metadata={
|
|
1794
|
+
"graph_id": assistant["graph_id"],
|
|
1795
|
+
"assistant_id": str(assistant_id),
|
|
1796
|
+
**(config.get("metadata") or {}),
|
|
1797
|
+
**metadata,
|
|
1779
1798
|
},
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1799
|
+
config=Runs._merge_jsonb(
|
|
1800
|
+
assistant["config"],
|
|
1801
|
+
config,
|
|
1802
|
+
{
|
|
1803
|
+
"configurable": Runs._merge_jsonb(
|
|
1804
|
+
Runs._get_configurable(assistant["config"]),
|
|
1805
|
+
Runs._get_configurable(config),
|
|
1806
|
+
)
|
|
1807
|
+
},
|
|
1808
|
+
),
|
|
1809
|
+
created_at=datetime.now(UTC),
|
|
1810
|
+
updated_at=datetime.now(UTC),
|
|
1811
|
+
values=b"",
|
|
1812
|
+
)
|
|
1813
|
+
else:
|
|
1814
|
+
thread = Thread(
|
|
1815
|
+
thread_id=thread_id,
|
|
1816
|
+
status="idle",
|
|
1817
|
+
metadata={
|
|
1818
|
+
"graph_id": assistant["graph_id"],
|
|
1819
|
+
"assistant_id": str(assistant_id),
|
|
1820
|
+
**(config.get("metadata") or {}),
|
|
1821
|
+
**metadata,
|
|
1822
|
+
},
|
|
1823
|
+
config={},
|
|
1824
|
+
created_at=datetime.now(UTC),
|
|
1825
|
+
updated_at=datetime.now(UTC),
|
|
1826
|
+
values=b"",
|
|
1827
|
+
)
|
|
1785
1828
|
await logger.ainfo("Creating thread", thread_id=thread_id)
|
|
1786
1829
|
conn.store["threads"].append(thread)
|
|
1787
1830
|
elif existing_thread:
|
|
1788
1831
|
# Update existing thread
|
|
1789
|
-
if existing_thread["status"] != "busy":
|
|
1832
|
+
if FF_RICH_THREADS and existing_thread["status"] != "busy":
|
|
1790
1833
|
existing_thread["status"] = "busy"
|
|
1791
1834
|
existing_thread["metadata"] = Runs._merge_jsonb(
|
|
1792
1835
|
existing_thread["metadata"],
|
langgraph_runtime_inmem/queue.py
CHANGED
|
@@ -128,8 +128,7 @@ async def queue():
|
|
|
128
128
|
# sweep runs if needed
|
|
129
129
|
if do_sweep:
|
|
130
130
|
last_sweep_secs = loop.time()
|
|
131
|
-
|
|
132
|
-
logger.info("Swept runs", run_ids=run_ids)
|
|
131
|
+
await ops.Runs.sweep()
|
|
133
132
|
except Exception as exc:
|
|
134
133
|
# keep trying to run the scheduler indefinitely
|
|
135
134
|
logger.exception("Background worker scheduler failed", exc_info=exc)
|
{langgraph_runtime_inmem-0.6.12.dist-info → langgraph_runtime_inmem-0.6.13.dist-info}/RECORD
RENAMED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
langgraph_runtime_inmem/__init__.py,sha256=
|
|
1
|
+
langgraph_runtime_inmem/__init__.py,sha256=mPj20Y7jJEr9XATlg7oD3Q0F4BJdwWnfN7JMijIiRHc,311
|
|
2
2
|
langgraph_runtime_inmem/checkpoint.py,sha256=nc1G8DqVdIu-ibjKTqXfbPfMbAsKjPObKqegrSzo6Po,4432
|
|
3
3
|
langgraph_runtime_inmem/database.py,sha256=G_6L2khpRDSpS2Vs_SujzHayODcwG5V2IhFP7LLBXgw,6349
|
|
4
4
|
langgraph_runtime_inmem/inmem_stream.py,sha256=UWk1srLF44HZPPbRdArGGhsy0MY0UOJKSIxBSO7Hosc,5138
|
|
5
5
|
langgraph_runtime_inmem/lifespan.py,sha256=t0w2MX2dGxe8yNtSX97Z-d2pFpllSLS4s1rh2GJDw5M,3557
|
|
6
6
|
langgraph_runtime_inmem/metrics.py,sha256=HhO0RC2bMDTDyGBNvnd2ooLebLA8P1u5oq978Kp_nAA,392
|
|
7
|
-
langgraph_runtime_inmem/ops.py,sha256=
|
|
8
|
-
langgraph_runtime_inmem/queue.py,sha256=
|
|
7
|
+
langgraph_runtime_inmem/ops.py,sha256=ffxYACydXPmWKt89AY22M1j8s75JbFMtzXI1SKC3R50,93949
|
|
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.6.
|
|
12
|
-
langgraph_runtime_inmem-0.6.
|
|
13
|
-
langgraph_runtime_inmem-0.6.
|
|
11
|
+
langgraph_runtime_inmem-0.6.13.dist-info/METADATA,sha256=GUxT1ClUkx_1b0nR-tiuetNRDfSoB5iejMXS2ieX9HA,566
|
|
12
|
+
langgraph_runtime_inmem-0.6.13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
13
|
+
langgraph_runtime_inmem-0.6.13.dist-info/RECORD,,
|
|
File without changes
|