langgraph-api 0.0.9__tar.gz → 0.0.11__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 (85) hide show
  1. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/PKG-INFO +2 -1
  2. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/auth/custom.py +48 -11
  3. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/auth/middleware.py +4 -0
  4. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/utils.py +3 -3
  5. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_storage/ops.py +1 -2
  6. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/pyproject.toml +3 -3
  7. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/LICENSE +0 -0
  8. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/README.md +0 -0
  9. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/__init__.py +0 -0
  10. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/api/__init__.py +0 -0
  11. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/api/assistants.py +0 -0
  12. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/api/meta.py +0 -0
  13. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/api/openapi.py +0 -0
  14. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/api/runs.py +0 -0
  15. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/api/store.py +0 -0
  16. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/api/threads.py +0 -0
  17. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/asyncio.py +0 -0
  18. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/auth/__init__.py +0 -0
  19. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/auth/langsmith/__init__.py +0 -0
  20. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/auth/langsmith/backend.py +0 -0
  21. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/auth/langsmith/client.py +0 -0
  22. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/auth/noop.py +0 -0
  23. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/cli.py +0 -0
  24. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/config.py +0 -0
  25. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/cron_scheduler.py +0 -0
  26. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/errors.py +0 -0
  27. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/graph.py +0 -0
  28. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/http.py +0 -0
  29. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/http_logger.py +0 -0
  30. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/.gitignore +0 -0
  31. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/build.mts +0 -0
  32. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/client.mts +0 -0
  33. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/global.d.ts +0 -0
  34. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/package.json +0 -0
  35. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/remote.py +0 -0
  36. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/server_sent_events.py +0 -0
  37. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/src/graph.mts +0 -0
  38. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/src/hooks.mjs +0 -0
  39. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/src/parser/parser.mts +0 -0
  40. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/src/parser/parser.worker.mjs +0 -0
  41. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/src/schema/types.mts +0 -0
  42. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/src/schema/types.template.mts +0 -0
  43. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/src/utils/importMap.mts +0 -0
  44. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
  45. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/src/utils/serde.mts +0 -0
  46. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/tests/api.test.mts +0 -0
  47. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/tests/compose-postgres.yml +0 -0
  48. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/tests/graphs/.gitignore +0 -0
  49. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/tests/graphs/agent.mts +0 -0
  50. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/tests/graphs/error.mts +0 -0
  51. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/tests/graphs/langgraph.json +0 -0
  52. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/tests/graphs/nested.mts +0 -0
  53. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/tests/graphs/package.json +0 -0
  54. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/tests/graphs/weather.mts +0 -0
  55. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/tests/graphs/yarn.lock +0 -0
  56. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/tests/parser.test.mts +0 -0
  57. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/tests/utils.mts +0 -0
  58. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/js/yarn.lock +0 -0
  59. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/lifespan.py +0 -0
  60. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/logging.py +0 -0
  61. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/metadata.py +0 -0
  62. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/models/__init__.py +0 -0
  63. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/models/run.py +0 -0
  64. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/patch.py +0 -0
  65. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/queue.py +0 -0
  66. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/route.py +0 -0
  67. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/schema.py +0 -0
  68. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/serde.py +0 -0
  69. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/server.py +0 -0
  70. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/sse.py +0 -0
  71. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/state.py +0 -0
  72. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/stream.py +0 -0
  73. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_api/validation.py +0 -0
  74. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_license/__init__.py +0 -0
  75. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_license/middleware.py +0 -0
  76. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_license/validation.py +0 -0
  77. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_storage/__init__.py +0 -0
  78. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_storage/checkpoint.py +0 -0
  79. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_storage/database.py +0 -0
  80. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_storage/queue.py +0 -0
  81. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_storage/retry.py +0 -0
  82. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_storage/store.py +0 -0
  83. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/langgraph_storage/ttl_dict.py +0 -0
  84. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/logging.json +0 -0
  85. {langgraph_api-0.0.9 → langgraph_api-0.0.11}/openapi.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langgraph-api
3
- Version: 0.0.9
3
+ Version: 0.0.11
4
4
  Summary:
5
5
  License: Elastic-2.0
6
6
  Author: Nuno Campos
@@ -16,6 +16,7 @@ Requires-Dist: jsonschema-rs (>=0.25.0,<0.26.0)
16
16
  Requires-Dist: langchain-core (>=0.2.38,<0.4.0)
17
17
  Requires-Dist: langgraph (>=0.2.56,<0.3.0)
18
18
  Requires-Dist: langgraph-checkpoint (>=2.0.7,<3.0)
19
+ Requires-Dist: langgraph-sdk (>=0.1.47,<0.2.0)
19
20
  Requires-Dist: langsmith (>=0.1.63,<0.3.0)
20
21
  Requires-Dist: orjson (>=3.10.1)
21
22
  Requires-Dist: pyjwt (>=2.9.0,<3.0.0)
@@ -3,13 +3,13 @@ import copy
3
3
  import functools
4
4
  import importlib.util
5
5
  import inspect
6
- import logging
7
6
  import os
8
7
  import sys
9
8
  from collections.abc import Awaitable, Callable, Mapping
10
9
  from contextlib import AsyncExitStack
11
10
  from typing import Any, get_args
12
11
 
12
+ import structlog
13
13
  from langgraph_sdk import Auth
14
14
  from starlette.authentication import (
15
15
  AuthCredentials,
@@ -26,7 +26,7 @@ from starlette.responses import Response
26
26
  from langgraph_api.auth.langsmith.backend import LangsmithAuthBackend
27
27
  from langgraph_api.config import LANGGRAPH_AUTH
28
28
 
29
- logger = logging.getLogger(__name__)
29
+ logger = structlog.stdlib.get_logger(__name__)
30
30
 
31
31
  SUPPORTED_PARAMETERS = {
32
32
  "request": Request,
@@ -50,11 +50,15 @@ def get_custom_auth_middleware() -> AuthenticationBackend:
50
50
  "LANGGRAPH_AUTH must be set to a Python file path or a config dict"
51
51
  " to use custom authentication."
52
52
  )
53
+ logger.info("Using custom authentication", langgraph_auth=LANGGRAPH_AUTH)
53
54
  return _get_custom_auth_middleware(LANGGRAPH_AUTH)
54
55
 
55
56
 
56
57
  @functools.lru_cache(maxsize=1)
57
58
  def get_auth_instance() -> Auth | None:
59
+ logger.info(
60
+ f"Getting auth instance: {LANGGRAPH_AUTH}", langgraph_auth=str(LANGGRAPH_AUTH)
61
+ )
58
62
  if not LANGGRAPH_AUTH:
59
63
  return None
60
64
  path = LANGGRAPH_AUTH.get("path")
@@ -116,7 +120,6 @@ class CustomAuthBackend(AuthenticationBackend):
116
120
  ) = None,
117
121
  disable_studio_auth: bool = False,
118
122
  ):
119
- assert fn is not None
120
123
  if fn is None:
121
124
  self.fn = None
122
125
  elif not inspect.iscoroutinefunction(fn):
@@ -133,6 +136,14 @@ class CustomAuthBackend(AuthenticationBackend):
133
136
  else:
134
137
  self.ls_auth = None
135
138
 
139
+ def __str__(self):
140
+ return (
141
+ f"CustomAuthBackend(fn={self.fn}, "
142
+ f"ls_auth={self.ls_auth}, "
143
+ f"param_names={self._param_names}"
144
+ ")"
145
+ )
146
+
136
147
  async def authenticate(
137
148
  self, conn: HTTPConnection
138
149
  ) -> tuple[AuthCredentials, BaseUser] | None:
@@ -147,8 +158,8 @@ class CustomAuthBackend(AuthenticationBackend):
147
158
  args = _extract_arguments_from_scope(
148
159
  conn.scope, self._param_names, request=Request(conn.scope)
149
160
  )
150
- scopes, user = await self.fn(**args)
151
- return AuthCredentials(scopes), _normalize_user(user)
161
+ response = await self.fn(**args)
162
+ return _normalize_auth_response(response)
152
163
  except AssertionError as e:
153
164
  raise AuthenticationError(str(e)) from None
154
165
 
@@ -163,10 +174,12 @@ def _get_custom_auth_middleware(
163
174
  path = config.get("path")
164
175
  disable_studio_auth = config.get("disable_studio_auth", disable_studio_auth)
165
176
  auth_instance = _get_auth_instance(path)
166
- return CustomAuthBackend(
177
+ result = CustomAuthBackend(
167
178
  auth_instance._authenticate_handler if auth_instance else None,
168
179
  disable_studio_auth,
169
180
  )
181
+ logger.info(f"Loaded custom auth middleware: {str(result)}")
182
+ return result
170
183
 
171
184
 
172
185
  @functools.lru_cache(maxsize=1)
@@ -182,7 +195,7 @@ def _get_auth_instance(path: str | None = None) -> Auth | None:
182
195
  auth_instance._authenticate_handler = _solve_fastapi_dependencies(
183
196
  auth_instance._authenticate_handler, deps
184
197
  )
185
-
198
+ logger.info(f"Loaded auth instance from path {path}: {auth_instance}")
186
199
  return auth_instance
187
200
 
188
201
 
@@ -216,10 +229,11 @@ def _extract_arguments_from_scope(
216
229
  if "headers" in param_names:
217
230
  args["headers"] = dict(scope.get("headers", {}))
218
231
  if "authorization" in param_names:
219
- headers = scope.get("headers", {})
220
- args["authorization"] = headers.get("authorization") or headers.get(
221
- "Authorization"
222
- )
232
+ headers = dict(scope.get("headers", {}))
233
+ authorization = headers.get(b"authorization") or headers.get(b"Authorization")
234
+ if isinstance(authorization, bytes):
235
+ authorization = authorization.decode(encoding="utf-8")
236
+ args["authorization"] = authorization
223
237
  if "method" in param_names:
224
238
  args["method"] = scope.get("method")
225
239
 
@@ -254,6 +268,7 @@ def _solve_fastapi_dependencies(
254
268
  fn: Callable[..., Any], deps: Mapping[str, Any]
255
269
  ) -> Callable:
256
270
  """Solve FastAPI dependencies for a given function."""
271
+ logger.info("Solving FastAPI dependencies", fn=str(fn), deps=str(deps))
257
272
  from fastapi.dependencies.utils import (
258
273
  get_parameterless_sub_dependant,
259
274
  solve_dependencies,
@@ -400,6 +415,28 @@ class ProxyUser(BaseUser):
400
415
  return getattr(self._user, name)
401
416
 
402
417
 
418
+ def _normalize_auth_response(
419
+ response: Any,
420
+ ) -> tuple[AuthCredentials, BaseUser]:
421
+ if isinstance(response, tuple):
422
+ if len(response) != 2:
423
+ raise ValueError(
424
+ f"Expected a tuple with two elements (permissions, user), got {len(response)}"
425
+ )
426
+ permissions, user = response
427
+ elif hasattr(response, "permissions"):
428
+ permissions = response.permissions
429
+ user = response
430
+ elif isinstance(response, dict | Mapping) and "permissions" in response:
431
+ permissions = response["permissions"]
432
+ user = response
433
+ else:
434
+ user = response
435
+ permissions = []
436
+
437
+ return AuthCredentials(permissions), _normalize_user(user)
438
+
439
+
403
440
  def _normalize_user(user: Any) -> BaseUser:
404
441
  """Normalize user into a BaseUser instance."""
405
442
  if isinstance(user, BaseUser):
@@ -1,3 +1,4 @@
1
+ import structlog
1
2
  from starlette.middleware import Middleware
2
3
  from starlette.middleware.authentication import (
3
4
  AuthenticationError,
@@ -9,8 +10,11 @@ from starlette.types import Receive, Scope, Send
9
10
 
10
11
  from langgraph_api.config import LANGGRAPH_AUTH_TYPE
11
12
 
13
+ logger = structlog.stdlib.get_logger(__name__)
14
+
12
15
 
13
16
  def get_auth_backend():
17
+ logger.info(f"Using auth of type={LANGGRAPH_AUTH_TYPE}")
14
18
  if LANGGRAPH_AUTH_TYPE == "langsmith":
15
19
  from langgraph_api.auth.langsmith.backend import LangsmithAuthBackend
16
20
 
@@ -6,7 +6,7 @@ from datetime import datetime
6
6
  from typing import Any, Protocol, TypeAlias, TypeVar
7
7
 
8
8
  from langgraph_sdk import Auth
9
- from starlette.authentication import AuthCredentials, BaseUser
9
+ from starlette.authentication import AuthCredentials, BaseUser, SimpleUser
10
10
  from starlette.exceptions import HTTPException
11
11
 
12
12
  T = TypeVar("T")
@@ -32,8 +32,8 @@ def set_auth_ctx(user: BaseUser | None, auth: AuthCredentials | None) -> None:
32
32
  else:
33
33
  AuthContext.set(
34
34
  Auth.types.BaseAuthContext(
35
- scopes=auth.scopes,
36
- user=user,
35
+ permissions=auth.scopes,
36
+ user=user or SimpleUser(""),
37
37
  )
38
38
  )
39
39
 
@@ -83,7 +83,7 @@ class Authenticated:
83
83
  return
84
84
  return Auth.types.AuthContext(
85
85
  user=ctx.user,
86
- scopes=ctx.scopes,
86
+ permissions=ctx.permissions,
87
87
  resource=cls.resource,
88
88
  action=action,
89
89
  )
@@ -846,7 +846,6 @@ class Threads(Authenticated):
846
846
  raise HTTPException(
847
847
  status_code=404, detail=f"Thread with ID {thread_id} not found"
848
848
  )
849
-
850
849
  # Delete the thread
851
850
  conn.locks.pop(thread_id, None)
852
851
  # Cascade delete all runs associated with this thread
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "langgraph-api"
3
- version = "0.0.9"
3
+ version = "0.0.11"
4
4
  description = ""
5
5
  authors = [
6
6
  "Nuno Campos <nuno@langchain.dev>",
@@ -35,6 +35,7 @@ jsonschema-rs = "^0.25.0"
35
35
  structlog = "^24.4.0"
36
36
  pyjwt = "^2.9.0"
37
37
  cryptography = "^43.0.3"
38
+ langgraph-sdk = "^0.1.47"
38
39
 
39
40
  [tool.poetry.group.dev.dependencies]
40
41
  ruff = "^0.6.2"
@@ -42,8 +43,7 @@ codespell = "^2.2.0"
42
43
  pytest = "^7.4.4"
43
44
  anyio = "^4.4.0"
44
45
  pytest-watcher = "^0.4.2"
45
- langgraph-cli = "^0.1.62"
46
- langgraph-sdk = "^0.1.45"
46
+ langgraph-cli = "^0.1.63"
47
47
  pytest-repeat = "^0.9.3"
48
48
  pytest-retry = "^1.6.3"
49
49
 
File without changes
File without changes