langgraph-api 0.0.47__py3-none-any.whl → 0.1.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.

Potentially problematic release.


This version of langgraph-api might be problematic. Click here for more details.

langgraph_api/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.0.47"
1
+ __version__ = "0.1.0"
@@ -21,7 +21,7 @@ from langgraph_api.auth.middleware import auth_middleware
21
21
  from langgraph_api.config import HTTP_CONFIG, MIGRATIONS_PATH
22
22
  from langgraph_api.graph import js_bg_tasks
23
23
  from langgraph_api.validation import DOCS_HTML
24
- from langgraph_storage.database import connect, healthcheck
24
+ from langgraph_runtime.database import connect, healthcheck
25
25
 
26
26
  logger = structlog.stdlib.get_logger(__name__)
27
27
 
@@ -138,7 +138,7 @@ else:
138
138
  if "inmem" in MIGRATIONS_PATH:
139
139
 
140
140
  async def truncate(request: Request):
141
- from langgraph_storage.checkpoint import Checkpointer
141
+ from langgraph_runtime.checkpoint import Checkpointer
142
142
 
143
143
  await asyncio.to_thread(Checkpointer().clear)
144
144
  async with connect() as conn:
@@ -21,9 +21,9 @@ from langgraph_api.validation import (
21
21
  AssistantVersionChange,
22
22
  AssistantVersionsSearchRequest,
23
23
  )
24
- from langgraph_storage.database import connect
25
- from langgraph_storage.ops import Assistants
26
- from langgraph_storage.retry import retry_db
24
+ from langgraph_runtime.database import connect
25
+ from langgraph_runtime.ops import Assistants
26
+ from langgraph_runtime.retry import retry_db
27
27
 
28
28
  logger = structlog.stdlib.get_logger(__name__)
29
29
 
langgraph_api/api/meta.py CHANGED
@@ -5,9 +5,9 @@ from starlette.responses import JSONResponse, PlainTextResponse
5
5
  from langgraph_api import config
6
6
  from langgraph_api.route import ApiRequest
7
7
  from langgraph_license.validation import plus_features_enabled
8
- from langgraph_storage.database import connect, pool_stats
9
- from langgraph_storage.ops import Runs
10
- from langgraph_storage.queue import WORKERS
8
+ from langgraph_runtime.database import connect, pool_stats
9
+ from langgraph_runtime.metrics import get_metrics
10
+ from langgraph_runtime.ops import Runs
11
11
 
12
12
  METRICS_FORMATS = {"prometheus", "json"}
13
13
 
@@ -32,20 +32,18 @@ async def meta_metrics(request: ApiRequest):
32
32
  format = "prometheus"
33
33
 
34
34
  # collect stats
35
- workers_max = config.N_JOBS_PER_WORKER
36
- workers_active = len(WORKERS)
37
- workers_available = workers_max - workers_active
35
+ metrics = get_metrics()
36
+ worker_metrics = metrics["workers"]
37
+ workers_max = worker_metrics["max"]
38
+ workers_active = worker_metrics["active"]
39
+ workers_available = worker_metrics["available"]
38
40
 
39
41
  if format == "json":
40
42
  async with connect() as conn:
41
43
  return JSONResponse(
42
44
  {
43
45
  **pool_stats(),
44
- "workers": {
45
- "max": workers_max,
46
- "active": workers_active,
47
- "available": workers_available,
48
- },
46
+ "workers": worker_metrics,
49
47
  "queue": await Runs.stats(conn),
50
48
  }
51
49
  )
langgraph_api/api/runs.py CHANGED
@@ -22,9 +22,9 @@ from langgraph_api.validation import (
22
22
  RunsCancel,
23
23
  )
24
24
  from langgraph_license.validation import plus_features_enabled
25
- from langgraph_storage.database import connect
26
- from langgraph_storage.ops import Crons, Runs, Threads
27
- from langgraph_storage.retry import retry_db
25
+ from langgraph_runtime.database import connect
26
+ from langgraph_runtime.ops import Crons, Runs, Threads
27
+ from langgraph_runtime.retry import retry_db
28
28
 
29
29
 
30
30
  @retry_db
@@ -13,8 +13,8 @@ from langgraph_api.validation import (
13
13
  StorePutRequest,
14
14
  StoreSearchRequest,
15
15
  )
16
- from langgraph_storage.retry import retry_db
17
- from langgraph_storage.store import Store
16
+ from langgraph_runtime.retry import retry_db
17
+ from langgraph_runtime.store import Store
18
18
 
19
19
 
20
20
  def _validate_namespace(namespace: tuple[str, ...]) -> Response | None:
@@ -15,9 +15,9 @@ from langgraph_api.validation import (
15
15
  ThreadStateSearch,
16
16
  ThreadStateUpdate,
17
17
  )
18
- from langgraph_storage.database import connect
19
- from langgraph_storage.ops import Threads
20
- from langgraph_storage.retry import retry_db
18
+ from langgraph_runtime.database import connect
19
+ from langgraph_runtime.ops import Threads
20
+ from langgraph_runtime.retry import retry_db
21
21
 
22
22
 
23
23
  @retry_db
langgraph_api/cli.py CHANGED
@@ -6,6 +6,7 @@ import pathlib
6
6
  import threading
7
7
  import typing
8
8
  from collections.abc import Mapping, Sequence
9
+ from typing import Literal
9
10
 
10
11
  from typing_extensions import TypedDict
11
12
 
@@ -134,6 +135,7 @@ def run_server(
134
135
  studio_url: str | None = None,
135
136
  disable_persistence: bool = False,
136
137
  allow_blocking: bool = False,
138
+ runtime_edition: Literal["inmem", "community", "postgres"] = "inmem",
137
139
  **kwargs: typing.Any,
138
140
  ):
139
141
  """Run the LangGraph API server."""
@@ -197,6 +199,7 @@ def run_server(
197
199
  LANGGRAPH_UI_BUNDLER="true",
198
200
  LANGGRAPH_API_URL=local_url,
199
201
  LANGGRAPH_DISABLE_FILE_PERSISTENCE=str(disable_persistence).lower(),
202
+ LANGGRAPH_RUNTIME_EDITION=runtime_edition,
200
203
  # If true, we will not raise on blocking IO calls (via blockbuster)
201
204
  LANGGRAPH_ALLOW_BLOCKING=str(allow_blocking).lower(),
202
205
  # See https://developer.chrome.com/blog/private-network-access-update-2024-03
@@ -274,7 +277,6 @@ For production use, please use LangGraph Cloud.
274
277
 
275
278
  """
276
279
  logger.info(welcome)
277
-
278
280
  if open_browser:
279
281
  threading.Thread(target=_open_browser, daemon=True).start()
280
282
  supported_kwargs = {
langgraph_api/config.py CHANGED
@@ -323,6 +323,9 @@ USES_INDEXING = (
323
323
  and STORE_CONFIG.get("index").get("embed")
324
324
  )
325
325
  USES_CUSTOM_APP = HTTP_CONFIG and HTTP_CONFIG.get("app")
326
+ USES_CUSTOM_AUTH = bool(LANGGRAPH_AUTH)
327
+ USES_THREAD_TTL = bool(THREAD_TTL)
328
+ USES_STORE_TTL = bool(STORE_CONFIG and STORE_CONFIG.get("ttl"))
326
329
 
327
330
  API_VARIANT = env("LANGSMITH_LANGGRAPH_API_VARIANT", cast=str, default="")
328
331
 
@@ -7,9 +7,9 @@ from langchain_core.runnables.config import run_in_executor
7
7
  from langgraph_api.models.run import create_valid_run
8
8
  from langgraph_api.utils import next_cron_date
9
9
  from langgraph_api.worker import set_auth_ctx_for_run
10
- from langgraph_storage.database import connect
11
- from langgraph_storage.ops import Crons
12
- from langgraph_storage.retry import retry_db
10
+ from langgraph_runtime.database import connect
11
+ from langgraph_runtime.ops import Crons
12
+ from langgraph_runtime.retry import retry_db
13
13
 
14
14
  logger = structlog.stdlib.get_logger(__name__)
15
15
 
langgraph_api/graph.py CHANGED
@@ -50,8 +50,8 @@ async def register_graph(
50
50
  description: str | None = None,
51
51
  ) -> None:
52
52
  """Register a graph."""
53
- from langgraph_storage.database import connect
54
- from langgraph_storage.ops import Assistants
53
+ from langgraph_runtime.database import connect
54
+ from langgraph_runtime.ops import Assistants
55
55
 
56
56
  await logger.ainfo(f"Registering graph with id '{graph_id}'", graph_id=graph_id)
57
57
  GRAPHS[graph_id] = graph
@@ -365,7 +365,7 @@ async def run_js_process(paths_str: str, watch: bool = False):
365
365
 
366
366
 
367
367
  def _get_passthrough_checkpointer(conn: AsyncConnectionProto):
368
- from langgraph_storage.checkpoint import Checkpointer
368
+ from langgraph_runtime.checkpoint import Checkpointer
369
369
 
370
370
  class PassthroughSerialiser(SerializerProtocol):
371
371
  def dumps(self, obj: Any) -> bytes:
@@ -393,7 +393,7 @@ def _get_passthrough_checkpointer(conn: AsyncConnectionProto):
393
393
 
394
394
 
395
395
  def _get_passthrough_store():
396
- from langgraph_storage.store import Store
396
+ from langgraph_runtime.store import Store
397
397
 
398
398
  return Store()
399
399
 
@@ -401,7 +401,7 @@ def _get_passthrough_store():
401
401
  # Setup a HTTP server on top of CHECKPOINTER_SOCKET unix socket
402
402
  # used by `client.mts` to communicate with the Python checkpointer
403
403
  async def run_remote_checkpointer():
404
- from langgraph_storage.database import connect
404
+ from langgraph_runtime.database import connect
405
405
 
406
406
  async def checkpointer_list(payload: dict):
407
407
  """Search checkpoints"""
langgraph_api/metadata.py CHANGED
@@ -11,7 +11,10 @@ from langgraph_api.config import (
11
11
  LANGSMITH_API_KEY,
12
12
  LANGSMITH_AUTH_ENDPOINT,
13
13
  USES_CUSTOM_APP,
14
+ USES_CUSTOM_AUTH,
14
15
  USES_INDEXING,
16
+ USES_STORE_TTL,
17
+ USES_THREAD_TTL,
15
18
  )
16
19
  from langgraph_api.http import http_request
17
20
  from langgraph_license.validation import plus_features_enabled
@@ -95,8 +98,12 @@ async def metadata_loop() -> None:
95
98
  "langgraph.platform.variant": VARIANT,
96
99
  "langgraph.platform.host": HOST,
97
100
  "langgraph.platform.plan": PLAN,
101
+ # user app features
98
102
  "user_app.uses_indexing": USES_INDEXING,
99
103
  "user_app.uses_custom_app": USES_CUSTOM_APP,
104
+ "user_app.uses_custom_auth": USES_CUSTOM_AUTH,
105
+ "user_app.uses_thread_ttl": USES_THREAD_TTL,
106
+ "user_app.uses_store_ttl": USES_STORE_TTL,
100
107
  },
101
108
  "measures": {
102
109
  "langgraph.platform.runs": runs,
@@ -5,7 +5,6 @@ import structlog
5
5
  from starlette.requests import ClientDisconnect
6
6
  from starlette.types import Message, Receive, Scope, Send
7
7
 
8
- from langgraph_api.asyncio import create_task
9
8
  from langgraph_api.logging import LOG_JSON
10
9
 
11
10
  asgi = structlog.stdlib.get_logger("asgi")
@@ -21,6 +20,12 @@ class AccessLoggerMiddleware:
21
20
  ) -> None:
22
21
  self.app = app
23
22
  self.logger = logger
23
+ if hasattr(logger, "isEnabledFor"):
24
+ self.debug_enabled = self.logger.isEnabledFor(logging.DEBUG)
25
+ elif hasattr(logger, "is_enabled_for"):
26
+ self.debug_enabled = self.logger.is_enabled_for(logging.DEBUG)
27
+ else:
28
+ self.debug_enabled = False
24
29
 
25
30
  async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
26
31
  if scope["type"] != "http" or (LOG_JSON and scope.get("path") in PATHS_IGNORE):
@@ -29,7 +34,7 @@ class AccessLoggerMiddleware:
29
34
  loop = asyncio.get_event_loop()
30
35
  info = {"response": {}}
31
36
 
32
- if self.logger.isEnabledFor(logging.DEBUG):
37
+ if self.debug_enabled:
33
38
 
34
39
  async def inner_receive() -> Message:
35
40
  message = await receive()
@@ -61,20 +66,18 @@ class AccessLoggerMiddleware:
61
66
  finally:
62
67
  info["end_time"] = loop.time()
63
68
  latency = int((info["end_time"] - info["start_time"]) * 1_000)
64
- create_task(
65
- self.logger.ainfo(
66
- f"{scope.get('method')} {scope.get('path')} {info['response'].get('status')} {latency}ms",
67
- method=scope.get("method"),
68
- path=scope.get("path"),
69
- status=info["response"].get("status"),
70
- latency_ms=latency,
71
- route=scope.get("route"),
72
- path_params=scope.get("path_params"),
73
- query_string=scope.get("query_string").decode(),
74
- proto=scope.get("http_version"),
75
- req_header=_headers_to_dict(scope.get("headers")),
76
- res_header=_headers_to_dict(info["response"].get("headers")),
77
- )
69
+ self.logger.info(
70
+ f"{scope.get('method')} {scope.get('path')} {info['response'].get('status')} {latency}ms",
71
+ method=scope.get("method"),
72
+ path=scope.get("path"),
73
+ status=info["response"].get("status"),
74
+ latency_ms=latency,
75
+ route=scope.get("route"),
76
+ path_params=scope.get("path_params"),
77
+ query_string=scope.get("query_string").decode(),
78
+ proto=scope.get("http_version"),
79
+ req_header=_headers_to_dict(scope.get("headers")),
80
+ res_header=_headers_to_dict(info["response"].get("headers")),
78
81
  )
79
82
 
80
83
 
@@ -23,7 +23,7 @@ from langgraph_api.schema import (
23
23
  StreamMode,
24
24
  )
25
25
  from langgraph_api.utils import AsyncConnectionProto, get_auth_ctx
26
- from langgraph_storage.ops import Runs, logger
26
+ from langgraph_runtime.ops import Runs, logger
27
27
 
28
28
 
29
29
  class RunCreateDict(TypedDict):
@@ -177,6 +177,15 @@ async def create_valid_run(
177
177
  payload,
178
178
  run_id=run_id,
179
179
  )
180
+ if (
181
+ thread_id is None
182
+ and (command := payload.get("command"))
183
+ and command.get("resume")
184
+ ):
185
+ raise HTTPException(
186
+ status_code=400,
187
+ detail="You must provide a thread_id when resuming.",
188
+ )
180
189
  temporary = thread_id is None and payload.get("on_completion", "delete") == "delete"
181
190
  stream_mode, multitask_strategy, prevent_insert_if_inflight = assign_defaults(
182
191
  payload
@@ -8,7 +8,7 @@ import pathlib
8
8
  import structlog
9
9
  import uvloop
10
10
 
11
- from langgraph_api.lifespan import lifespan
11
+ from langgraph_runtime.lifespan import lifespan
12
12
 
13
13
  logger = structlog.stdlib.get_logger(__name__)
14
14
 
langgraph_api/server.py CHANGED
@@ -22,12 +22,12 @@ from langgraph_api.errors import (
22
22
  validation_error_handler,
23
23
  value_error_handler,
24
24
  )
25
- from langgraph_api.lifespan import lifespan
25
+ from langgraph_runtime.lifespan import lifespan
26
26
  from langgraph_api.middleware.http_logger import AccessLoggerMiddleware
27
27
  from langgraph_api.middleware.private_network import PrivateNetworkMiddleware
28
28
  from langgraph_api.utils import SchemaGenerator
29
29
  from langgraph_license.middleware import LicenseValidationMiddleware
30
- from langgraph_storage.retry import OVERLOADED_EXCEPTIONS
30
+ from langgraph_runtime.retry import OVERLOADED_EXCEPTIONS
31
31
  from langgraph_sdk.client import configure_loopback_transports
32
32
 
33
33
  logging.captureWarnings(True)
langgraph_api/stream.py CHANGED
@@ -30,9 +30,9 @@ from langgraph_api.metadata import HOST, PLAN, USER_API_URL, incr_nodes
30
30
  from langgraph_api.schema import Run, StreamMode
31
31
  from langgraph_api.serde import json_dumpb
32
32
  from langgraph_api.utils import AsyncConnectionProto
33
- from langgraph_storage.checkpoint import Checkpointer
34
- from langgraph_storage.ops import Runs
35
- from langgraph_storage.store import Store
33
+ from langgraph_runtime.checkpoint import Checkpointer
34
+ from langgraph_runtime.ops import Runs
35
+ from langgraph_runtime.store import Store
36
36
 
37
37
  logger = structlog.stdlib.get_logger(__name__)
38
38
 
@@ -5,7 +5,7 @@ import asyncio
5
5
  import structlog
6
6
 
7
7
  from langgraph_api.config import THREAD_TTL
8
- from langgraph_storage.database import connect
8
+ from langgraph_runtime.database import connect
9
9
 
10
10
  logger = structlog.stdlib.get_logger(__name__)
11
11
 
@@ -30,7 +30,7 @@ async def thread_ttl_sweep_loop():
30
30
  interval_minutes=sweep_interval_minutes,
31
31
  )
32
32
 
33
- from langgraph_storage.ops import Threads
33
+ from langgraph_runtime.ops import Threads
34
34
 
35
35
  while True:
36
36
  await asyncio.sleep(sweep_interval_minutes * 60)
langgraph_api/worker.py CHANGED
@@ -26,9 +26,9 @@ from langgraph_api.stream import (
26
26
  consume,
27
27
  )
28
28
  from langgraph_api.utils import set_auth_ctx, with_user
29
- from langgraph_storage.database import connect
30
- from langgraph_storage.ops import Runs, Threads
31
- from langgraph_storage.retry import RETRIABLE_EXCEPTIONS
29
+ from langgraph_runtime.database import connect
30
+ from langgraph_runtime.ops import Runs, Threads
31
+ from langgraph_runtime.retry import RETRIABLE_EXCEPTIONS
32
32
 
33
33
  try:
34
34
  from psycopg.errors import InFailedSqlTransaction
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: langgraph-api
3
- Version: 0.0.47
3
+ Version: 0.1.0
4
4
  Summary:
5
5
  License: Elastic-2.0
6
6
  Author: Nuno Campos
@@ -1,13 +1,13 @@
1
1
  LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
2
- langgraph_api/__init__.py,sha256=OkbXUm6WCcFd54358Y0HZk3Aq5hLc0sK6xgxJ6RmT5M,23
3
- langgraph_api/api/__init__.py,sha256=qNcg8QJydef0gM-vYJlxITMRZw-9r1vw8zqm2raqqYE,5493
4
- langgraph_api/api/assistants.py,sha256=WwaBtx1MpGn9gdJ8P9fkorJHMVrJKHt1nvtw0OCZcdw,14353
2
+ langgraph_api/__init__.py,sha256=kUR5RAFc7HCeiqdlX36dZOHkUI5wI6V_43RpEcD8b-0,22
3
+ langgraph_api/api/__init__.py,sha256=ohkuKTIYaWMAnr2pck2XAMrg4srA418VM76GQWRf5tU,5493
4
+ langgraph_api/api/assistants.py,sha256=i-nxkScUB2g8bTVGtQIp1psABXlaY1aVx9pkB_UiRH8,14353
5
5
  langgraph_api/api/mcp.py,sha256=KbR19dtFCpJEiKYj3IfepAuJij8YZVELuVp7JY_yu_o,13754
6
- langgraph_api/api/meta.py,sha256=ifJ_Ki0Qf2DYbmY6OKlqKhLGxbt55gm0lEqH1A0cJbw,2790
6
+ langgraph_api/api/meta.py,sha256=M1JHcuZGEn8E-ZpuEbNBJ6SoAwZBCcPOq0NRHMCplR8,2713
7
7
  langgraph_api/api/openapi.py,sha256=f9gfmWN2AMKNUpLCpSgZuw_aeOF9jCXPdOtFT5PaTWM,10960
8
- langgraph_api/api/runs.py,sha256=qAXfgZjjaMBfwPnlnAogvemtKZZeshNSIMQqcW20tGs,18010
9
- langgraph_api/api/store.py,sha256=XNNZFRlvgReidq9u7mg-i7pjwz21BdP9Qw3Jr5Ra9Fk,5447
10
- langgraph_api/api/threads.py,sha256=QbAy7MRupWKDUhmC6_LKU2ExJbLJ6Z-CJG2gSpcMXtc,9163
8
+ langgraph_api/api/runs.py,sha256=dhHZ3xu7V0anftqzXaOYnhVEryJpVeqzu60MFiUw4u8,18010
9
+ langgraph_api/api/store.py,sha256=G4Fm8hgFLlJUW5_ekLS_IOgCfpFy-TK9uq5r9QTOELQ,5447
10
+ langgraph_api/api/threads.py,sha256=EvKJDnZDWutKoB5KoTP40NPEqG5LJ-Iw97TLYHkhLbw,9163
11
11
  langgraph_api/api/ui.py,sha256=kdCQ-p0voxAqIFc72aqqzdPGH2v-yEBKzjRE6cUPvpU,2201
12
12
  langgraph_api/asyncio.py,sha256=h0eZ7aoDGnJpoxnHLZABVlj1jQ78UxjgiHntTmAEWek,8613
13
13
  langgraph_api/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -18,12 +18,12 @@ langgraph_api/auth/langsmith/client.py,sha256=eKchvAom7hdkUXauD8vHNceBDDUijrFgdT
18
18
  langgraph_api/auth/middleware.py,sha256=jU8aDSIZHdzCGdifejRF7ndHkSjBtqIHcBwFIuUdHEA,1875
19
19
  langgraph_api/auth/noop.py,sha256=Bk6Nf3p8D_iMVy_OyfPlyiJp_aEwzL-sHrbxoXpCbac,586
20
20
  langgraph_api/auth/studio_user.py,sha256=FzFQRROKDlA9JjtBuwyZvk6Mbwno5M9RVYjDO6FU3F8,186
21
- langgraph_api/cli.py,sha256=W8rf3v4rMwv9W-tK_9yqcc7waQezMMlpBoy64WSGLMw,12682
21
+ langgraph_api/cli.py,sha256=eVX8zGeQAoVMotib2s-QhIQWQX1JInpVMItkTTgG_dU,12833
22
22
  langgraph_api/command.py,sha256=3O9v3i0OPa96ARyJ_oJbLXkfO8rPgDhLCswgO9koTFA,768
23
- langgraph_api/config.py,sha256=OJ6_9UCkPYNpUEB17EIU1nO0zQd3_T3G1Dr-ag0J8hE,10218
24
- langgraph_api/cron_scheduler.py,sha256=9yzbbGxzNgJdIg4ZT7yu2oTwT_wRuPxD1c2sbbd52xs,2630
23
+ langgraph_api/config.py,sha256=ZxVQitVzc9Rp9_j3myjW_NcSJ463kUAMmbxmmOS-tXY,10357
24
+ langgraph_api/cron_scheduler.py,sha256=i87j4pJrcsmsqMKeKUs69gaAjrGaSM3pM3jnXdN5JDQ,2630
25
25
  langgraph_api/errors.py,sha256=Bu_i5drgNTyJcLiyrwVE_6-XrSU50BHf9TDpttki9wQ,1690
26
- langgraph_api/graph.py,sha256=v7qj60MBQKfEx_0kmw9AsPygCQsOLmrJ1MkVkt4-GiM,21086
26
+ langgraph_api/graph.py,sha256=ba3G0AiI7vyHAMLV7ol8nZnsLivcBRMGGmj9fiaO7PU,21086
27
27
  langgraph_api/http.py,sha256=gYbxxjY8aLnsXeJymcJ7G7Nj_yToOGpPYQqmZ1_ggfA,5240
28
28
  langgraph_api/js/.gitignore,sha256=l5yI6G_V6F1600I1IjiUKn87f4uYIrBAYU1MOyBBhg4,59
29
29
  langgraph_api/js/base.py,sha256=xkBp5bwRrbpMFaAMViEU-qIlnsJuu3X_G8sa1pqNZK0,227
@@ -32,7 +32,7 @@ langgraph_api/js/client.mts,sha256=GJv846jWBRL0W_Yr6XtDu3UdYjdpndQ2v6dOfAhJXi0,2
32
32
  langgraph_api/js/errors.py,sha256=Cm1TKWlUCwZReDC5AQ6SgNIVGD27Qov2xcgHyf8-GXo,361
33
33
  langgraph_api/js/global.d.ts,sha256=yDusqAyzVYhxfwqqcERUzucu2Pw9ma3-ug4DFyUvQfs,167
34
34
  langgraph_api/js/package.json,sha256=oNcWe7UIoJtqzoIVr47px6-1n8KziqwEhyi4wBpzTQ0,1266
35
- langgraph_api/js/remote.py,sha256=dDrxJhe9Nm1OQREoa811GeXHygiBHTtHjvEVglOGfto,24808
35
+ langgraph_api/js/remote.py,sha256=-f3o85b7bBWhcbgdO4fLmRBdqG_lAN56d9WWcTlEBGo,24808
36
36
  langgraph_api/js/schema.py,sha256=7idnv7URlYUdSNMBXQcw7E4SxaPxCq_Oxwnlml8q5ik,408
37
37
  langgraph_api/js/src/graph.mts,sha256=otgztTNzNJpeF2IOrpNuuwbSbpAy4eFE5dHtUd7eQwU,3742
38
38
  langgraph_api/js/src/hooks.mjs,sha256=XtktgmIHlls_DsknAuwib-z7TqCm0haRoTXvnkgzMuo,601
@@ -63,43 +63,35 @@ langgraph_api/js/tests/parser.test.mts,sha256=dEC8KTqKygeb1u39ZvpPqCT4HtfPD947nL
63
63
  langgraph_api/js/tests/utils.mts,sha256=q1V9gvT63v95onlfK9W4iv3n9ZJO3h-0RD9TdDYuRyY,439
64
64
  langgraph_api/js/ui.py,sha256=XNT8iBcyT8XmbIqSQUWd-j_00HsaWB2vRTVabwFBkik,2439
65
65
  langgraph_api/js/yarn.lock,sha256=m4erGgHd30Enxdu1wKnohnzotZiEDvXh-H83qitf_W4,83812
66
- langgraph_api/lifespan.py,sha256=SfVZj0SQdsIfYwvN5s4dfxGMb7MMlGe40DghCGDFaTQ,2915
67
66
  langgraph_api/logging.py,sha256=JJIzbNIgLCN6ClQ3tA-Mm5ffuBGvpRDSZsEvnIlsuu4,3693
68
- langgraph_api/metadata.py,sha256=bAeN3NwibBuXUVPjOEbEUJMnhUXe_VdTGw508VNeav4,3655
67
+ langgraph_api/metadata.py,sha256=iM_3qaxFk1ItB4E5VaVb4n_mbqXzqZFMknVcHXnV0mI,3937
69
68
  langgraph_api/middleware/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
- langgraph_api/middleware/http_logger.py,sha256=yuFPNFIWwn-4AE1CogBfWlo8KytzywLi_Bd4ccsyVQE,3150
69
+ langgraph_api/middleware/http_logger.py,sha256=aj4mdisRobFePkD3Iy6-w_Mujwx4TQRaEhPvSd6HgLk,3284
71
70
  langgraph_api/middleware/private_network.py,sha256=eYgdyU8AzU2XJu362i1L8aSFoQRiV7_aLBPw7_EgeqI,2111
72
71
  langgraph_api/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
- langgraph_api/models/run.py,sha256=85-pyyvosFAot8WrWl2QjCje-2c4lhattYvoAEMqztA,11000
72
+ langgraph_api/models/run.py,sha256=6zl3t1_LAr5v2AIcrFSWDG5rLvqREeswXJymuGx6AT8,11258
74
73
  langgraph_api/patch.py,sha256=Dgs0PXHytekX4SUL6KsjjN0hHcOtGLvv1GRGbh6PswU,1408
75
- langgraph_api/queue_entrypoint.py,sha256=4xICUxXarNV8DhnaqAMhVi3xCmyVKCL3J5NzHxPA9Xc,1835
74
+ langgraph_api/queue_entrypoint.py,sha256=gjtajZfnDXhsi7JElfmkY-p0ENBiKBDJ4Ugiw-exapw,1839
76
75
  langgraph_api/route.py,sha256=fM4qYCGbmH0a3_cV8uKocb1sLklehxO6HhdRXqLK6OM,4421
77
76
  langgraph_api/schema.py,sha256=Frh_YOC3S1cDAMPUVanNi78ooSXK2WFpu9YkIVz5h14,5433
78
77
  langgraph_api/serde.py,sha256=D5t_HeABMYKRAsoXWaWG0IsdaYM8yOXIez2wJUTIgT8,3963
79
- langgraph_api/server.py,sha256=bnXOOYztQmqR-QVpEFoRWB5Fzd33PuEIlwBK2R7W8NE,4849
78
+ langgraph_api/server.py,sha256=Chjk-TddIVKqYqulRJb7AGYW6GZS3aU3T8ApNS7azGA,4853
80
79
  langgraph_api/sse.py,sha256=2wNodCOP2eg7a9mpSu0S3FQ0CHk2BBV_vv0UtIgJIcc,4034
81
80
  langgraph_api/state.py,sha256=8jx4IoTCOjTJuwzuXJKKFwo1VseHjNnw_CCq4x1SW14,2284
82
- langgraph_api/stream.py,sha256=lhjnom-T8GbquUZry-KSkajnqYjElaIERhPiXPtpw1E,11354
83
- langgraph_api/thread_ttl.py,sha256=QS9C7cx63KBh82_I6DqOb42-5mLTqTvneL8FJeX3aqU,1765
81
+ langgraph_api/stream.py,sha256=EdFb1ctSzkIWGws4vJMkTAtdGIWMmvNuTSQ7FBazb4I,11354
82
+ langgraph_api/thread_ttl.py,sha256=4vch4nu1UOiYcqYRd7bTHsfs0Ei_lXuy9nBQ0uVJLyo,1765
84
83
  langgraph_api/utils.py,sha256=92mSti9GfGdMRRWyESKQW5yV-75Z9icGHnIrBYvdypU,3619
85
84
  langgraph_api/validation.py,sha256=Qo3EkSRXzIRe3GRuqRWbElTcUXRMXMyA1w0VbMvdwME,4934
86
85
  langgraph_api/webhook.py,sha256=1ncwO0rIZcj-Df9sxSnFEzd1gP1bfS4okeZQS8NSRoE,1382
87
- langgraph_api/worker.py,sha256=CLmohk3B03OTsKHq_ZPhujMHFSuc694qeEL4VNSxHvg,12679
86
+ langgraph_api/worker.py,sha256=_i1cmpnjMzQtok5CzssjnR5IFxLk4dMyuPwreq8dorU,12679
88
87
  langgraph_license/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
89
88
  langgraph_license/middleware.py,sha256=_ODIYzQkymr6W9_Fp9wtf1kAQspnpsmr53xuzyF2GA0,612
90
89
  langgraph_license/validation.py,sha256=Uu_G8UGO_WTlLsBEY0gTVWjRR4czYGfw5YAD3HLZoj0,203
91
- langgraph_storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
- langgraph_storage/checkpoint.py,sha256=Qq0y6vdh27qdF3h5nOLT5CcX9Rj2bcFqkVOMeCaGoK4,4036
93
- langgraph_storage/database.py,sha256=sZjZvMcvbr_6dX0d1YrYEccVuQozIfkiWt8bdlXGVYU,5849
94
- langgraph_storage/inmem_stream.py,sha256=LjJSAxsh_E0ywqEMzdWJk8Hy_Jn9oQByzycss-fANng,3264
95
- langgraph_storage/ops.py,sha256=S2qXgfyuCr5qkKLqIV-kZNRK924bBSLZ2qdLtExfi-M,75939
96
- langgraph_storage/queue.py,sha256=IGjzCzYaGhbR9_Y37p1Hbd5uQkN9_IGzYkT_5lcPU54,7595
97
- langgraph_storage/retry.py,sha256=XmldOP4e_H5s264CagJRVnQMDFcEJR_dldVR1Hm5XvM,763
98
- langgraph_storage/store.py,sha256=JB9jZ87GE19MVN9wgl3-esgR2eIkeipws9q6qsPWkgc,3399
90
+ langgraph_runtime/__init__.py,sha256=3stEi5ECApK7l0Y7q4vN-fQQz8cgJ9lyqAyhqDBqags,1075
99
91
  logging.json,sha256=3RNjSADZmDq38eHePMm1CbP6qZ71AmpBtLwCmKU9Zgo,379
100
92
  openapi.json,sha256=YW4ND-N3adriEoNwxw7UD9endO2xUZoodCtwVIfa2dU,132261
101
- langgraph_api-0.0.47.dist-info/LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
102
- langgraph_api-0.0.47.dist-info/METADATA,sha256=IO4hwBirD3f4JqdFNa0B6V1TsB-QXhD0SlWYYRbce6Y,4165
103
- langgraph_api-0.0.47.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
104
- langgraph_api-0.0.47.dist-info/entry_points.txt,sha256=3EYLgj89DfzqJHHYGxPH4A_fEtClvlRbWRUHaXO7hj4,77
105
- langgraph_api-0.0.47.dist-info/RECORD,,
93
+ langgraph_api-0.1.0.dist-info/LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
94
+ langgraph_api-0.1.0.dist-info/METADATA,sha256=nFYl9c7QS5BKMRaRLTr1eFhOTPyVh4ouyYgbUalt_K8,4164
95
+ langgraph_api-0.1.0.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
96
+ langgraph_api-0.1.0.dist-info/entry_points.txt,sha256=3EYLgj89DfzqJHHYGxPH4A_fEtClvlRbWRUHaXO7hj4,77
97
+ langgraph_api-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,39 @@
1
+ import importlib.util
2
+ import os
3
+ import sys
4
+
5
+ import structlog
6
+
7
+ logger = structlog.stdlib.get_logger(__name__)
8
+
9
+ try:
10
+ RUNTIME_EDITION = os.environ["LANGGRAPH_RUNTIME_EDITION"]
11
+ RUNTIME_PACKAGE = f"langgraph_runtime_{RUNTIME_EDITION}"
12
+ except KeyError:
13
+ raise ValueError(
14
+ "LANGGRAPH_RUNTIME_EDITION environment variable is not set."
15
+ " Expected LANGGRAPH_RUNTIME_EDITION to be set to one of:\n"
16
+ " - inmem\n"
17
+ " - postgres\n"
18
+ " - community\n"
19
+ ) from None
20
+ if importlib.util.find_spec(RUNTIME_PACKAGE):
21
+ backend = importlib.import_module(RUNTIME_PACKAGE)
22
+ logger.info(f"Using {RUNTIME_PACKAGE}")
23
+ else:
24
+ raise ImportError(
25
+ "Langgraph runtime backend not found. Please install with "
26
+ f'`pip install "langgraph-runtime[{RUNTIME_EDITION}"`'
27
+ ) from None
28
+
29
+ # All runtime backends share the same API
30
+ for module_name in (
31
+ "checkpoint",
32
+ "database",
33
+ "lifespan",
34
+ "ops",
35
+ "retry",
36
+ "store",
37
+ "metrics",
38
+ ):
39
+ sys.modules["langgraph_runtime." + module_name] = getattr(backend, module_name)
langgraph_api/lifespan.py DELETED
@@ -1,74 +0,0 @@
1
- import asyncio
2
- from contextlib import asynccontextmanager
3
-
4
- import structlog
5
- from langchain_core.runnables.config import var_child_runnable_config
6
- from langgraph.constants import CONF, CONFIG_KEY_STORE
7
- from starlette.applications import Starlette
8
-
9
- import langgraph_api.config as config
10
- from langgraph_api.asyncio import SimpleTaskGroup, set_event_loop
11
- from langgraph_api.cron_scheduler import cron_scheduler
12
- from langgraph_api.graph import collect_graphs_from_env, stop_remote_graphs
13
- from langgraph_api.http import start_http_client, stop_http_client
14
- from langgraph_api.js.ui import start_ui_bundler, stop_ui_bundler
15
- from langgraph_api.metadata import metadata_loop
16
- from langgraph_api.thread_ttl import thread_ttl_sweep_loop
17
- from langgraph_license.validation import get_license_status, plus_features_enabled
18
- from langgraph_storage.database import start_pool, stop_pool
19
- from langgraph_storage.queue import queue
20
- from langgraph_storage.store import Store
21
-
22
- logger = structlog.stdlib.get_logger(__name__)
23
-
24
-
25
- @asynccontextmanager
26
- async def lifespan(
27
- app: Starlette | None = None,
28
- with_cron_scheduler: bool = True,
29
- taskset: set[asyncio.Task] | None = None,
30
- ):
31
- try:
32
- current_loop = asyncio.get_running_loop()
33
- set_event_loop(current_loop)
34
- except RuntimeError:
35
- await logger.aerror("Failed to set loop")
36
-
37
- if not await get_license_status():
38
- raise ValueError(
39
- "License verification failed. Please ensure proper configuration:\n"
40
- "- For local development, set a valid LANGSMITH_API_KEY for an account with LangGraph Cloud access "
41
- "in the environment defined in your langgraph.json file.\n"
42
- "- For production, configure the LANGGRAPH_CLOUD_LICENSE_KEY environment variable "
43
- "with your LangGraph Cloud license key.\n"
44
- "Review your configuration settings and try again. If issues persist, "
45
- "contact support for assistance."
46
- )
47
- await start_http_client()
48
- await start_pool()
49
- await collect_graphs_from_env(True)
50
- await start_ui_bundler()
51
- try:
52
- async with SimpleTaskGroup(
53
- cancel=True, taskset=taskset, taskgroup_name="Lifespan"
54
- ) as tg:
55
- tg.create_task(metadata_loop())
56
- if config.N_JOBS_PER_WORKER > 0:
57
- tg.create_task(queue())
58
- if (
59
- with_cron_scheduler
60
- and config.FF_CRONS_ENABLED
61
- and plus_features_enabled()
62
- ):
63
- tg.create_task(cron_scheduler())
64
- store = Store()
65
- tg.create_task(Store().start_ttl_sweeper())
66
- tg.create_task(thread_ttl_sweep_loop())
67
- var_child_runnable_config.set({CONF: {CONFIG_KEY_STORE: store}})
68
-
69
- yield
70
- finally:
71
- await stop_ui_bundler()
72
- await stop_remote_graphs()
73
- await stop_http_client()
74
- await stop_pool()
File without changes