langgraph-api 0.0.26__py3-none-any.whl → 0.0.28rc1__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.

Files changed (53) hide show
  1. langgraph_api/api/__init__.py +2 -0
  2. langgraph_api/api/assistants.py +43 -13
  3. langgraph_api/api/meta.py +2 -1
  4. langgraph_api/api/runs.py +14 -1
  5. langgraph_api/api/ui.py +68 -0
  6. langgraph_api/asyncio.py +43 -4
  7. langgraph_api/auth/middleware.py +2 -2
  8. langgraph_api/cli.py +72 -57
  9. langgraph_api/config.py +23 -1
  10. langgraph_api/cron_scheduler.py +1 -1
  11. langgraph_api/graph.py +5 -0
  12. langgraph_api/http.py +24 -7
  13. langgraph_api/js/.gitignore +2 -0
  14. langgraph_api/js/build.mts +49 -3
  15. langgraph_api/js/client.mts +84 -40
  16. langgraph_api/js/global.d.ts +1 -0
  17. langgraph_api/js/package.json +15 -7
  18. langgraph_api/js/remote.py +662 -16
  19. langgraph_api/js/src/graph.mts +5 -4
  20. langgraph_api/js/sse.py +138 -0
  21. langgraph_api/js/tests/api.test.mts +28 -0
  22. langgraph_api/js/tests/compose-postgres.yml +2 -2
  23. langgraph_api/js/tests/graphs/agent.css +1 -0
  24. langgraph_api/js/tests/graphs/agent.ui.tsx +10 -0
  25. langgraph_api/js/tests/graphs/package.json +2 -2
  26. langgraph_api/js/tests/graphs/yarn.lock +13 -13
  27. langgraph_api/js/yarn.lock +710 -1187
  28. langgraph_api/lifespan.py +15 -5
  29. langgraph_api/logging.py +9 -0
  30. langgraph_api/metadata.py +5 -1
  31. langgraph_api/middleware/http_logger.py +1 -1
  32. langgraph_api/patch.py +2 -0
  33. langgraph_api/queue_entrypoint.py +63 -0
  34. langgraph_api/schema.py +2 -0
  35. langgraph_api/stream.py +1 -0
  36. langgraph_api/webhook.py +42 -0
  37. langgraph_api/{queue.py → worker.py} +52 -166
  38. {langgraph_api-0.0.26.dist-info → langgraph_api-0.0.28rc1.dist-info}/METADATA +8 -8
  39. {langgraph_api-0.0.26.dist-info → langgraph_api-0.0.28rc1.dist-info}/RECORD +49 -46
  40. langgraph_storage/database.py +8 -22
  41. langgraph_storage/inmem_stream.py +108 -0
  42. langgraph_storage/ops.py +80 -57
  43. langgraph_storage/queue.py +126 -103
  44. langgraph_storage/retry.py +5 -1
  45. langgraph_storage/store.py +5 -1
  46. openapi.json +3 -3
  47. langgraph_api/js/client.new.mts +0 -861
  48. langgraph_api/js/remote_new.py +0 -694
  49. langgraph_api/js/remote_old.py +0 -667
  50. langgraph_api/js/server_sent_events.py +0 -126
  51. {langgraph_api-0.0.26.dist-info → langgraph_api-0.0.28rc1.dist-info}/LICENSE +0 -0
  52. {langgraph_api-0.0.26.dist-info → langgraph_api-0.0.28rc1.dist-info}/WHEEL +0 -0
  53. {langgraph_api-0.0.26.dist-info → langgraph_api-0.0.28rc1.dist-info}/entry_points.txt +0 -0
@@ -1,126 +0,0 @@
1
- """Adapted from https://github.com/florimondmanca/httpx-sse"""
2
-
3
- from collections.abc import AsyncIterator, Iterator
4
- from contextlib import asynccontextmanager
5
- from typing import Any, TypedDict
6
-
7
- import httpx
8
-
9
-
10
- class ServerSentEvent(TypedDict):
11
- event: str | None
12
- data: str | None
13
- id: str | None
14
- retry: int | None
15
-
16
-
17
- class SSEDecoder:
18
- def __init__(self) -> None:
19
- self._event = ""
20
- self._data: list[str] = []
21
- self._last_event_id = ""
22
- self._retry: int | None = None
23
-
24
- def decode(self, line: str) -> ServerSentEvent | None:
25
- # See: https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation # noqa: E501
26
- if not line:
27
- if (
28
- not self._event
29
- and not self._data
30
- and not self._last_event_id
31
- and self._retry is None
32
- ):
33
- return None
34
-
35
- sse = {
36
- "event": self._event,
37
- "data": "\n".join(self._data),
38
- "id": self._last_event_id,
39
- "retry": self._retry,
40
- }
41
-
42
- # NOTE: as per the SSE spec, do not reset last_event_id.
43
- self._event = ""
44
- self._data = []
45
- self._retry = None
46
-
47
- return sse
48
-
49
- if line.startswith(":"):
50
- return None
51
-
52
- fieldname, _, value = line.partition(":")
53
-
54
- if value.startswith(" "):
55
- value = value[1:]
56
-
57
- if fieldname == "event":
58
- self._event = value
59
- elif fieldname == "data":
60
- self._data.append(value)
61
- elif fieldname == "id":
62
- if "\0" in value:
63
- pass
64
- else:
65
- self._last_event_id = value
66
- elif fieldname == "retry":
67
- try:
68
- self._retry = int(value)
69
- except (TypeError, ValueError):
70
- pass
71
- else:
72
- pass # Field is ignored.
73
-
74
- return None
75
-
76
-
77
- class EventSource:
78
- def __init__(self, response: httpx.Response) -> None:
79
- self._response = response
80
-
81
- def _check_content_type(self) -> None:
82
- """Check that the response content type is 'text/event-stream'."""
83
- self._response.raise_for_status()
84
- content_type = self._response.headers.get("content-type", "").partition(";")[0]
85
- if "text/event-stream" not in content_type:
86
- raise AssertionError(
87
- "Expected response header Content-Type to contain 'text/event-stream', "
88
- f"got {content_type!r}"
89
- )
90
-
91
- @property
92
- def response(self) -> httpx.Response:
93
- return self._response
94
-
95
- def iter_sse(self) -> Iterator[ServerSentEvent]:
96
- self._check_content_type()
97
- decoder = SSEDecoder()
98
- for line in self._response.iter_lines():
99
- line = line.rstrip("\n")
100
- sse = decoder.decode(line)
101
- if sse is not None:
102
- yield sse
103
-
104
- async def aiter_sse(self) -> AsyncIterator[ServerSentEvent]:
105
- self._check_content_type()
106
- decoder = SSEDecoder()
107
- async for line in self._response.aiter_lines():
108
- line = line.rstrip("\n")
109
- sse = decoder.decode(line)
110
- if sse is not None:
111
- yield sse
112
-
113
-
114
- @asynccontextmanager
115
- async def aconnect_sse(
116
- client: httpx.AsyncClient,
117
- method: str,
118
- url: str,
119
- **kwargs: Any,
120
- ) -> AsyncIterator[EventSource]:
121
- headers = kwargs.pop("headers", {})
122
- headers["Accept"] = "text/event-stream"
123
- headers["Cache-Control"] = "no-store"
124
-
125
- async with client.stream(method, url, headers=headers, **kwargs) as response:
126
- yield EventSource(response)