langgraph-api 0.2.23__py3-none-any.whl → 0.2.25__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.2.23"
1
+ __version__ = "0.2.25"
langgraph_api/serde.py CHANGED
@@ -1,7 +1,9 @@
1
1
  import asyncio
2
+ import re
2
3
  import uuid
3
4
  from base64 import b64encode
4
5
  from collections import deque
6
+ from collections.abc import Mapping
5
7
  from datetime import timedelta, timezone
6
8
  from decimal import Decimal
7
9
  from ipaddress import (
@@ -101,11 +103,36 @@ def default(obj):
101
103
 
102
104
  _option = orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_NON_STR_KEYS
103
105
 
106
+ _SURROGATE_RE = re.compile(r"[\ud800-\udfff]")
107
+
108
+
109
+ def _strip_surr(s: str) -> str:
110
+ return s if _SURROGATE_RE.search(s) is None else _SURROGATE_RE.sub("", s)
111
+
112
+
113
+ def _sanitise(o: Any) -> Any:
114
+ if isinstance(o, str):
115
+ return _strip_surr(o)
116
+ if isinstance(o, Mapping):
117
+ return {_sanitise(k): _sanitise(v) for k, v in o.items()}
118
+ if isinstance(o, list | tuple | set):
119
+ ctor = list if isinstance(o, list) else type(o)
120
+ return ctor(_sanitise(x) for x in o)
121
+ return o
122
+
104
123
 
105
124
  def json_dumpb(obj) -> bytes:
106
- return orjson.dumps(obj, default=default, option=_option).replace(
107
- rb"\u0000", b""
108
- ) # null unicode char not allowed in json
125
+ try:
126
+ return orjson.dumps(obj, default=default, option=_option).replace(
127
+ rb"\u0000", b""
128
+ ) # null unicode char not allowed in json
129
+ except TypeError as e:
130
+ if "surrogates not allowed" not in str(e):
131
+ raise
132
+ surrogate_sanitized = _sanitise(obj)
133
+ return orjson.dumps(
134
+ surrogate_sanitized, default=default, option=_option
135
+ ).replace(rb"\u0000", b"")
109
136
 
110
137
 
111
138
  def json_loads(content: bytes | Fragment | dict) -> Any:
langgraph_api/stream.py CHANGED
@@ -9,6 +9,7 @@ import structlog
9
9
  from langchain_core.messages import (
10
10
  BaseMessage,
11
11
  BaseMessageChunk,
12
+ convert_to_messages,
12
13
  message_chunk_to_message,
13
14
  )
14
15
  from langchain_core.runnables.config import run_in_executor
@@ -178,7 +179,11 @@ async def astream_state(
178
179
  else:
179
180
  yield "messages", chunk
180
181
  else:
181
- msg, meta = cast(tuple[BaseMessage, dict[str, Any]], chunk)
182
+ msg, meta = cast(
183
+ tuple[BaseMessage | dict, dict[str, Any]], chunk
184
+ )
185
+ if isinstance(msg, dict):
186
+ msg = convert_to_messages([msg])[0]
182
187
  if msg.id in messages:
183
188
  messages[msg.id] += msg
184
189
  else:
@@ -233,7 +238,11 @@ async def astream_state(
233
238
  else:
234
239
  yield "messages", chunk
235
240
  else:
236
- msg, meta = cast(tuple[BaseMessage, dict[str, Any]], chunk)
241
+ msg, meta = cast(
242
+ tuple[BaseMessage | dict, dict[str, Any]], chunk
243
+ )
244
+ if isinstance(msg, dict):
245
+ msg = convert_to_messages([msg])[0]
237
246
  if msg.id in messages:
238
247
  messages[msg.id] += msg
239
248
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: langgraph-api
3
- Version: 0.2.23
3
+ Version: 0.2.25
4
4
  Summary:
5
5
  License: Elastic-2.0
6
6
  Author: Nuno Campos
@@ -1,5 +1,5 @@
1
1
  LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
2
- langgraph_api/__init__.py,sha256=drfF0qMRjoB2RacyqP-NkNmDOIBrys6RWHvqSTpZLuc,23
2
+ langgraph_api/__init__.py,sha256=kx2V3mL-5OE7Q8rQ4rG5_RJEWOoZ9gDri5puJRGkRm8,23
3
3
  langgraph_api/api/__init__.py,sha256=YVzpbn5IQotvuuLG9fhS9QMrxXfP4s4EpEMG0n4q3Nw,5625
4
4
  langgraph_api/api/assistants.py,sha256=4_tZCXlOmFg-YwgtsCZPc1wr-3fexqJ6A3_2a5giF90,15811
5
5
  langgraph_api/api/mcp.py,sha256=RvRYgANqRzNQzSmgjNkq4RlKTtoEJYil04ot9lsmEtE,14352
@@ -81,11 +81,11 @@ langgraph_api/patch.py,sha256=Dgs0PXHytekX4SUL6KsjjN0hHcOtGLvv1GRGbh6PswU,1408
81
81
  langgraph_api/queue_entrypoint.py,sha256=Hw6W66EEY_V7GHvnRzijsbvoNy4TM7IQVoZJ-DRbSfU,2173
82
82
  langgraph_api/route.py,sha256=uN311KjIugyNHG3rmVw_ms61QO1W1l16jJx03rf0R_s,4630
83
83
  langgraph_api/schema.py,sha256=2711t4PIBk5dky4gmMndrTRC9CVvAgH47C9FKDxhkBo,5444
84
- langgraph_api/serde.py,sha256=TVsx2QQtepf8Wsgsabcku1NV4Vbugu4Oujmdnq4qMS0,3964
84
+ langgraph_api/serde.py,sha256=8fQXg7T7RVUqj_jgOoSOJrWVpQDW0qJKjAjSsEhPHo4,4803
85
85
  langgraph_api/server.py,sha256=4P7GpXbE9m-sAV7rBQ4Gd3oFk6htNbL-tRQfICAFc2k,6837
86
86
  langgraph_api/sse.py,sha256=3jG_FZj8FI9r7xGWTqaAyDkmqf6P1NOu0EzGrcSOGYc,4033
87
87
  langgraph_api/state.py,sha256=8jx4IoTCOjTJuwzuXJKKFwo1VseHjNnw_CCq4x1SW14,2284
88
- langgraph_api/stream.py,sha256=4wKeoLuxqy7m7iamONmP9Lw4vcHEMWPeQFV_PrJC5AY,12042
88
+ langgraph_api/stream.py,sha256=vQXHb2f8g-VvTRjPcgq4MEQ2mR4tYdQ8nxr4V3ogQkQ,12433
89
89
  langgraph_api/thread_ttl.py,sha256=-Ox8NFHqUH3wGNdEKMIfAXUubY5WGifIgCaJ7npqLgw,1762
90
90
  langgraph_api/tunneling/cloudflare.py,sha256=iKb6tj-VWPlDchHFjuQyep2Dpb-w2NGfJKt-WJG9LH0,3650
91
91
  langgraph_api/utils.py,sha256=92mSti9GfGdMRRWyESKQW5yV-75Z9icGHnIrBYvdypU,3619
@@ -96,9 +96,9 @@ langgraph_license/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
96
96
  langgraph_license/validation.py,sha256=ZKraAVJArAABKqrmHN-EN18ncoNUmRm500Yt1Sc7tUA,537
97
97
  langgraph_runtime/__init__.py,sha256=O4GgSmu33c-Pr8Xzxj_brcK5vkm70iNTcyxEjICFZxA,1075
98
98
  logging.json,sha256=3RNjSADZmDq38eHePMm1CbP6qZ71AmpBtLwCmKU9Zgo,379
99
- openapi.json,sha256=h2zgGTQD9houdruwRdNwZuAFo-w3eP_f6huQ6jRFp84,133801
100
- langgraph_api-0.2.23.dist-info/LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
101
- langgraph_api-0.2.23.dist-info/METADATA,sha256=17XvJmMLdBhzcwrl06VdUWmqIFUgDbCb5_rUjfDrPwY,4275
102
- langgraph_api-0.2.23.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
103
- langgraph_api-0.2.23.dist-info/entry_points.txt,sha256=3EYLgj89DfzqJHHYGxPH4A_fEtClvlRbWRUHaXO7hj4,77
104
- langgraph_api-0.2.23.dist-info/RECORD,,
99
+ openapi.json,sha256=ZMY9UXZJYiFK59z8QmDxVZ7LV6KonQbHzG-D5h-ZTYE,135412
100
+ langgraph_api-0.2.25.dist-info/LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
101
+ langgraph_api-0.2.25.dist-info/METADATA,sha256=F1iyqIgf6SPCfAhhV1VG3T1ku730vjotATOHCf820rE,4275
102
+ langgraph_api-0.2.25.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
103
+ langgraph_api-0.2.25.dist-info/entry_points.txt,sha256=3EYLgj89DfzqJHHYGxPH4A_fEtClvlRbWRUHaXO7hj4,77
104
+ langgraph_api-0.2.25.dist-info/RECORD,,
openapi.json CHANGED
@@ -779,56 +779,6 @@
779
779
  }
780
780
  }
781
781
  },
782
- "/threads/state/bulk": {
783
- "post": {
784
- "tags": ["Threads"],
785
- "summary": "Bulk Update Thread State",
786
- "description": "Create a new thread from a batch of state updates.",
787
- "operationId": "bulk_update_thread_state_post",
788
- "requestBody": {
789
- "content": {
790
- "application/json": {
791
- "schema": {
792
- "$ref": "#/components/schemas/ThreadStateBulkUpdate"
793
- }
794
- }
795
- },
796
- "required": true
797
- },
798
- "responses": {
799
- "200": {
800
- "description": "Success",
801
- "content": {
802
- "application/json": {
803
- "schema": {
804
- "$ref": "#/components/schemas/Thread"
805
- }
806
- }
807
- }
808
- },
809
- "409": {
810
- "description": "Conflict",
811
- "content": {
812
- "application/json": {
813
- "schema": {
814
- "$ref": "#/components/schemas/ErrorResponse"
815
- }
816
- }
817
- }
818
- },
819
- "422": {
820
- "description": "Validation Error",
821
- "content": {
822
- "application/json": {
823
- "schema": {
824
- "$ref": "#/components/schemas/ErrorResponse"
825
- }
826
- }
827
- }
828
- }
829
- }
830
- }
831
- },
832
782
  "/threads/{thread_id}/state": {
833
783
  "get": {
834
784
  "tags": ["Threads"],
@@ -847,6 +797,17 @@
847
797
  },
848
798
  "name": "thread_id",
849
799
  "in": "path"
800
+ },
801
+ {
802
+ "description": "Whether to include subgraphs in the response.",
803
+ "required": false,
804
+ "schema": {
805
+ "type": "boolean",
806
+ "title": "Subgraphs",
807
+ "description": "Whether to include subgraphs in the response."
808
+ },
809
+ "name": "subgraphs",
810
+ "in": "query"
850
811
  }
851
812
  ],
852
813
  "responses": {
@@ -925,12 +886,103 @@
925
886
  }
926
887
  }
927
888
  },
889
+ "/threads/{thread_id}/state/{checkpoint_id}": {
890
+ "get": {
891
+ "tags": ["Threads"],
892
+ "summary": "Get Thread State At Checkpoint",
893
+ "description": "Get state for a thread at a specific checkpoint.",
894
+ "operationId": "get_thread_state_at_checkpoint_threads__thread_id__state__checkpoint_id__get",
895
+ "parameters": [
896
+ {
897
+ "description": "The ID of the thread.",
898
+ "required": true,
899
+ "schema": {
900
+ "type": "string",
901
+ "format": "uuid",
902
+ "title": "Thread Id",
903
+ "description": "The ID of the thread."
904
+ },
905
+ "name": "thread_id",
906
+ "in": "path"
907
+ },
908
+ {
909
+ "description": "The ID of the checkpoint.",
910
+ "required": true,
911
+ "schema": {
912
+ "type": "string",
913
+ "format": "uuid",
914
+ "title": "Checkpoint Id",
915
+ "description": "The ID of the checkpoint."
916
+ },
917
+ "name": "checkpoint_id",
918
+ "in": "path"
919
+ },
920
+ {
921
+ "description": "Whether to include subgraphs in the response.",
922
+ "required": false,
923
+ "schema": {
924
+ "type": "boolean",
925
+ "title": "Subgraphs",
926
+ "description": "Whether to include subgraphs in the response."
927
+ },
928
+ "name": "subgraphs",
929
+ "in": "query"
930
+ }
931
+ ],
932
+ "responses": {
933
+ "200": {
934
+ "description": "Success",
935
+ "content": {
936
+ "application/json": {
937
+ "schema": {
938
+ "$ref": "#/components/schemas/ThreadState"
939
+ }
940
+ }
941
+ }
942
+ },
943
+ "422": {
944
+ "description": "Validation Error",
945
+ "content": {
946
+ "application/json": {
947
+ "schema": {
948
+ "$ref": "#/components/schemas/ErrorResponse"
949
+ }
950
+ }
951
+ }
952
+ }
953
+ }
954
+ }
955
+ },
928
956
  "/threads/{thread_id}/state/checkpoint": {
929
957
  "post": {
930
958
  "tags": ["Threads"],
931
959
  "summary": "Get Thread State At Checkpoint",
932
960
  "description": "Get state for a thread at a specific checkpoint.",
933
961
  "operationId": "post_thread_state_at_checkpoint_threads__thread_id__state__checkpoint_id__get",
962
+ "parameters": [
963
+ {
964
+ "description": "The ID of the thread.",
965
+ "required": true,
966
+ "schema": {
967
+ "type": "string",
968
+ "format": "uuid",
969
+ "title": "Thread Id",
970
+ "description": "The ID of the thread."
971
+ },
972
+ "name": "thread_id",
973
+ "in": "path"
974
+ },
975
+ {
976
+ "required": false,
977
+ "schema": {
978
+ "type": "boolean",
979
+ "title": "Subgraphs",
980
+ "description": "If true, includes subgraph states."
981
+ },
982
+ "name": "subgraphs",
983
+ "in": "query"
984
+ }
985
+ ],
934
986
  "requestBody": {
935
987
  "content": {
936
988
  "application/json": {