langgraph-runtime-inmem 0.21.0__tar.gz → 0.22.0__tar.gz

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 (17) hide show
  1. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/PKG-INFO +1 -1
  2. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/langgraph_runtime_inmem/__init__.py +3 -1
  3. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/langgraph_runtime_inmem/checkpoint.py +26 -3
  4. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/langgraph_runtime_inmem/ops.py +4 -0
  5. langgraph_runtime_inmem-0.22.0/langgraph_runtime_inmem/routes.py +39 -0
  6. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/.gitignore +0 -0
  7. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/Makefile +0 -0
  8. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/README.md +0 -0
  9. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/langgraph_runtime_inmem/database.py +0 -0
  10. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/langgraph_runtime_inmem/inmem_stream.py +0 -0
  11. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/langgraph_runtime_inmem/lifespan.py +0 -0
  12. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/langgraph_runtime_inmem/metrics.py +0 -0
  13. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/langgraph_runtime_inmem/queue.py +0 -0
  14. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/langgraph_runtime_inmem/retry.py +0 -0
  15. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/langgraph_runtime_inmem/store.py +0 -0
  16. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/pyproject.toml +0 -0
  17. {langgraph_runtime_inmem-0.21.0 → langgraph_runtime_inmem-0.22.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-runtime-inmem
3
- Version: 0.21.0
3
+ Version: 0.22.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
@@ -6,10 +6,11 @@ from langgraph_runtime_inmem import (
6
6
  ops,
7
7
  queue,
8
8
  retry,
9
+ routes,
9
10
  store,
10
11
  )
11
12
 
12
- __version__ = "0.21.0"
13
+ __version__ = "0.22.0"
13
14
  __all__ = [
14
15
  "ops",
15
16
  "database",
@@ -19,5 +20,6 @@ __all__ = [
19
20
  "store",
20
21
  "queue",
21
22
  "metrics",
23
+ "routes",
22
24
  "__version__",
23
25
  ]
@@ -21,6 +21,17 @@ if typing.TYPE_CHECKING:
21
21
  logger = logging.getLogger(__name__)
22
22
 
23
23
  _EXCLUDED_KEYS = {"checkpoint_ns", "checkpoint_id", "run_id", "thread_id"}
24
+
25
+ # Configurable keys that are transient (per-request) and should not be persisted in checkpoints
26
+ _TRANSIENT_CONFIGURABLE_KEYS = frozenset(
27
+ {
28
+ "langgraph_request_id",
29
+ "langgraph_auth_user",
30
+ "langgraph_auth_user_id",
31
+ "langgraph_auth_permissions",
32
+ }
33
+ )
34
+
24
35
  DISABLE_FILE_PERSISTENCE = (
25
36
  os.getenv("LANGGRAPH_DISABLE_FILE_PERSISTENCE", "false").lower() == "true"
26
37
  )
@@ -84,14 +95,26 @@ class InMemorySaver(MemorySaver):
84
95
  new_versions: dict[str, str | int | float],
85
96
  ) -> RunnableConfig:
86
97
  # TODO: Should this be done in OSS as well?
98
+ # Filter out transient fields that are request-scoped, not checkpoint-scoped
99
+ config_metadata = config.get("metadata", {})
87
100
  metadata = {
88
101
  **{
89
102
  k: v
90
103
  for k, v in config["configurable"].items()
91
- if not k.startswith("__") and k not in _EXCLUDED_KEYS
104
+ if not k.startswith("__")
105
+ and k not in _EXCLUDED_KEYS
106
+ and k not in _TRANSIENT_CONFIGURABLE_KEYS
107
+ },
108
+ **{
109
+ k: v
110
+ for k, v in config_metadata.items()
111
+ if k not in _TRANSIENT_CONFIGURABLE_KEYS
112
+ },
113
+ **{
114
+ k: v
115
+ for k, v in metadata.items()
116
+ if k not in _TRANSIENT_CONFIGURABLE_KEYS
92
117
  },
93
- **config.get("metadata", {}),
94
- **metadata,
95
118
  }
96
119
  if not isinstance(checkpoint["id"], uuid.UUID):
97
120
  # Avoid type inconsistencies
@@ -1437,6 +1437,7 @@ class Threads(Authenticated):
1437
1437
  thread_config,
1438
1438
  checkpointer=checkpointer,
1439
1439
  store=(await get_store()),
1440
+ is_for_execution=False,
1440
1441
  ) as graph:
1441
1442
  result = await graph.aget_state(config, subgraphs=subgraphs)
1442
1443
  if (
@@ -1532,6 +1533,7 @@ class Threads(Authenticated):
1532
1533
  thread_config,
1533
1534
  checkpointer=checkpointer,
1534
1535
  store=(await get_store()),
1536
+ is_for_execution=False,
1535
1537
  ) as graph:
1536
1538
  update_config = config.copy()
1537
1539
  update_config["configurable"] = {
@@ -1634,6 +1636,7 @@ class Threads(Authenticated):
1634
1636
  thread_config,
1635
1637
  checkpointer=Checkpointer(),
1636
1638
  store=(await get_store()),
1639
+ is_for_execution=False,
1637
1640
  ) as graph:
1638
1641
  next_config = await graph.abulk_update_state(
1639
1642
  config,
@@ -1734,6 +1737,7 @@ class Threads(Authenticated):
1734
1737
  Checkpointer, conn, unpack_hook=_msgpack_ext_hook_to_json
1735
1738
  ),
1736
1739
  store=(await get_store()),
1740
+ is_for_execution=False,
1737
1741
  ) as graph:
1738
1742
  # Convert before parameter if it's a string
1739
1743
  before_param = (
@@ -0,0 +1,39 @@
1
+ """Internal routes for inmem runtime (testing/debugging only)."""
2
+
3
+ import asyncio
4
+
5
+ from langgraph_runtime_inmem.database import connect
6
+
7
+
8
+ def get_internal_routes():
9
+ from langgraph_api.config import MIGRATIONS_PATH
10
+
11
+ if "__inmem" not in MIGRATIONS_PATH:
12
+ # not in a testing mode.
13
+ return []
14
+ from langgraph_api.route import ApiRequest, ApiResponse, ApiRoute
15
+
16
+ async def truncate(request: ApiRequest):
17
+ """Truncate all inmem data (for testing)."""
18
+ from langgraph_runtime.checkpoint import Checkpointer
19
+
20
+ await asyncio.to_thread(Checkpointer().clear)
21
+ async with connect() as conn:
22
+ await asyncio.to_thread(conn.clear)
23
+ return ApiResponse({"ok": True})
24
+
25
+ async def debug_get_raw_thread(request: ApiRequest):
26
+ """Return raw thread from store without decryption (for testing)."""
27
+ thread_id = request.path_params["thread_id"]
28
+ async with connect() as conn:
29
+ for thread in conn.store["threads"]:
30
+ if str(thread["thread_id"]) == thread_id:
31
+ return ApiResponse(thread)
32
+ return ApiResponse({"error": "not found"}, status_code=404)
33
+
34
+ return [
35
+ ApiRoute("/internal/truncate", truncate, methods=["POST"]),
36
+ ApiRoute(
37
+ "/internal/debug/thread/{thread_id}", debug_get_raw_thread, methods=["GET"]
38
+ ),
39
+ ]