langgraph-api 0.4.26__py3-none-any.whl → 0.4.28__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 +1 -1
- langgraph_api/api/a2a.py +22 -2
- langgraph_api/cli.py +2 -0
- langgraph_api/config.py +2 -2
- langgraph_api/queue_entrypoint.py +40 -22
- {langgraph_api-0.4.26.dist-info → langgraph_api-0.4.28.dist-info}/METADATA +1 -1
- {langgraph_api-0.4.26.dist-info → langgraph_api-0.4.28.dist-info}/RECORD +10 -10
- {langgraph_api-0.4.26.dist-info → langgraph_api-0.4.28.dist-info}/WHEEL +0 -0
- {langgraph_api-0.4.26.dist-info → langgraph_api-0.4.28.dist-info}/entry_points.txt +0 -0
- {langgraph_api-0.4.26.dist-info → langgraph_api-0.4.28.dist-info}/licenses/LICENSE +0 -0
langgraph_api/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.4.
|
|
1
|
+
__version__ = "0.4.28"
|
langgraph_api/api/a2a.py
CHANGED
|
@@ -674,12 +674,12 @@ async def handle_post_request(request: ApiRequest, assistant_id: str) -> Respons
|
|
|
674
674
|
|
|
675
675
|
accept_header = request.headers.get("Accept") or ""
|
|
676
676
|
if method == "message/stream":
|
|
677
|
-
if "text/event-stream"
|
|
677
|
+
if not _accepts_media_type(accept_header, "text/event-stream"):
|
|
678
678
|
return create_error_response(
|
|
679
679
|
"Accept header must include text/event-stream for streaming", 400
|
|
680
680
|
)
|
|
681
681
|
else:
|
|
682
|
-
if "application/json"
|
|
682
|
+
if not _accepts_media_type(accept_header, "application/json"):
|
|
683
683
|
return create_error_response(
|
|
684
684
|
"Accept header must include application/json", 400
|
|
685
685
|
)
|
|
@@ -720,6 +720,26 @@ def create_error_response(message: str, status_code: int) -> Response:
|
|
|
720
720
|
)
|
|
721
721
|
|
|
722
722
|
|
|
723
|
+
def _accepts_media_type(accept_header: str, media_type: str) -> bool:
|
|
724
|
+
"""Return True if the Accept header allows the provided media type."""
|
|
725
|
+
if not accept_header:
|
|
726
|
+
return False
|
|
727
|
+
|
|
728
|
+
target = media_type.lower()
|
|
729
|
+
for media_range in accept_header.split(","):
|
|
730
|
+
value = media_range.strip().lower()
|
|
731
|
+
if not value:
|
|
732
|
+
continue
|
|
733
|
+
candidate = value.split(";", 1)[0].strip()
|
|
734
|
+
if candidate == "*/*" or candidate == target:
|
|
735
|
+
return True
|
|
736
|
+
if candidate.endswith("/*"):
|
|
737
|
+
type_prefix = candidate.split("/", 1)[0]
|
|
738
|
+
if target.startswith(f"{type_prefix}/"):
|
|
739
|
+
return True
|
|
740
|
+
return False
|
|
741
|
+
|
|
742
|
+
|
|
723
743
|
# ============================================================================
|
|
724
744
|
# JSON-RPC Message Handlers
|
|
725
745
|
# ============================================================================
|
langgraph_api/cli.py
CHANGED
|
@@ -165,6 +165,8 @@ def run_server(
|
|
|
165
165
|
mount_prefix = None
|
|
166
166
|
if http is not None and http.get("mount_prefix") is not None:
|
|
167
167
|
mount_prefix = http.get("mount_prefix")
|
|
168
|
+
if os.environ.get("MOUNT_PREFIX"):
|
|
169
|
+
mount_prefix = os.environ.get("MOUNT_PREFIX")
|
|
168
170
|
if os.environ.get("LANGGRAPH_MOUNT_PREFIX"):
|
|
169
171
|
mount_prefix = os.environ.get("LANGGRAPH_MOUNT_PREFIX")
|
|
170
172
|
if isinstance(env, str | pathlib.Path):
|
langgraph_api/config.py
CHANGED
|
@@ -179,8 +179,6 @@ REDIS_URI = env("REDIS_URI", cast=str)
|
|
|
179
179
|
REDIS_CLUSTER = env("REDIS_CLUSTER", cast=bool, default=False)
|
|
180
180
|
REDIS_MAX_CONNECTIONS = env("REDIS_MAX_CONNECTIONS", cast=int, default=2000)
|
|
181
181
|
REDIS_CONNECT_TIMEOUT = env("REDIS_CONNECT_TIMEOUT", cast=float, default=10.0)
|
|
182
|
-
REDIS_MAX_IDLE_TIME = env("REDIS_MAX_IDLE_TIME", cast=float, default=120.0)
|
|
183
|
-
REDIS_STREAM_TIMEOUT = env("REDIS_STREAM_TIMEOUT", cast=float, default=30.0)
|
|
184
182
|
REDIS_KEY_PREFIX = env("REDIS_KEY_PREFIX", cast=str, default="")
|
|
185
183
|
RUN_STATS_CACHE_SECONDS = env("RUN_STATS_CACHE_SECONDS", cast=int, default=60)
|
|
186
184
|
|
|
@@ -290,8 +288,10 @@ if THREAD_TTL is None and CHECKPOINTER_CONFIG is not None:
|
|
|
290
288
|
|
|
291
289
|
N_JOBS_PER_WORKER = env("N_JOBS_PER_WORKER", cast=int, default=10)
|
|
292
290
|
BG_JOB_TIMEOUT_SECS = env("BG_JOB_TIMEOUT_SECS", cast=float, default=3600)
|
|
291
|
+
|
|
293
292
|
FF_CRONS_ENABLED = env("FF_CRONS_ENABLED", cast=bool, default=True)
|
|
294
293
|
FF_RICH_THREADS = env("FF_RICH_THREADS", cast=bool, default=True)
|
|
294
|
+
FF_LOG_DROPPED_EVENTS = env("FF_LOG_DROPPED_EVENTS", cast=bool, default=False)
|
|
295
295
|
|
|
296
296
|
# auth
|
|
297
297
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# ruff: noqa: E402
|
|
2
2
|
import os
|
|
3
3
|
|
|
4
|
+
from langgraph_api.api.meta import METRICS_FORMATS
|
|
5
|
+
|
|
4
6
|
if not (
|
|
5
7
|
(disable_truststore := os.getenv("DISABLE_TRUSTSTORE"))
|
|
6
8
|
and disable_truststore.lower() == "true"
|
|
@@ -30,6 +32,7 @@ logger = structlog.stdlib.get_logger(__name__)
|
|
|
30
32
|
async def health_and_metrics_server():
|
|
31
33
|
import uvicorn
|
|
32
34
|
from starlette.applications import Starlette
|
|
35
|
+
from starlette.requests import Request
|
|
33
36
|
from starlette.responses import JSONResponse, PlainTextResponse
|
|
34
37
|
from starlette.routing import Route
|
|
35
38
|
|
|
@@ -38,7 +41,14 @@ async def health_and_metrics_server():
|
|
|
38
41
|
async def health_endpoint(request):
|
|
39
42
|
return JSONResponse({"status": "ok"})
|
|
40
43
|
|
|
41
|
-
async def metrics_endpoint(request):
|
|
44
|
+
async def metrics_endpoint(request: Request):
|
|
45
|
+
metrics_format = request.query_params.get("format", "prometheus")
|
|
46
|
+
if metrics_format not in METRICS_FORMATS:
|
|
47
|
+
await logger.awarning(
|
|
48
|
+
f"metrics format {metrics_format} not supported, falling back to prometheus"
|
|
49
|
+
)
|
|
50
|
+
metrics_format = "prometheus"
|
|
51
|
+
|
|
42
52
|
metrics = get_metrics()
|
|
43
53
|
worker_metrics = cast(dict[str, int], metrics["workers"])
|
|
44
54
|
workers_max = worker_metrics["max"]
|
|
@@ -48,29 +58,37 @@ async def health_and_metrics_server():
|
|
|
48
58
|
project_id = os.getenv("LANGSMITH_HOST_PROJECT_ID")
|
|
49
59
|
revision_id = os.getenv("LANGSMITH_HOST_REVISION_ID")
|
|
50
60
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"# HELP lg_api_workers_active The number of currently active workers.",
|
|
56
|
-
"# TYPE lg_api_workers_active gauge",
|
|
57
|
-
f'lg_api_workers_active{{project_id="{project_id}", revision_id="{revision_id}"}} {workers_active}',
|
|
58
|
-
"# HELP lg_api_workers_available The number of available (idle) workers.",
|
|
59
|
-
"# TYPE lg_api_workers_available gauge",
|
|
60
|
-
f'lg_api_workers_available{{project_id="{project_id}", revision_id="{revision_id}"}} {workers_available}',
|
|
61
|
-
]
|
|
62
|
-
|
|
63
|
-
metrics_lines.extend(
|
|
64
|
-
pool_stats(
|
|
65
|
-
project_id=project_id,
|
|
66
|
-
revision_id=revision_id,
|
|
67
|
-
)
|
|
61
|
+
pg_redis_stats = pool_stats(
|
|
62
|
+
project_id=project_id,
|
|
63
|
+
revision_id=revision_id,
|
|
64
|
+
format=metrics_format,
|
|
68
65
|
)
|
|
69
66
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
if metrics_format == "json":
|
|
68
|
+
resp = {
|
|
69
|
+
**pg_redis_stats,
|
|
70
|
+
"workers": worker_metrics,
|
|
71
|
+
}
|
|
72
|
+
return JSONResponse(resp)
|
|
73
|
+
elif metrics_format == "prometheus":
|
|
74
|
+
metrics_lines = [
|
|
75
|
+
"# HELP lg_api_workers_max The maximum number of workers available.",
|
|
76
|
+
"# TYPE lg_api_workers_max gauge",
|
|
77
|
+
f'lg_api_workers_max{{project_id="{project_id}", revision_id="{revision_id}"}} {workers_max}',
|
|
78
|
+
"# HELP lg_api_workers_active The number of currently active workers.",
|
|
79
|
+
"# TYPE lg_api_workers_active gauge",
|
|
80
|
+
f'lg_api_workers_active{{project_id="{project_id}", revision_id="{revision_id}"}} {workers_active}',
|
|
81
|
+
"# HELP lg_api_workers_available The number of available (idle) workers.",
|
|
82
|
+
"# TYPE lg_api_workers_available gauge",
|
|
83
|
+
f'lg_api_workers_available{{project_id="{project_id}", revision_id="{revision_id}"}} {workers_available}',
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
metrics_lines.extend(pg_redis_stats)
|
|
87
|
+
|
|
88
|
+
return PlainTextResponse(
|
|
89
|
+
"\n".join(metrics_lines),
|
|
90
|
+
media_type="text/plain; version=0.0.4; charset=utf-8",
|
|
91
|
+
)
|
|
74
92
|
|
|
75
93
|
app = Starlette(
|
|
76
94
|
routes=[
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
langgraph_api/__init__.py,sha256=
|
|
1
|
+
langgraph_api/__init__.py,sha256=QZ0p7EqvqxpClz_YH3XtlxgPmyXKcK-CGg_B_p5Z7w0,23
|
|
2
2
|
langgraph_api/asgi_transport.py,sha256=XtiLOu4WWsd-xizagBLzT5xUkxc9ZG9YqwvETBPjBFE,5161
|
|
3
3
|
langgraph_api/asyncio.py,sha256=FEEkLm_N-15cbElo4vQ309MkDKBZuRqAYV8VJ1DocNw,9860
|
|
4
|
-
langgraph_api/cli.py,sha256=
|
|
4
|
+
langgraph_api/cli.py,sha256=o_zD2vkky06dzW87HQgkIR1_h3ZCSZ8tgNvFCK9rKVo,19669
|
|
5
5
|
langgraph_api/command.py,sha256=Bh-rvuTLwdHCqFWryCjB1M8oWxPBwRBUjMNj_04KPxM,852
|
|
6
|
-
langgraph_api/config.py,sha256=
|
|
6
|
+
langgraph_api/config.py,sha256=eS0lIOMx-UhqEw9zDXcz3W5aOLX7laqxZUQcasuXoAs,12168
|
|
7
7
|
langgraph_api/cron_scheduler.py,sha256=25wYzEQrhPEivZrAPYOmzLPDOQa-aFogU37mTXc9TJk,2566
|
|
8
8
|
langgraph_api/errors.py,sha256=zlnl3xXIwVG0oGNKKpXf1an9Rn_SBDHSyhe53hU6aLw,1858
|
|
9
9
|
langgraph_api/executor_entrypoint.py,sha256=CaX813ygtf9CpOaBkfkQXJAHjFtmlScCkrOvTDmu4Aw,750
|
|
@@ -14,7 +14,7 @@ langgraph_api/http_metrics.py,sha256=MU9ccXt7aBb0AJ2SWEjwtbtbJEWmeqSdx7-CI51e32o
|
|
|
14
14
|
langgraph_api/logging.py,sha256=qB6q_cUba31edE4_D6dBGhdiUTpW7sXAOepUjYb_R50,5216
|
|
15
15
|
langgraph_api/metadata.py,sha256=0eGYhXOW6UIVDj2Y5mOdSJz_RadgJG8xmUsC9WqwsiE,8342
|
|
16
16
|
langgraph_api/patch.py,sha256=J0MmcfpZG15SUVaVcI0Z4x_c0-0rbbT7Pwh9fDAQOpA,1566
|
|
17
|
-
langgraph_api/queue_entrypoint.py,sha256=
|
|
17
|
+
langgraph_api/queue_entrypoint.py,sha256=k-Lz-HdaM2ICJacf9yCQw21GlJp00dPoHKuhe1PSrSs,6418
|
|
18
18
|
langgraph_api/route.py,sha256=EBhELuJ1He-ZYcAnR5YTImcIeDtWthDae5CHELBxPkM,5056
|
|
19
19
|
langgraph_api/schema.py,sha256=AsgF0dIjBvDd_PDy20mGqB_IkBLgVvSj8qRKG_lPlec,8440
|
|
20
20
|
langgraph_api/serde.py,sha256=Jkww6ixP5o2YZmnXtM7ihuAYC6YSuNDNPvE-8ILoqVo,5499
|
|
@@ -29,7 +29,7 @@ langgraph_api/validation.py,sha256=86jftgOsMa7tkeshBw6imYe7zyUXPoVuf5Voh6dFiR8,5
|
|
|
29
29
|
langgraph_api/webhook.py,sha256=SvSM1rdnNtiH4q3JQYmAqJUk2Sable5xAcwOLuRhtlo,1723
|
|
30
30
|
langgraph_api/worker.py,sha256=FQRw3kL9ynDv_LNgY_OjjPZQBuAvSQpsW6nECnABvDg,15354
|
|
31
31
|
langgraph_api/api/__init__.py,sha256=raFkYH50tsO-KjRmDbGVoHCuxuH58u1lrZbr-MlITIY,6262
|
|
32
|
-
langgraph_api/api/a2a.py,sha256=
|
|
32
|
+
langgraph_api/api/a2a.py,sha256=HIHZkLnIcM1u1FJti-L2NH-h1I9BZ_d-QW9z3gFonn8,53995
|
|
33
33
|
langgraph_api/api/assistants.py,sha256=OX83GCWwGR8MuEJKIzAPEC4LC3Aghs5vD3NGLNnijaU,17268
|
|
34
34
|
langgraph_api/api/mcp.py,sha256=qe10ZRMN3f-Hli-9TI8nbQyWvMeBb72YB1PZVbyqBQw,14418
|
|
35
35
|
langgraph_api/api/meta.py,sha256=Qyj6r5czkVJ81tpD6liFY7tlrmFDsiSfBr-4X8HJpRc,4834
|
|
@@ -99,8 +99,8 @@ langgraph_runtime/store.py,sha256=7mowndlsIroGHv3NpTSOZDJR0lCuaYMBoTnTrewjslw,11
|
|
|
99
99
|
LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
|
|
100
100
|
logging.json,sha256=3RNjSADZmDq38eHePMm1CbP6qZ71AmpBtLwCmKU9Zgo,379
|
|
101
101
|
openapi.json,sha256=21wu-NxdxyTQwZctNcEfRkLMnSBi0QhGAfwq5kg8XNU,172618
|
|
102
|
-
langgraph_api-0.4.
|
|
103
|
-
langgraph_api-0.4.
|
|
104
|
-
langgraph_api-0.4.
|
|
105
|
-
langgraph_api-0.4.
|
|
106
|
-
langgraph_api-0.4.
|
|
102
|
+
langgraph_api-0.4.28.dist-info/METADATA,sha256=qTje00tzH8lBtQcOUOFLqvnoB8siS_uFb7bUVdNzzmk,3893
|
|
103
|
+
langgraph_api-0.4.28.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
104
|
+
langgraph_api-0.4.28.dist-info/entry_points.txt,sha256=hGedv8n7cgi41PypMfinwS_HfCwA7xJIfS0jAp8htV8,78
|
|
105
|
+
langgraph_api-0.4.28.dist-info/licenses/LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
|
|
106
|
+
langgraph_api-0.4.28.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|