langgraph-api 0.4.28__py3-none-any.whl → 0.4.29__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.

@@ -0,0 +1,540 @@
1
+ """gRPC-based operations for LangGraph API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import functools
7
+ from collections.abc import AsyncIterator
8
+ from http import HTTPStatus
9
+ from typing import Any
10
+ from uuid import UUID
11
+
12
+ import structlog
13
+ from google.protobuf.json_format import MessageToDict
14
+ from google.protobuf.struct_pb2 import Struct # type: ignore[import]
15
+ from grpc import StatusCode
16
+ from grpc.aio import AioRpcError
17
+ from langgraph_sdk.schema import Config
18
+ from starlette.exceptions import HTTPException
19
+
20
+ from langgraph_api.schema import (
21
+ Assistant,
22
+ AssistantSelectField,
23
+ Context,
24
+ MetadataInput,
25
+ OnConflictBehavior,
26
+ )
27
+
28
+ from .client import GrpcClient
29
+ from .generated import core_api_pb2 as pb
30
+
31
+ GRPC_STATUS_TO_HTTP_STATUS = {
32
+ StatusCode.NOT_FOUND: HTTPStatus.NOT_FOUND,
33
+ StatusCode.ALREADY_EXISTS: HTTPStatus.CONFLICT,
34
+ StatusCode.INVALID_ARGUMENT: HTTPStatus.UNPROCESSABLE_ENTITY,
35
+ }
36
+
37
+ logger = structlog.stdlib.get_logger(__name__)
38
+
39
+
40
+ def map_if_exists(if_exists: str) -> pb.OnConflictBehavior:
41
+ if if_exists == "do_nothing":
42
+ return pb.OnConflictBehavior.DO_NOTHING
43
+ return pb.OnConflictBehavior.RAISE
44
+
45
+
46
+ def map_configurable(config: Config) -> Struct:
47
+ return pb.RunnableConfig(
48
+ tags=config.get("tags", []),
49
+ recursion_limit=config.get("recursion_limit"),
50
+ configurable=dict_to_struct(config.get("configurable", {}))
51
+ if config.get("configurable")
52
+ else None,
53
+ )
54
+
55
+
56
+ def consolidate_config_and_context(config: Config, context: Context | None):
57
+ if config and config.get("configurable") and context:
58
+ raise HTTPException(
59
+ status_code=400,
60
+ detail="Cannot specify both configurable and context. Prefer setting context alone. Context was introduced in LangGraph 0.6.0 and is the long term planned replacement for configurable.",
61
+ )
62
+
63
+ # Keep config and context up to date with one another
64
+ if config and config.get("configurable"):
65
+ context = config["configurable"]
66
+ elif context:
67
+ config["configurable"] = context
68
+
69
+
70
+ def dict_to_struct(data: dict[str, Any]) -> Struct:
71
+ """Convert a dictionary to a protobuf Struct."""
72
+ struct = Struct()
73
+ if data:
74
+ struct.update(data)
75
+ return struct
76
+
77
+
78
+ def struct_to_dict(struct: Struct) -> dict[str, Any]:
79
+ """Convert a protobuf Struct to a dictionary."""
80
+ return MessageToDict(struct) if struct else {}
81
+
82
+
83
+ def proto_to_assistant(proto_assistant: pb.Assistant) -> Assistant:
84
+ """Convert protobuf Assistant to dictionary format."""
85
+ return {
86
+ "assistant_id": proto_assistant.assistant_id,
87
+ "graph_id": proto_assistant.graph_id,
88
+ "version": proto_assistant.version,
89
+ "created_at": proto_assistant.created_at.ToDatetime(),
90
+ "updated_at": proto_assistant.updated_at.ToDatetime(),
91
+ "config": struct_to_dict(proto_assistant.config),
92
+ "context": struct_to_dict(proto_assistant.context),
93
+ "metadata": struct_to_dict(proto_assistant.metadata),
94
+ "name": proto_assistant.name,
95
+ "description": proto_assistant.description,
96
+ }
97
+
98
+
99
+ def _map_sort_by(sort_by: str | None) -> pb.AssistantsSortBy:
100
+ """Map string sort_by to protobuf enum."""
101
+ if not sort_by:
102
+ return pb.AssistantsSortBy.CREATED_AT
103
+
104
+ sort_by_lower = sort_by.lower()
105
+ mapping = {
106
+ "assistant_id": pb.AssistantsSortBy.ASSISTANT_ID,
107
+ "graph_id": pb.AssistantsSortBy.GRAPH_ID,
108
+ "name": pb.AssistantsSortBy.NAME,
109
+ "created_at": pb.AssistantsSortBy.CREATED_AT,
110
+ "updated_at": pb.AssistantsSortBy.UPDATED_AT,
111
+ }
112
+ return mapping.get(sort_by_lower, pb.AssistantsSortBy.CREATED_AT)
113
+
114
+
115
+ def _map_sort_order(sort_order: str | None) -> pb.SortOrder:
116
+ """Map string sort_order to protobuf enum."""
117
+ if sort_order and sort_order.upper() == "ASC":
118
+ return pb.SortOrder.ASC
119
+ return pb.SortOrder.DESC
120
+
121
+
122
+ def _handle_grpc_error(error: AioRpcError) -> None:
123
+ """Handle gRPC errors and convert to appropriate exceptions."""
124
+ raise HTTPException(
125
+ status_code=GRPC_STATUS_TO_HTTP_STATUS.get(
126
+ error.code(), HTTPStatus.INTERNAL_SERVER_ERROR
127
+ ),
128
+ detail=str(error.details()),
129
+ )
130
+
131
+
132
+ class Authenticated:
133
+ """Base class for authenticated operations (matches storage_postgres interface)."""
134
+
135
+ resource: str = "assistants"
136
+
137
+ @classmethod
138
+ async def handle_event(
139
+ cls,
140
+ ctx: Any, # Auth context
141
+ action: str,
142
+ value: Any,
143
+ ) -> dict[str, Any] | None:
144
+ """Handle authentication event - stub implementation for now."""
145
+ # TODO: Implement proper auth handling that converts auth context
146
+ # to gRPC AuthFilter format when needed
147
+ return None
148
+
149
+
150
+ def grpc_error_guard(cls):
151
+ """Class decorator to wrap async methods and handle gRPC errors uniformly."""
152
+ for name, attr in list(cls.__dict__.items()):
153
+ func = None
154
+ wrapper_type = None
155
+ if isinstance(attr, staticmethod):
156
+ func = attr.__func__
157
+ wrapper_type = staticmethod
158
+ elif isinstance(attr, classmethod):
159
+ func = attr.__func__
160
+ wrapper_type = classmethod
161
+ elif callable(attr):
162
+ func = attr
163
+
164
+ if func and asyncio.iscoroutinefunction(func):
165
+
166
+ def make_wrapper(f):
167
+ @functools.wraps(f)
168
+ async def wrapped(*args, **kwargs):
169
+ try:
170
+ return await f(*args, **kwargs)
171
+ except AioRpcError as e:
172
+ _handle_grpc_error(e)
173
+
174
+ return wrapped # noqa: B023
175
+
176
+ wrapped = make_wrapper(func)
177
+ if wrapper_type is staticmethod:
178
+ setattr(cls, name, staticmethod(wrapped))
179
+ elif wrapper_type is classmethod:
180
+ setattr(cls, name, classmethod(wrapped))
181
+ else:
182
+ setattr(cls, name, wrapped)
183
+ return cls
184
+
185
+
186
+ @grpc_error_guard
187
+ class Assistants(Authenticated):
188
+ """gRPC-based assistants operations."""
189
+
190
+ resource = "assistants"
191
+
192
+ @staticmethod
193
+ async def search(
194
+ conn, # Not used in gRPC implementation
195
+ *,
196
+ graph_id: str | None,
197
+ metadata: MetadataInput,
198
+ limit: int,
199
+ offset: int,
200
+ sort_by: str | None = None,
201
+ sort_order: str | None = None,
202
+ select: list[AssistantSelectField] | None = None,
203
+ ctx: Any = None,
204
+ ) -> tuple[AsyncIterator[Assistant], int | None]: # type: ignore[return-value]
205
+ """Search assistants via gRPC."""
206
+ # Handle auth filters
207
+ auth_filters = await Assistants.handle_event(
208
+ ctx,
209
+ "search",
210
+ {
211
+ "graph_id": graph_id,
212
+ "metadata": metadata,
213
+ "limit": limit,
214
+ "offset": offset,
215
+ },
216
+ )
217
+
218
+ # Build the gRPC request
219
+ request = pb.SearchAssistantsRequest(
220
+ filters=auth_filters,
221
+ graph_id=graph_id,
222
+ metadata=dict_to_struct(metadata or {}),
223
+ limit=limit,
224
+ offset=offset,
225
+ sort_by=_map_sort_by(sort_by),
226
+ sort_order=_map_sort_order(sort_order),
227
+ select=select,
228
+ )
229
+
230
+ # Make the gRPC call
231
+ async with GrpcClient() as client:
232
+ response = await client.assistants.Search(request)
233
+
234
+ # Convert response to expected format
235
+ assistants = [
236
+ proto_to_assistant(assistant) for assistant in response.assistants
237
+ ]
238
+
239
+ # Determine if there are more results
240
+ # Note: gRPC doesn't return cursor info, so we estimate based on result count
241
+ cursor = offset + limit if len(assistants) == limit else None
242
+
243
+ async def generate_results():
244
+ for assistant in assistants:
245
+ yield {
246
+ k: v for k, v in assistant.items() if select is None or k in select
247
+ }
248
+
249
+ return generate_results(), cursor
250
+
251
+ @staticmethod
252
+ async def get(
253
+ conn, # Not used in gRPC implementation
254
+ assistant_id: UUID | str,
255
+ ctx: Any = None,
256
+ ) -> AsyncIterator[Assistant]: # type: ignore[return-value]
257
+ """Get assistant by ID via gRPC."""
258
+ # Handle auth filters
259
+ auth_filters = await Assistants.handle_event(
260
+ ctx, "read", {"assistant_id": str(assistant_id)}
261
+ )
262
+
263
+ # Build the gRPC request
264
+ request = pb.GetAssistantRequest(
265
+ assistant_id=str(assistant_id),
266
+ filters=auth_filters or {},
267
+ )
268
+
269
+ # Make the gRPC call
270
+ async with GrpcClient() as client:
271
+ response = await client.assistants.Get(request)
272
+
273
+ # Convert and yield the result
274
+ assistant = proto_to_assistant(response)
275
+
276
+ async def generate_result():
277
+ yield assistant
278
+
279
+ return generate_result()
280
+
281
+ @staticmethod
282
+ async def put(
283
+ conn, # Not used in gRPC implementation
284
+ assistant_id: UUID | str,
285
+ *,
286
+ graph_id: str,
287
+ config: Config,
288
+ context: Context,
289
+ metadata: MetadataInput,
290
+ if_exists: OnConflictBehavior,
291
+ name: str,
292
+ description: str | None = None,
293
+ ctx: Any = None,
294
+ ) -> AsyncIterator[Assistant]: # type: ignore[return-value]
295
+ """Create/update assistant via gRPC."""
296
+ # Handle auth filters
297
+ auth_filters = await Assistants.handle_event(
298
+ ctx,
299
+ "create",
300
+ {
301
+ "assistant_id": str(assistant_id),
302
+ "graph_id": graph_id,
303
+ "config": config,
304
+ "context": context,
305
+ "metadata": metadata,
306
+ "name": name,
307
+ "description": description,
308
+ },
309
+ )
310
+
311
+ consolidate_config_and_context(config, context)
312
+
313
+ on_conflict = map_if_exists(if_exists)
314
+
315
+ # Build the gRPC request
316
+ request = pb.CreateAssistantRequest(
317
+ assistant_id=str(assistant_id),
318
+ graph_id=graph_id,
319
+ filters=auth_filters or {},
320
+ if_exists=on_conflict,
321
+ config=map_configurable(config),
322
+ context=dict_to_struct(context or {}),
323
+ name=name,
324
+ description=description,
325
+ metadata=dict_to_struct(metadata or {}),
326
+ )
327
+
328
+ # Make the gRPC call
329
+ async with GrpcClient() as client:
330
+ response = await client.assistants.Create(request)
331
+
332
+ # Convert and yield the result
333
+ assistant = proto_to_assistant(response)
334
+
335
+ async def generate_result():
336
+ yield assistant
337
+
338
+ return generate_result()
339
+
340
+ @staticmethod
341
+ async def patch(
342
+ conn, # Not used in gRPC implementation
343
+ assistant_id: UUID | str,
344
+ *,
345
+ config: dict | None = None,
346
+ context: Context | None = None,
347
+ graph_id: str | None = None,
348
+ metadata: MetadataInput | None = None,
349
+ name: str | None = None,
350
+ description: str | None = None,
351
+ ctx: Any = None,
352
+ ) -> AsyncIterator[Assistant]: # type: ignore[return-value]
353
+ """Update assistant via gRPC."""
354
+ metadata = metadata if metadata is not None else {}
355
+ config = config if config is not None else {}
356
+ # Handle auth filters
357
+ auth_filters = await Assistants.handle_event(
358
+ ctx,
359
+ "update",
360
+ {
361
+ "assistant_id": str(assistant_id),
362
+ "graph_id": graph_id,
363
+ "config": config,
364
+ "context": context,
365
+ "metadata": metadata,
366
+ "name": name,
367
+ "description": description,
368
+ },
369
+ )
370
+
371
+ consolidate_config_and_context(config, context)
372
+
373
+ # Build the gRPC request
374
+ request = pb.PatchAssistantRequest(
375
+ assistant_id=str(assistant_id),
376
+ filters=auth_filters or {},
377
+ graph_id=graph_id,
378
+ name=name,
379
+ description=description,
380
+ metadata=dict_to_struct(metadata or {}),
381
+ )
382
+
383
+ # Add optional config if provided
384
+ if config:
385
+ request.config.CopyFrom(map_configurable(config))
386
+
387
+ # Add optional context if provided
388
+ if context:
389
+ request.context.CopyFrom(dict_to_struct(context))
390
+
391
+ # Make the gRPC call
392
+ async with GrpcClient() as client:
393
+ response = await client.assistants.Patch(request)
394
+
395
+ # Convert and yield the result
396
+ assistant = proto_to_assistant(response)
397
+
398
+ async def generate_result():
399
+ yield assistant
400
+
401
+ return generate_result()
402
+
403
+ @staticmethod
404
+ async def delete(
405
+ conn, # Not used in gRPC implementation
406
+ assistant_id: UUID | str,
407
+ ctx: Any = None,
408
+ ) -> AsyncIterator[UUID]: # type: ignore[return-value]
409
+ """Delete assistant via gRPC."""
410
+ # Handle auth filters
411
+ auth_filters = await Assistants.handle_event(
412
+ ctx, "delete", {"assistant_id": str(assistant_id)}
413
+ )
414
+
415
+ # Build the gRPC request
416
+ request = pb.DeleteAssistantRequest(
417
+ assistant_id=str(assistant_id),
418
+ filters=auth_filters or {},
419
+ )
420
+
421
+ # Make the gRPC call
422
+ async with GrpcClient() as client:
423
+ await client.assistants.Delete(request)
424
+
425
+ # Return the deleted ID
426
+ async def generate_result():
427
+ yield UUID(str(assistant_id))
428
+
429
+ return generate_result()
430
+
431
+ @staticmethod
432
+ async def set_latest(
433
+ conn, # Not used in gRPC implementation
434
+ assistant_id: UUID | str,
435
+ version: int,
436
+ ctx: Any = None,
437
+ ) -> AsyncIterator[Assistant]: # type: ignore[return-value]
438
+ """Set latest version of assistant via gRPC."""
439
+ # Handle auth filters
440
+ auth_filters = await Assistants.handle_event(
441
+ ctx,
442
+ "update",
443
+ {
444
+ "assistant_id": str(assistant_id),
445
+ "version": version,
446
+ },
447
+ )
448
+
449
+ # Build the gRPC request
450
+ request = pb.SetLatestAssistantRequest(
451
+ assistant_id=str(assistant_id),
452
+ version=version,
453
+ filters=auth_filters or {},
454
+ )
455
+
456
+ # Make the gRPC call
457
+ async with GrpcClient() as client:
458
+ response = await client.assistants.SetLatest(request)
459
+
460
+ # Convert and yield the result
461
+ assistant = proto_to_assistant(response)
462
+
463
+ async def generate_result():
464
+ yield assistant
465
+
466
+ return generate_result()
467
+
468
+ @staticmethod
469
+ async def get_versions(
470
+ conn, # Not used in gRPC implementation
471
+ assistant_id: UUID | str,
472
+ metadata: MetadataInput,
473
+ limit: int,
474
+ offset: int,
475
+ ctx: Any = None,
476
+ ) -> AsyncIterator[Assistant]: # type: ignore[return-value]
477
+ """Get all versions of assistant via gRPC."""
478
+ # Handle auth filters
479
+ auth_filters = await Assistants.handle_event(
480
+ ctx,
481
+ "search",
482
+ {"assistant_id": str(assistant_id), "metadata": metadata},
483
+ )
484
+
485
+ # Build the gRPC request
486
+ request = pb.GetAssistantVersionsRequest(
487
+ assistant_id=str(assistant_id),
488
+ filters=auth_filters or {},
489
+ metadata=dict_to_struct(metadata or {}),
490
+ limit=limit,
491
+ offset=offset,
492
+ )
493
+
494
+ # Make the gRPC call
495
+ async with GrpcClient() as client:
496
+ response = await client.assistants.GetVersions(request)
497
+
498
+ # Convert and yield the results
499
+ async def generate_results():
500
+ for version in response.versions:
501
+ yield {
502
+ "assistant_id": version.assistant_id,
503
+ "graph_id": version.graph_id,
504
+ "version": version.version,
505
+ "created_at": version.created_at.ToDatetime(),
506
+ "config": struct_to_dict(version.config),
507
+ "context": struct_to_dict(version.context),
508
+ "metadata": struct_to_dict(version.metadata),
509
+ "name": version.name,
510
+ "description": version.description,
511
+ }
512
+
513
+ return generate_results()
514
+
515
+ @staticmethod
516
+ async def count(
517
+ conn, # Not used in gRPC implementation
518
+ *,
519
+ graph_id: str | None = None,
520
+ metadata: MetadataInput = None,
521
+ ctx: Any = None,
522
+ ) -> int: # type: ignore[return-value]
523
+ """Count assistants via gRPC."""
524
+ # Handle auth filters
525
+ auth_filters = await Assistants.handle_event(
526
+ ctx, "search", {"graph_id": graph_id, "metadata": metadata}
527
+ )
528
+
529
+ # Build the gRPC request
530
+ request = pb.CountAssistantsRequest(
531
+ filters=auth_filters or {},
532
+ graph_id=graph_id,
533
+ metadata=dict_to_struct(metadata or {}),
534
+ )
535
+
536
+ # Make the gRPC call
537
+ async with GrpcClient() as client:
538
+ response = await client.assistants.Count(request)
539
+
540
+ return int(response.count)
@@ -0,0 +1,47 @@
1
+ #!/bin/bash
2
+ # Generate Python protobuf files from core protos
3
+ # Run this from the api/langgraph_api/grpc_ops directory
4
+
5
+ set -e
6
+
7
+ # Get the project root (three levels up from api/langgraph_api/grpc_ops)
8
+ PROJECT_ROOT="$(cd ../../../ && pwd)"
9
+ PROTO_DIR="${PROJECT_ROOT}/core/protos"
10
+ OUTPUT_DIR="generated"
11
+
12
+ # Check if proto file exists
13
+ if [[ ! -f "${PROTO_DIR}/core-api.proto" ]]; then
14
+ echo "Error: Proto file not found at ${PROTO_DIR}/core-api.proto"
15
+ exit 1
16
+ fi
17
+
18
+ # Create output directory if it doesn't exist
19
+ mkdir -p "${OUTPUT_DIR}"
20
+
21
+ # Generate Python protobuf files
22
+ echo "Generating Python protobuf files..."
23
+ uv run python -m grpc_tools.protoc \
24
+ -I"${PROTO_DIR}" \
25
+ --python_out="${OUTPUT_DIR}" \
26
+ --grpc_python_out="${OUTPUT_DIR}" \
27
+ --pyi_out="${OUTPUT_DIR}" \
28
+ "${PROTO_DIR}/core-api.proto"
29
+
30
+ # Fix imports to be relative in the generated gRPC file
31
+ echo "Fixing imports to be relative..."
32
+ if [[ -f "${OUTPUT_DIR}/core_api_pb2_grpc.py" ]]; then
33
+ # Make import of core_api_pb2 relative, preserving whatever alias grpc_tools chose
34
+ sed -i.bak 's/^import core_api_pb2 as /from . import core_api_pb2 as /' "${OUTPUT_DIR}/core_api_pb2_grpc.py"
35
+ rm -f "${OUTPUT_DIR}/core_api_pb2_grpc.py.bak"
36
+ fi
37
+
38
+ # Create __init__.py files
39
+ cat > "${OUTPUT_DIR}/__init__.py" << 'EOF'
40
+ # Generated protobuf files
41
+ from . import core_api_pb2
42
+ from . import core_api_pb2_grpc
43
+
44
+ __all__ = ["core_api_pb2", "core_api_pb2_grpc"]
45
+ EOF
46
+
47
+ echo "Python protobuf files generated successfully!"
langgraph_api/schema.py CHANGED
@@ -62,7 +62,7 @@ class Checkpoint(TypedDict):
62
62
  checkpoint_map: dict[str, Any] | None
63
63
 
64
64
 
65
- class Assistant(TypedDict):
65
+ class Assistant(TypedDict, total=False):
66
66
  """Assistant model."""
67
67
 
68
68
  assistant_id: UUID
@@ -176,6 +176,7 @@ class RunKwargs(TypedDict):
176
176
  subgraphs: bool
177
177
  resumable: bool
178
178
  checkpoint_during: bool
179
+ durability: str | None
179
180
 
180
181
 
181
182
  class Run(TypedDict):
@@ -1,12 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-api
3
- Version: 0.4.28
3
+ Version: 0.4.29
4
4
  Author-email: Nuno Campos <nuno@langchain.dev>, Will Fu-Hinthorn <will@langchain.dev>
5
5
  License: Elastic-2.0
6
6
  License-File: LICENSE
7
7
  Requires-Python: >=3.11
8
8
  Requires-Dist: cloudpickle>=3.0.0
9
9
  Requires-Dist: cryptography<45.0,>=42.0.0
10
+ Requires-Dist: grpcio-tools<2.0.0,>=1.75.0
11
+ Requires-Dist: grpcio<2.0.0,>=1.75.0
10
12
  Requires-Dist: httpx>=0.25.0
11
13
  Requires-Dist: jsonschema-rs<0.30,>=0.20.0
12
14
  Requires-Dist: langchain-core>=0.3.64
@@ -16,6 +18,7 @@ Requires-Dist: langgraph-sdk>=0.2.0
16
18
  Requires-Dist: langgraph>=0.4.0
17
19
  Requires-Dist: langsmith>=0.3.45
18
20
  Requires-Dist: orjson>=3.9.7
21
+ Requires-Dist: protobuf<7.0.0,>=6.32.1
19
22
  Requires-Dist: pyjwt>=2.9.0
20
23
  Requires-Dist: sse-starlette<2.2.0,>=2.1.0
21
24
  Requires-Dist: starlette>=0.38.6
@@ -1,4 +1,4 @@
1
- langgraph_api/__init__.py,sha256=QZ0p7EqvqxpClz_YH3XtlxgPmyXKcK-CGg_B_p5Z7w0,23
1
+ langgraph_api/__init__.py,sha256=LtSKwkqgueDQK6uLnhs8HgKylJHH36EMo48UDeHgv2Y,23
2
2
  langgraph_api/asgi_transport.py,sha256=XtiLOu4WWsd-xizagBLzT5xUkxc9ZG9YqwvETBPjBFE,5161
3
3
  langgraph_api/asyncio.py,sha256=FEEkLm_N-15cbElo4vQ309MkDKBZuRqAYV8VJ1DocNw,9860
4
4
  langgraph_api/cli.py,sha256=o_zD2vkky06dzW87HQgkIR1_h3ZCSZ8tgNvFCK9rKVo,19669
@@ -7,8 +7,8 @@ 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
10
- langgraph_api/feature_flags.py,sha256=x28NwFJXdfuGW2uUmon6lBSh0pGBo27bw_Se72TO4sM,409
11
- langgraph_api/graph.py,sha256=h1m6rsLiCocvMO283LLU03A5cBycxAIxixXu9mwzqsQ,25056
10
+ langgraph_api/feature_flags.py,sha256=taZRhukeBV8r62EmEo92rxfBwYhIw56-P_UvSzQLzt8,576
11
+ langgraph_api/graph.py,sha256=u10F9a8dxi7_Shx42xHOPi1Ri0occU6lUhWnTAF8_K4,25081
12
12
  langgraph_api/http.py,sha256=fyK-H-0UfNy_BzuVW3aWWGvhRavmGAVMkDwDArryJ_4,5659
13
13
  langgraph_api/http_metrics.py,sha256=MU9ccXt7aBb0AJ2SWEjwtbtbJEWmeqSdx7-CI51e32o,5594
14
14
  langgraph_api/logging.py,sha256=qB6q_cUba31edE4_D6dBGhdiUTpW7sXAOepUjYb_R50,5216
@@ -16,7 +16,7 @@ langgraph_api/metadata.py,sha256=0eGYhXOW6UIVDj2Y5mOdSJz_RadgJG8xmUsC9WqwsiE,834
16
16
  langgraph_api/patch.py,sha256=J0MmcfpZG15SUVaVcI0Z4x_c0-0rbbT7Pwh9fDAQOpA,1566
17
17
  langgraph_api/queue_entrypoint.py,sha256=k-Lz-HdaM2ICJacf9yCQw21GlJp00dPoHKuhe1PSrSs,6418
18
18
  langgraph_api/route.py,sha256=EBhELuJ1He-ZYcAnR5YTImcIeDtWthDae5CHELBxPkM,5056
19
- langgraph_api/schema.py,sha256=AsgF0dIjBvDd_PDy20mGqB_IkBLgVvSj8qRKG_lPlec,8440
19
+ langgraph_api/schema.py,sha256=spZ_XPT4AMJfw2YatsdnMZZLzgB9Sm3YR8n0SlgGdJ8,8480
20
20
  langgraph_api/serde.py,sha256=Jkww6ixP5o2YZmnXtM7ihuAYC6YSuNDNPvE-8ILoqVo,5499
21
21
  langgraph_api/server.py,sha256=C9TO7N0mzyrLulT_2FtaJfgfFbm2B4yyYTdAGPxgIeE,7255
22
22
  langgraph_api/sse.py,sha256=SLdtZmTdh5D8fbWrQjuY9HYLd2dg8Rmi6ZMmFMVc2iE,4204
@@ -30,7 +30,7 @@ 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
32
  langgraph_api/api/a2a.py,sha256=HIHZkLnIcM1u1FJti-L2NH-h1I9BZ_d-QW9z3gFonn8,53995
33
- langgraph_api/api/assistants.py,sha256=OX83GCWwGR8MuEJKIzAPEC4LC3Aghs5vD3NGLNnijaU,17268
33
+ langgraph_api/api/assistants.py,sha256=87FMcq8T4-7PfrAX1adOtBS_qQdomGOFpcFQw6PxZDA,17453
34
34
  langgraph_api/api/mcp.py,sha256=qe10ZRMN3f-Hli-9TI8nbQyWvMeBb72YB1PZVbyqBQw,14418
35
35
  langgraph_api/api/meta.py,sha256=Qyj6r5czkVJ81tpD6liFY7tlrmFDsiSfBr-4X8HJpRc,4834
36
36
  langgraph_api/api/openapi.py,sha256=If-z1ckXt-Yu5bwQytK1LWyX_T7G46UtLfixgEP8hwc,11959
@@ -46,6 +46,14 @@ langgraph_api/auth/studio_user.py,sha256=fojJpexdIZYI1w3awiqOLSwMUiK_M_3p4mlfQI0
46
46
  langgraph_api/auth/langsmith/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
47
  langgraph_api/auth/langsmith/backend.py,sha256=rdkz8IXLHusJqcoacvl2XuMZnQVR7PLpE0SHHcKTqv0,3664
48
48
  langgraph_api/auth/langsmith/client.py,sha256=Kn9503en1tmlNtkbvqRxYSRCOUrWaVpqvxyLLb1cgzY,3908
49
+ langgraph_api/grpc_ops/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
+ langgraph_api/grpc_ops/client.py,sha256=VB740C9QMhJJrpAEjsADmasN-uGd0apGYtuv_ho0Rl8,2452
51
+ langgraph_api/grpc_ops/ops.py,sha256=6xCWc5ylMcuTY_FFUJlnqPuRYOr0aOP96pXgx2X4I44,17139
52
+ langgraph_api/grpc_ops/generated/__init__.py,sha256=dRiB_iGscPKdMpuLp9ueLwAmIfRaNjNXC64ABtb4cg8,135
53
+ langgraph_api/grpc_ops/generated/core_api_pb2.py,sha256=5tvJCY00-ud-IO9OKIqRPEpUw12wjxYO3LQklMXB73o,42143
54
+ langgraph_api/grpc_ops/generated/core_api_pb2.pyi,sha256=cpbtS6nf3aaOnbBbAsyCinttxiVELmje7xf0AaRcYUM,49208
55
+ langgraph_api/grpc_ops/generated/core_api_pb2_grpc.py,sha256=fhlFCIrGpi3NPcyTcRsMQWXaw4Glr2-leMTyWiJer7M,52467
56
+ langgraph_api/grpc_ops/scripts/generate_protos.sh,sha256=hSf1vgS0MoTlavbaUjiDKOSujuJ1RRN19UL6HS24JY4,1486
49
57
  langgraph_api/js/.gitignore,sha256=l5yI6G_V6F1600I1IjiUKn87f4uYIrBAYU1MOyBBhg4,59
50
58
  langgraph_api/js/.prettierrc,sha256=0es3ovvyNIqIw81rPQsdt1zCQcOdBqyR_DMbFE4Ifms,19
51
59
  langgraph_api/js/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -99,8 +107,8 @@ langgraph_runtime/store.py,sha256=7mowndlsIroGHv3NpTSOZDJR0lCuaYMBoTnTrewjslw,11
99
107
  LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
100
108
  logging.json,sha256=3RNjSADZmDq38eHePMm1CbP6qZ71AmpBtLwCmKU9Zgo,379
101
109
  openapi.json,sha256=21wu-NxdxyTQwZctNcEfRkLMnSBi0QhGAfwq5kg8XNU,172618
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,,
110
+ langgraph_api-0.4.29.dist-info/METADATA,sha256=VFgEuF3tQk5UU_jlddc4WCwXsgPp7A9STteH1LyMLzg,4012
111
+ langgraph_api-0.4.29.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
112
+ langgraph_api-0.4.29.dist-info/entry_points.txt,sha256=hGedv8n7cgi41PypMfinwS_HfCwA7xJIfS0jAp8htV8,78
113
+ langgraph_api-0.4.29.dist-info/licenses/LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
114
+ langgraph_api-0.4.29.dist-info/RECORD,,