langgraph-api 0.1.2__tar.gz → 0.1.4__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.

Potentially problematic release.


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

Files changed (102) hide show
  1. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/PKG-INFO +1 -1
  2. langgraph_api-0.1.4/langgraph_api/__init__.py +1 -0
  3. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/api/__init__.py +3 -1
  4. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/auth/middleware.py +1 -2
  5. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/cli.py +5 -0
  6. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/config.py +10 -4
  7. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/package.json +3 -3
  8. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/api.test.mts +3 -3
  9. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/yarn.lock +13 -20
  10. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/metadata.py +6 -0
  11. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/serde.py +1 -1
  12. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/server.py +38 -0
  13. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/validation.py +2 -2
  14. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/pyproject.toml +2 -1
  15. langgraph_api-0.1.2/langgraph_api/__init__.py +0 -1
  16. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/LICENSE +0 -0
  17. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/README.md +0 -0
  18. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/api/assistants.py +0 -0
  19. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/api/mcp.py +0 -0
  20. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/api/meta.py +0 -0
  21. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/api/openapi.py +0 -0
  22. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/api/runs.py +0 -0
  23. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/api/store.py +0 -0
  24. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/api/threads.py +0 -0
  25. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/api/ui.py +0 -0
  26. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/asyncio.py +0 -0
  27. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/auth/__init__.py +0 -0
  28. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/auth/custom.py +0 -0
  29. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/auth/langsmith/__init__.py +0 -0
  30. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/auth/langsmith/backend.py +0 -0
  31. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/auth/langsmith/client.py +0 -0
  32. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/auth/noop.py +0 -0
  33. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/auth/studio_user.py +0 -0
  34. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/command.py +0 -0
  35. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/cron_scheduler.py +0 -0
  36. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/errors.py +0 -0
  37. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/graph.py +0 -0
  38. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/http.py +0 -0
  39. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/.gitignore +0 -0
  40. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/__init__.py +0 -0
  41. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/base.py +0 -0
  42. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/build.mts +0 -0
  43. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/client.mts +0 -0
  44. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/errors.py +0 -0
  45. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/global.d.ts +0 -0
  46. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/remote.py +0 -0
  47. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/schema.py +0 -0
  48. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/src/graph.mts +0 -0
  49. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/src/hooks.mjs +0 -0
  50. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/src/parser/parser.mts +0 -0
  51. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/src/parser/parser.worker.mjs +0 -0
  52. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/src/schema/types.mts +0 -0
  53. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/src/schema/types.template.mts +0 -0
  54. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/src/utils/files.mts +0 -0
  55. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/src/utils/importMap.mts +0 -0
  56. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
  57. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/src/utils/serde.mts +0 -0
  58. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/sse.py +0 -0
  59. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/auth.test.mts +0 -0
  60. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/compose-postgres.auth.yml +0 -0
  61. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/compose-postgres.yml +0 -0
  62. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/.gitignore +0 -0
  63. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/agent.css +0 -0
  64. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/agent.mts +0 -0
  65. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/agent.ui.tsx +0 -0
  66. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/agent_simple.mts +0 -0
  67. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/auth.mts +0 -0
  68. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/command.mts +0 -0
  69. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/delay.mts +0 -0
  70. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/dynamic.mts +0 -0
  71. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/error.mts +0 -0
  72. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/langgraph.json +0 -0
  73. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/nested.mts +0 -0
  74. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/package.json +0 -0
  75. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/weather.mts +0 -0
  76. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/graphs/yarn.lock +0 -0
  77. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/parser.test.mts +0 -0
  78. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/tests/utils.mts +0 -0
  79. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/js/ui.py +0 -0
  80. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/logging.py +0 -0
  81. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/middleware/__init__.py +0 -0
  82. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/middleware/http_logger.py +0 -0
  83. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/middleware/private_network.py +0 -0
  84. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/models/__init__.py +0 -0
  85. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/models/run.py +0 -0
  86. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/patch.py +0 -0
  87. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/queue_entrypoint.py +0 -0
  88. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/route.py +0 -0
  89. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/schema.py +0 -0
  90. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/sse.py +0 -0
  91. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/state.py +0 -0
  92. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/stream.py +0 -0
  93. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/thread_ttl.py +0 -0
  94. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/utils.py +0 -0
  95. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/webhook.py +0 -0
  96. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_api/worker.py +0 -0
  97. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_license/__init__.py +0 -0
  98. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_license/middleware.py +0 -0
  99. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_license/validation.py +0 -0
  100. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/langgraph_runtime/__init__.py +0 -0
  101. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/logging.json +0 -0
  102. {langgraph_api-0.1.2 → langgraph_api-0.1.4}/openapi.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: langgraph-api
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary:
5
5
  License: Elastic-2.0
6
6
  Author: Nuno Campos
@@ -0,0 +1 @@
1
+ __version__ = "0.1.4"
@@ -43,7 +43,9 @@ async def openapi(request: Request):
43
43
 
44
44
 
45
45
  async def docs(request: Request):
46
- return HTMLResponse(DOCS_HTML)
46
+ from langgraph_api.config import MOUNT_PREFIX
47
+
48
+ return HTMLResponse(DOCS_HTML.format(mount_prefix=MOUNT_PREFIX or ""))
47
49
 
48
50
 
49
51
  meta_routes: list[BaseRoute] = [
@@ -36,7 +36,7 @@ def on_error(conn: HTTPConnection, exc: AuthenticationError):
36
36
 
37
37
  class ConditionalAuthenticationMiddleware(AuthenticationMiddleware):
38
38
  async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
39
- if scope["root_path"] == "/noauth":
39
+ if (root_path := scope.get("root_path")) and root_path.startswith("/noauth"):
40
40
  # disable auth for requests originating from SDK ASGI transport
41
41
  # root_path cannot be set from a request, so safe to use as auth bypass
42
42
  await self.app(scope, receive, send)
@@ -46,7 +46,6 @@ class ConditionalAuthenticationMiddleware(AuthenticationMiddleware):
46
46
  # disable auth for UI asset requests
47
47
  await self.app(scope, receive, send)
48
48
  return
49
-
50
49
  return await super().__call__(scope, receive, send)
51
50
 
52
51
 
@@ -148,6 +148,9 @@ def run_server(
148
148
  start_time = time.time()
149
149
 
150
150
  env_vars = env if isinstance(env, Mapping) else None
151
+ mount_prefix = None
152
+ if http:
153
+ mount_prefix = http.get("mount_prefix")
151
154
  if isinstance(env, str | pathlib.Path):
152
155
  try:
153
156
  from dotenv.main import DotEnv
@@ -184,6 +187,8 @@ def run_server(
184
187
  logger.info("Debugger attached. Starting server...")
185
188
 
186
189
  local_url = f"http://{host}:{port}"
190
+ if mount_prefix:
191
+ local_url += mount_prefix
187
192
  to_patch = dict(
188
193
  MIGRATIONS_PATH="__inmem",
189
194
  DATABASE_URI=":memory:",
@@ -37,6 +37,8 @@ class HttpConfig(TypedDict, total=False):
37
37
  """Disable /ui routes"""
38
38
  disable_mcp: bool
39
39
  """Disable /mcp routes"""
40
+ mount_prefix: str
41
+ """Prefix for mounted routes. E.g., "/my-deployment/api"."""
40
42
 
41
43
 
42
44
  class ThreadTTLConfig(TypedDict, total=False):
@@ -169,11 +171,15 @@ HTTP_CONFIG: HttpConfig | None = env("LANGGRAPH_HTTP", cast=_parse_json, default
169
171
  STORE_CONFIG: StoreConfig | None = env(
170
172
  "LANGGRAPH_STORE", cast=_parse_json, default=None
171
173
  )
174
+
175
+ MOUNT_PREFIX: str | None = env("MOUNT_PREFIX", cast=str, default=None) or (
176
+ HTTP_CONFIG.get("mount_prefix") if HTTP_CONFIG else None
177
+ )
178
+
172
179
  CORS_ALLOW_ORIGINS = env("CORS_ALLOW_ORIGINS", cast=CommaSeparatedStrings, default="*")
173
- if HTTP_CONFIG and HTTP_CONFIG.get("cors"):
174
- CORS_CONFIG = HTTP_CONFIG["cors"]
175
- else:
176
- CORS_CONFIG: CorsConfig | None = env("CORS_CONFIG", cast=_parse_json, default=None)
180
+ CORS_CONFIG: CorsConfig | None = env("CORS_CONFIG", cast=_parse_json, default=None) or (
181
+ HTTP_CONFIG.get("cors") if HTTP_CONFIG else None
182
+ )
177
183
  """
178
184
  {
179
185
  "type": "object",
@@ -9,9 +9,9 @@
9
9
  "dependencies": {
10
10
  "@hono/node-server": "^1.12.0",
11
11
  "@hono/zod-validator": "^0.2.2",
12
- "@langchain/core": "^0.3.40",
13
- "@langchain/langgraph": "^0.2.49",
14
- "@langchain/langgraph-checkpoint": "^0.0.15",
12
+ "@langchain/core": "^0.3.44",
13
+ "@langchain/langgraph": "^0.2.64",
14
+ "@langchain/langgraph-checkpoint": "^0.0.17",
15
15
  "@types/json-schema": "^7.0.15",
16
16
  "@typescript/vfs": "^1.6.0",
17
17
  "dedent": "^1.5.3",
@@ -821,7 +821,7 @@ describe("runs", () => {
821
821
  },
822
822
  );
823
823
 
824
- it.concurrent("human in the loop - modification", async () => {
824
+ it.concurrent("human in the loop - modification", {retry: 3}, async () => {
825
825
  // (2) interrupt, modify the message and then continue running
826
826
  const assistant = await client.assistants.create({ graphId: "agent" });
827
827
  const thread = await client.threads.create();
@@ -1204,7 +1204,7 @@ describe("subgraphs", () => {
1204
1204
  });
1205
1205
 
1206
1206
  // (1) interrupt and then continue running, no modification
1207
- it.concurrent("human in the loop - no modification", async () => {
1207
+ it.concurrent("human in the loop - no modification", {retry: 3}, async () => {
1208
1208
  const assistant = await client.assistants.create({ graphId: "weather" });
1209
1209
  const thread = await client.threads.create();
1210
1210
 
@@ -1491,7 +1491,7 @@ describe("subgraphs", () => {
1491
1491
  });
1492
1492
 
1493
1493
  // (2) interrupt, modify the message and then continue running
1494
- it.concurrent("human in the loop - modification", async () => {
1494
+ it.concurrent("human in the loop - modification", {retry: 3}, async () => {
1495
1495
  const assistant = await client.assistants.create({ graphId: "weather" });
1496
1496
  const thread = await client.threads.create();
1497
1497
  const input = {
@@ -185,10 +185,10 @@
185
185
  resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
186
186
  integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
187
187
 
188
- "@langchain/core@^0.3.40":
189
- version "0.3.42"
190
- resolved "https://registry.yarnpkg.com/@langchain/core/-/core-0.3.42.tgz#f1fa38425626d8efe9fe2ee51d36c91506632363"
191
- integrity sha512-pT/jC5lqWK3YGDq8dQwgKoa6anqAhMtG1x5JbnrOj9NdaLeBbCKBDQ+/Ykzk3nZ8o+0UMsaXNZo7IVL83VVjHg==
188
+ "@langchain/core@^0.3.44":
189
+ version "0.3.44"
190
+ resolved "https://registry.yarnpkg.com/@langchain/core/-/core-0.3.44.tgz#b449646ab31d0cefd3e9fa3ec02a0fb6a78f7ef6"
191
+ integrity sha512-3BsSFf7STvPPZyl2kMANgtVnCUvDdyP4k+koP+nY2Tczd5V+RFkuazIn/JOj/xxy/neZjr4PxFU4BFyF1aKXOA==
192
192
  dependencies:
193
193
  "@cfworker/json-schema" "^4.0.2"
194
194
  ansi-styles "^5.0.0"
@@ -228,17 +228,10 @@
228
228
  winston-console-format "^1.0.8"
229
229
  zod "^3.23.8"
230
230
 
231
- "@langchain/langgraph-checkpoint@^0.0.15":
232
- version "0.0.15"
233
- resolved "https://registry.yarnpkg.com/@langchain/langgraph-checkpoint/-/langgraph-checkpoint-0.0.15.tgz#90aaf1782f5ada4efd4d38444ba92aaae0a1988c"
234
- integrity sha512-AiJkvsYHqNbCh1Tx823qs2lf2qRqeB4EAMejirOk8gkpPszAGYua5c3niKYkcKR2tU8Snhrmj7Gm9HKZSFOXyw==
235
- dependencies:
236
- uuid "^10.0.0"
237
-
238
- "@langchain/langgraph-checkpoint@~0.0.16":
239
- version "0.0.16"
240
- resolved "https://registry.yarnpkg.com/@langchain/langgraph-checkpoint/-/langgraph-checkpoint-0.0.16.tgz#e996f31d5da8ce67b2a9bf3dc64c4c0e05f01d72"
241
- integrity sha512-B50l7w9o9353drHsdsD01vhQrCJw0eqvYeXid7oKeoj1Yye+qY90r97xuhiflaYCZHM5VEo2oaizs8oknerZsQ==
231
+ "@langchain/langgraph-checkpoint@^0.0.17", "@langchain/langgraph-checkpoint@~0.0.17":
232
+ version "0.0.17"
233
+ resolved "https://registry.yarnpkg.com/@langchain/langgraph-checkpoint/-/langgraph-checkpoint-0.0.17.tgz#d0a8824eb0769567da54262adebe65db4ee6d58f"
234
+ integrity sha512-6b3CuVVYx+7x0uWLG+7YXz9j2iBa+tn2AXvkLxzEvaAsLE6Sij++8PPbS2BZzC+S/FPJdWsz6I5bsrqL0BYrCA==
242
235
  dependencies:
243
236
  uuid "^10.0.0"
244
237
 
@@ -263,12 +256,12 @@
263
256
  esbuild-plugin-tailwindcss "^2.0.1"
264
257
  zod "^3.23.8"
265
258
 
266
- "@langchain/langgraph@^0.2.49":
267
- version "0.2.54"
268
- resolved "https://registry.yarnpkg.com/@langchain/langgraph/-/langgraph-0.2.54.tgz#f57a9b471808c122ee5ae4506ed05cc75f1578bd"
269
- integrity sha512-+P2rU0Qz6bBCNPXOSV8WeUpLRTvhu8fQuzMYR2MqWsbbfmZrfmLxqtVWPHkmr5khx/txxFy1vOBAy+KwZ94mrg==
259
+ "@langchain/langgraph@^0.2.64":
260
+ version "0.2.64"
261
+ resolved "https://registry.yarnpkg.com/@langchain/langgraph/-/langgraph-0.2.64.tgz#90f8c32bc34fbc3f7c1b04595f1e5165dd5a5fb4"
262
+ integrity sha512-M6lh8ekDoZVCLdA10jeqIsU58LODDzXpP38aeXil5A5pg31IJp5L8O4yBfbp8mRobVX+Bbga5R5ZRyQBQl6NTg==
270
263
  dependencies:
271
- "@langchain/langgraph-checkpoint" "~0.0.16"
264
+ "@langchain/langgraph-checkpoint" "~0.0.17"
272
265
  "@langchain/langgraph-sdk" "~0.0.32"
273
266
  uuid "^10.0.0"
274
267
  zod "^3.23.8"
@@ -70,6 +70,12 @@ async def metadata_loop() -> None:
70
70
  if not LANGGRAPH_CLOUD_LICENSE_KEY and not LANGSMITH_API_KEY:
71
71
  return
72
72
 
73
+ if LANGGRAPH_CLOUD_LICENSE_KEY and not LANGGRAPH_CLOUD_LICENSE_KEY.startswith(
74
+ "lcl_"
75
+ ):
76
+ logger.info("Running in air-gapped mode, skipping metadata loop")
77
+ return
78
+
73
79
  logger.info("Starting metadata loop")
74
80
 
75
81
  global RUN_COUNTER, NODE_COUNTER, FROM_TIMESTAMP
@@ -104,7 +104,7 @@ _option = orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_NON_STR_KEYS
104
104
 
105
105
  def json_dumpb(obj) -> bytes:
106
106
  return orjson.dumps(obj, default=default, option=_option).replace(
107
- b"\u0000", b""
107
+ rb"\u0000", b""
108
108
  ) # null unicode char not allowed in json
109
109
 
110
110
 
@@ -5,6 +5,7 @@ import sys
5
5
  # WARNING: Keep the import above before other code runs as it
6
6
  # patches an error in the Starlette library.
7
7
  import logging
8
+ import typing
8
9
 
9
10
  import jsonschema_rs
10
11
  import structlog
@@ -13,10 +14,13 @@ from langgraph.errors import EmptyInputError, InvalidUpdateError
13
14
  from starlette.applications import Starlette
14
15
  from starlette.middleware import Middleware
15
16
  from starlette.middleware.cors import CORSMiddleware
17
+
16
18
  from langgraph_api.api.openapi import set_custom_spec
19
+ from starlette.types import Receive, Scope, Send
17
20
 
18
21
  import langgraph_api.config as config
19
22
  from langgraph_api.api import routes, meta_routes, user_router
23
+ from starlette.routing import Mount
20
24
  from langgraph_api.errors import (
21
25
  overloaded_error_handler,
22
26
  validation_error_handler,
@@ -149,3 +153,37 @@ else:
149
153
  middleware=middleware,
150
154
  exception_handlers=exception_handlers,
151
155
  )
156
+
157
+ if config.MOUNT_PREFIX:
158
+ prefix = config.MOUNT_PREFIX
159
+ if not prefix.startswith("/") or prefix.endswith("/"):
160
+ raise ValueError(
161
+ f"Invalid mount_prefix '{prefix}': Must start with '/' and must not end with '/'. "
162
+ f"Valid examples: '/my-api', '/v1', '/api/v1'.\nInvalid examples: 'api/', '/api/'"
163
+ )
164
+ logger.info(f"Mounting routes at prefix: {prefix}")
165
+ plen = len(prefix)
166
+ rplen = len(prefix.encode("utf-8"))
167
+
168
+ class ASGIBypassMiddleware:
169
+ def __init__(self, app: typing.Any, **kwargs):
170
+ self.app = app
171
+
172
+ async def __call__(
173
+ self, scope: Scope, receive: Receive, send: Send
174
+ ) -> typing.Any:
175
+ if (root_path := scope.get("root_path")) and root_path == "/noauth":
176
+ # The SDK initialized with None is trying to connect via
177
+ # ASGITransport. Ensure that it has the correct subpath prefixes
178
+ # so the regular router can handle it.
179
+ scope["path"] = f'/noauth{prefix}{scope["path"]}'
180
+ scope["raw_path"] = scope["path"].encode("utf-8")
181
+
182
+ return await self.app(scope, receive, send)
183
+
184
+ app = Starlette(
185
+ routes=[Mount(prefix, app=app)],
186
+ lifespan=app.router.lifespan_context,
187
+ middleware=[Middleware(ASGIBypassMiddleware)] + app.user_middleware,
188
+ exception_handlers=app.exception_handlers,
189
+ )
@@ -143,9 +143,9 @@ DOCS_HTML = """<!doctype html>
143
143
  content="width=device-width, initial-scale=1" />
144
144
  </head>
145
145
  <body>
146
- <script id="api-reference" data-url="/openapi.json"></script>
146
+ <script id="api-reference" data-url="{mount_prefix}/openapi.json"></script>
147
147
  <script>
148
- var configuration = {}
148
+ var configuration = {{}}
149
149
  document.getElementById('api-reference').dataset.configuration =
150
150
  JSON.stringify(configuration)
151
151
  </script>
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "langgraph-api"
3
- version = "0.1.2"
3
+ version = "0.1.4"
4
4
  description = ""
5
5
  authors = [
6
6
  "Nuno Campos <nuno@langchain.dev>",
@@ -65,6 +65,7 @@ fastapi = "^0.115.8"
65
65
  langgraph = ">=0.3.17"
66
66
  pycryptodome = "^3.22.0"
67
67
  langgraph-runtime-inmem = { path = "../runtime_inmem", develop = true, python = ">=3.11,<4.0" }
68
+ blockbuster = "^1.5.24"
68
69
 
69
70
  [tool.poetry_bumpversion.file."langgraph_api/__init__.py"]
70
71
  search = '__version__ = "{current_version}"'
@@ -1 +0,0 @@
1
- __version__ = "0.1.1"
File without changes
File without changes