langgraph-executor 0.0.1a1__py3-none-any.whl → 0.0.1a3__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.
@@ -0,0 +1,497 @@
1
+ import asyncio
2
+ import contextlib
3
+ import functools
4
+ import logging
5
+ import uuid
6
+ from collections.abc import AsyncIterator, Callable, Collection, Iterator, Sequence
7
+ from typing import Any, Protocol, cast
8
+
9
+ import grpc
10
+ import grpc.aio
11
+ from google.protobuf.struct_pb2 import Struct # type: ignore[import-untyped]
12
+ from langchain_core.messages import BaseMessage, BaseMessageChunk
13
+ from langchain_core.runnables import RunnableConfig
14
+ from langgraph.checkpoint.base import Checkpoint
15
+ from langgraph.errors import GraphBubbleUp, GraphInterrupt
16
+ from langgraph.pregel import Pregel
17
+ from langgraph.pregel._algo import apply_writes
18
+ from langgraph.pregel._checkpoint import channels_from_checkpoint
19
+ from langgraph.pregel._retry import arun_with_retry
20
+ from langgraph.types import PregelExecutableTask
21
+
22
+ from langgraph_executor.common import (
23
+ checkpoint_to_proto,
24
+ exception_to_pb,
25
+ extract_channels,
26
+ pb_to_val,
27
+ reconstruct_channels,
28
+ reconstruct_checkpoint,
29
+ reconstruct_config,
30
+ reconstruct_task_writes,
31
+ updates_to_proto,
32
+ )
33
+ from langgraph_executor.execute_task import (
34
+ extract_writes,
35
+ reconstruct_task,
36
+ )
37
+ from langgraph_executor.extract_graph import extract_graph
38
+ from langgraph_executor.pb import executor_pb2, executor_pb2_grpc, types_pb2
39
+ from langgraph_executor.stream_utils import ExecutorStreamHandler
40
+
41
+
42
+ class Logger(Protocol):
43
+ def debug(self, msg: str, *args: Any, **kwargs: Any) -> None: ...
44
+ def info(self, msg: str, *args: Any, **kwargs: Any) -> None: ...
45
+ def warning(self, msg: str, *args: Any, **kwargs: Any) -> None: ...
46
+ def error(self, msg: str, *args: Any, **kwargs: Any) -> None: ...
47
+ def exception(self, msg: str, *args: Any, **kwargs: Any) -> None: ...
48
+ def critical(self, msg: str, *args: Any, **kwargs: Any) -> None: ...
49
+
50
+
51
+ LOGGER = logging.getLogger(__name__)
52
+ SENTINEL = cast(executor_pb2.ExecuteTaskResponse, object())
53
+ GetGraph = Callable[
54
+ [str, RunnableConfig], contextlib.AbstractAsyncContextManager[Pregel]
55
+ ]
56
+
57
+
58
+ class LangGraphExecutorServicer(executor_pb2_grpc.LangGraphExecutorServicer):
59
+ """gRPC servicer for LangGraph runtime execution operations."""
60
+
61
+ def __init__(
62
+ self,
63
+ graphs: Collection[str],
64
+ *,
65
+ subgraph_map: dict[str, str],
66
+ get_graph: GetGraph,
67
+ logger: Logger | None = None,
68
+ on_message: Callable[
69
+ [
70
+ BaseMessageChunk,
71
+ dict[str, Any],
72
+ ],
73
+ None,
74
+ ]
75
+ | None = None,
76
+ on_custom: Callable[[Any], None] | None = None,
77
+ ):
78
+ """Initialize the servicer with compiled graphs.
79
+
80
+ Args:
81
+ graphs: Dictionary mapping graph names to compiled graphs
82
+ subgraph_map: Dictionary mapping subgraph names to parent graph names
83
+ get_graph: Function to get a graph by name
84
+ logger: Optional logger
85
+
86
+ """
87
+ self.logger = logger or LOGGER
88
+ self.graphs = set(graphs)
89
+ self.graph_names = sorted(self.graphs)
90
+ self.subgraph_map = subgraph_map
91
+ self.get_graph = get_graph
92
+ _patch_base_message_with_ids()
93
+ self._graph_definition_cache: dict[str, executor_pb2.GetGraphResponse] = {}
94
+ self.on_message = on_message
95
+ self.on_custom = on_custom
96
+
97
+ async def ListGraphs(
98
+ self, request: Any, context: grpc.aio.ServicerContext
99
+ ) -> executor_pb2.ListGraphsResponse: # type: ignore[name-defined]
100
+ """List available graphs."""
101
+ return executor_pb2.ListGraphsResponse(
102
+ graph_names=self.graph_names,
103
+ )
104
+
105
+ async def GetGraph(
106
+ self, request: Any, context: grpc.aio.ServicerContext
107
+ ) -> executor_pb2.GetGraphResponse: # type: ignore[name-defined]
108
+ """Get graph definition."""
109
+ try:
110
+ self.logger.debug("GetGraph called")
111
+ graph_name: str = request.graph_name
112
+ return await self._get_graph_definition(graph_name)
113
+
114
+ except Exception as e:
115
+ self.logger.error(f"GetGraph Error: {e}", exc_info=True)
116
+ await context.abort(grpc.StatusCode.INTERNAL, str(e))
117
+
118
+ async def _get_graph_definition(self, name: str) -> executor_pb2.GetGraphResponse:
119
+ if (resp := self._graph_definition_cache.get(name)) is not None:
120
+ return resp
121
+ async with self.get_graph(name, RunnableConfig()) as graph:
122
+ graph_definition = extract_graph(graph)
123
+
124
+ resp = executor_pb2.GetGraphResponse(
125
+ graph_definition=graph_definition,
126
+ parent_name=self.subgraph_map.get(name, None),
127
+ checkpointer=graph.checkpointer is not None,
128
+ )
129
+ self._graph_definition_cache[name] = resp
130
+ return resp
131
+
132
+ async def GetAllGraphs(
133
+ self,
134
+ request: executor_pb2.GetAllGraphsRequest,
135
+ context: grpc.aio.ServicerContext,
136
+ ) -> AsyncIterator[executor_pb2.GetGraphResponse]:
137
+ try:
138
+ self.logger.debug("GetAllGraphs called")
139
+ for name in self.graph_names:
140
+ yield await self._get_graph_definition(name)
141
+
142
+ except Exception as e:
143
+ self.logger.error(f"GetAllGraphs Error: {e}", exc_info=True)
144
+ await context.abort(grpc.StatusCode.INTERNAL, str(e))
145
+
146
+ async def ChannelsFromCheckpoint(
147
+ self, request: Any, context: grpc.aio.ServicerContext
148
+ ) -> executor_pb2.ChannelsFromCheckpointResponse: # type: ignore[name-defined]
149
+ try:
150
+ self.logger.debug("ChannelsFromCheckpoint called")
151
+ async with self.get_graph(request.graph_name, RunnableConfig()) as graph:
152
+ # reconstruct specs
153
+ specs, _ = reconstruct_channels(
154
+ request.specs.channels,
155
+ graph,
156
+ scratchpad=None, # type: ignore[invalid-arg-type]
157
+ )
158
+
159
+ # initialize channels from specs and checkpoint channel values
160
+ checkpoint_dummy = Checkpoint( # type: ignore[typeddict-item]
161
+ channel_values={
162
+ k: pb_to_val(v)
163
+ for k, v in request.checkpoint_channel_values.items()
164
+ },
165
+ )
166
+ channels, _ = channels_from_checkpoint(specs, checkpoint_dummy)
167
+
168
+ # channels to pb
169
+ channels = extract_channels(channels)
170
+
171
+ return executor_pb2.ChannelsFromCheckpointResponse(channels=channels)
172
+
173
+ except Exception as e:
174
+ self.logger.error(f"ChannelsFromCheckpoint Error: {e}", exc_info=True)
175
+ await context.abort(grpc.StatusCode.INTERNAL, str(e))
176
+
177
+ async def ExecuteTask(
178
+ self,
179
+ request_iterator: Iterator[executor_pb2.ExecuteTaskRequest], # type: ignore[name-defined]
180
+ context: grpc.aio.ServicerContext,
181
+ ) -> AsyncIterator[executor_pb2.ExecuteTaskResponse]: # type: ignore[name-defined]
182
+ self.logger.debug("ExecuteTask called")
183
+
184
+ # Right now, only handle task execution without interrupts, etc
185
+ try:
186
+ request = await _get_init_request(request_iterator)
187
+ config = reconstruct_config(request.task.config)
188
+ async with self.get_graph(request.graph_name, config) as graph:
189
+ stream_messages = "messages" in request.stream_modes
190
+ stream_custom = "custom" in request.stream_modes
191
+
192
+ stream_queue = asyncio.Queue()
193
+
194
+ custom_stream_writer = (
195
+ _create_custom_stream_writer(
196
+ stream_queue, self.logger, on_custom=self.on_custom
197
+ )
198
+ if stream_custom
199
+ else None
200
+ )
201
+
202
+ task = reconstruct_task(
203
+ request, graph, custom_stream_writer=custom_stream_writer
204
+ )
205
+ if stream_messages:
206
+ # Create and inject callback handler
207
+ stream_handler = ExecutorStreamHandler(
208
+ functools.partial(
209
+ stream_callback,
210
+ logger=self.logger,
211
+ stream_queue=stream_queue,
212
+ on_message=self.on_message,
213
+ ),
214
+ task.id,
215
+ )
216
+
217
+ # Add handler to task config callbacks
218
+ if "callbacks" not in task.config:
219
+ task.config["callbacks"] = []
220
+ task.config["callbacks"].append(stream_handler) # type: ignore[union-attr]
221
+
222
+ # Execute task, catching interrupts
223
+ # Check cache if task has cache key - send request to Go orchestrator
224
+ should_execute = True
225
+ if task.cache_key:
226
+ self.logger.debug(
227
+ f"Task {task.id} has cache key, sending cache check request to Go",
228
+ )
229
+
230
+ # Send cache check request to Go runtime
231
+ cache_check_request = executor_pb2.CacheCheckRequest(
232
+ cache_namespace=list(task.cache_key.ns),
233
+ cache_key=task.cache_key.key,
234
+ ttl=task.cache_key.ttl,
235
+ )
236
+
237
+ yield executor_pb2.ExecuteTaskResponse(
238
+ cache_check_request=cache_check_request,
239
+ )
240
+
241
+ # Wait for Go's response via the bidirectional stream
242
+ try:
243
+ cache_response_request = next(request_iterator)
244
+ if hasattr(cache_response_request, "cache_check_response"):
245
+ cache_response = cache_response_request.cache_check_response
246
+ should_execute = not cache_response.cache_hit
247
+ self.logger.debug(
248
+ f"Received cache response for task {task.id}: cache_hit={cache_response.cache_hit}",
249
+ )
250
+ else:
251
+ self.logger.warning(
252
+ f"Expected cache_check_response for task {task.id}, got unexpected message type",
253
+ )
254
+ should_execute = (
255
+ True # Default to execution if unexpected response
256
+ )
257
+ except StopIteration:
258
+ self.logger.warning(
259
+ f"No cache response received for task {task.id}, defaulting to execution",
260
+ )
261
+ should_execute = True # Default to execution if no response
262
+
263
+ # TODO patch retry policy
264
+ # TODO configurable to deal with _call and the functional api
265
+ exception_pb = None
266
+ if should_execute:
267
+ runner_task = asyncio.create_task(
268
+ _run_task(task, logger=self.logger, stream_queue=stream_queue)
269
+ )
270
+ # Drain the queue and stream responses to client
271
+ while True:
272
+ item = await stream_queue.get()
273
+ if item is SENTINEL:
274
+ break
275
+ yield item
276
+ exception_pb = await runner_task
277
+
278
+ # Ensure the final chat messages are emitted (if any)
279
+ final_messages = _extract_output_messages(task.writes)
280
+ if final_messages:
281
+ for message in final_messages:
282
+ yield executor_pb2.ExecuteTaskResponse(
283
+ message_or_message_chunk=message
284
+ )
285
+
286
+ # Final task result
287
+ yield executor_pb2.ExecuteTaskResponse(
288
+ task_result=executor_pb2.TaskResult(
289
+ error=exception_pb, writes=extract_writes(task.writes)
290
+ )
291
+ )
292
+
293
+ except Exception as e:
294
+ self.logger.exception(f"ExecuteTask error: {e}")
295
+ await context.abort(grpc.StatusCode.INTERNAL, str(e))
296
+
297
+ async def ApplyWrites(
298
+ self, request: Any, context: grpc.aio.ServicerContext
299
+ ) -> executor_pb2.ApplyWritesResponse: # type: ignore[name-defined]
300
+ # get graph
301
+ self.logger.debug("ApplyWrites called")
302
+ try:
303
+ async with self.get_graph(request.graph_name, RunnableConfig()) as graph:
304
+ channels, _ = reconstruct_channels(
305
+ request.channels.channels,
306
+ graph,
307
+ # TODO: figure this out
308
+ scratchpad=None, # type: ignore[invalid-arg-type]
309
+ )
310
+ checkpoint = reconstruct_checkpoint(request.checkpoint)
311
+ tasks = reconstruct_task_writes(request.tasks)
312
+
313
+ # apply writes
314
+ updated_channel_names_set = apply_writes(
315
+ checkpoint,
316
+ channels,
317
+ tasks,
318
+ lambda *args: request.next_version,
319
+ graph.trigger_to_nodes,
320
+ )
321
+ updated_channel_names = list(updated_channel_names_set)
322
+
323
+ # Reconstruct protos
324
+ updated_channels = extract_channels(channels)
325
+ checkpoint_proto = checkpoint_to_proto(checkpoint)
326
+
327
+ # Respond with updates
328
+ return executor_pb2.ApplyWritesResponse(
329
+ updates=updates_to_proto(
330
+ checkpoint_proto,
331
+ updated_channel_names,
332
+ updated_channels,
333
+ ),
334
+ )
335
+
336
+ except Exception as e:
337
+ self.logger.exception(f"ApplyWrites error: {e}")
338
+ await context.abort(grpc.StatusCode.INTERNAL, str(e))
339
+
340
+ async def GenerateCacheKey(
341
+ self,
342
+ request: executor_pb2.GenerateCacheKeyRequest,
343
+ context: grpc.aio.ServicerContext,
344
+ ) -> executor_pb2.GenerateCacheKeyResponse:
345
+ """Generate cache key for a node execution"""
346
+ raise NotImplementedError("GenerateCacheKey not implemented")
347
+
348
+
349
+ # Helpers
350
+
351
+
352
+ async def _run_task(
353
+ task: PregelExecutableTask,
354
+ *,
355
+ logger: Logger,
356
+ stream_queue: asyncio.Queue[executor_pb2.ExecuteTaskResponse],
357
+ ) -> types_pb2.ExecutorError | None:
358
+ try:
359
+ await arun_with_retry(
360
+ task,
361
+ retry_policy=None,
362
+ )
363
+
364
+ except Exception as e:
365
+ if isinstance(e, GraphBubbleUp | GraphInterrupt):
366
+ logger.info(f"Interrupt in task {task.id}: {e}")
367
+ else:
368
+ logger.exception(
369
+ f"Exception running task {task.id}: {e}\nTask: {task}\n\n",
370
+ exc_info=True,
371
+ )
372
+ return exception_to_pb(e)
373
+ finally:
374
+ await stream_queue.put(SENTINEL)
375
+
376
+
377
+ def stream_callback(
378
+ message: BaseMessageChunk,
379
+ metadata: dict[str, Any],
380
+ *,
381
+ logger: Logger,
382
+ stream_queue: asyncio.Queue[executor_pb2.ExecuteTaskResponse],
383
+ on_message: Callable[[BaseMessageChunk, dict[str, Any]], None] | None = None,
384
+ ):
385
+ """Callback to capture stream chunks and queue them."""
386
+ try:
387
+ if on_message is not None:
388
+ on_message(message, metadata)
389
+ stream_queue.put_nowait(
390
+ executor_pb2.ExecuteTaskResponse(
391
+ message_or_message_chunk=_extract_output_message(message)
392
+ )
393
+ )
394
+ except Exception as e:
395
+ logger.warning(f"Failed to create stream chunk: {e}", exc_info=True)
396
+
397
+
398
+ def _create_custom_stream_writer(
399
+ stream_queue: asyncio.Queue[Any],
400
+ logger: Logger,
401
+ *,
402
+ on_custom: Callable[[Any], None] | None = None,
403
+ ):
404
+ """Create a proper stream_writer function for custom mode (like langgraph does)."""
405
+
406
+ def stream_writer(content):
407
+ """Custom stream writer that creates CustomStreamEvent messages."""
408
+ try:
409
+ if on_custom is not None:
410
+ on_custom(content)
411
+ # Create payload struct (like langgraph does)
412
+ payload = Struct()
413
+ if isinstance(content, str):
414
+ payload.update({"content": content})
415
+ elif isinstance(content, dict):
416
+ payload.update(content)
417
+ else:
418
+ payload.update({"content": str(content)})
419
+
420
+ # Create CustomStreamEvent
421
+ custom_event = executor_pb2.CustomStreamEvent(payload=payload)
422
+ custom_event_response = executor_pb2.ExecuteTaskResponse(
423
+ custom_stream_event=custom_event
424
+ )
425
+ stream_queue.put_nowait(custom_event_response)
426
+
427
+ except Exception as e:
428
+ logger.warning(f"Failed to create custom stream event: {e}", exc_info=True)
429
+
430
+ return stream_writer
431
+
432
+
433
+ def _extract_output_messages(writes: Sequence[Any]) -> list[types_pb2.Message]: # type: ignore[name-defined]
434
+ messages = []
435
+ for write in writes:
436
+ # Not sure this check is right
437
+ if isinstance(write[1], BaseMessage):
438
+ messages.append(_extract_output_message(write[1]))
439
+ elif isinstance(write[1], Sequence):
440
+ messages.extend(
441
+ [
442
+ _extract_output_message(w)
443
+ for w in write[1]
444
+ if isinstance(w, BaseMessage)
445
+ ]
446
+ )
447
+
448
+ return messages
449
+
450
+
451
+ def _extract_output_message(write: Any) -> types_pb2.Message: # type: ignore[name-defined]
452
+ message = Struct()
453
+ message.update(
454
+ {
455
+ "is_streaming_chunk": False,
456
+ "message": {
457
+ "id": getattr(write, "id", None) or uuid.uuid4().hex,
458
+ "type": getattr(write, "type", None),
459
+ "content": str(getattr(write, "content", "") or ""),
460
+ "additional_kwargs": getattr(write, "additional_kwargs", {}),
461
+ "usage_metadata": getattr(write, "usage_metadata", {}),
462
+ "tool_calls": getattr(write, "tool_calls", []),
463
+ "tool_call_id": getattr(write, "tool_call_id", ""),
464
+ "tool_call_chunks": getattr(write, "tool_call_chunks", []),
465
+ "response_metadata": getattr(write, "response_metadata", {}),
466
+ },
467
+ "metadata": {},
468
+ }
469
+ )
470
+ return types_pb2.Message(payload=message)
471
+
472
+
473
+ async def _get_init_request(request_iterator):
474
+ request = await anext(request_iterator)
475
+
476
+ if not hasattr(request, "init"):
477
+ raise ValueError("First message must be init")
478
+
479
+ return request.init
480
+
481
+
482
+ @functools.lru_cache(maxsize=1)
483
+ def _patch_base_message_with_ids() -> None:
484
+ """Patch the specific BaseMessage class used in your system."""
485
+ try:
486
+ from langchain_core.messages import BaseMessage
487
+
488
+ original_init = BaseMessage.__init__
489
+
490
+ def patched_init(self, content: Any, **kwargs: Any) -> None:
491
+ original_init(self, content, **kwargs)
492
+ if self.id is None:
493
+ self.id = str(uuid.uuid4())
494
+
495
+ BaseMessage.__init__ = patched_init # type: ignore[method-assign]
496
+ except Exception as e:
497
+ LOGGER.warning("Failed to patch BaseMessage with IDs: %s", e)
@@ -8,7 +8,7 @@ from pathlib import Path
8
8
  class ExecutorInfo:
9
9
  id: str
10
10
  pid: int
11
- port: int
11
+ address: str
12
12
  status: str
13
13
  start_time: float
14
14
  end_time: float | None = None
@@ -33,7 +33,7 @@ class ExecutorInfoLogger:
33
33
  data = {
34
34
  "id": executor_info.id,
35
35
  "pid": executor_info.pid,
36
- "port": executor_info.port,
36
+ "address": executor_info.address,
37
37
  "status": executor_info.status,
38
38
  "start_time": executor_info.start_time,
39
39
  "end_time": executor_info.end_time,
@@ -61,7 +61,7 @@ class ExecutorInfoLogger:
61
61
  return ExecutorInfo(
62
62
  id=data["id"],
63
63
  pid=data["pid"],
64
- port=data["port"],
64
+ address=data["address"],
65
65
  status=data["status"],
66
66
  start_time=data["start_time"],
67
67
  end_time=data.get("end_time"),
@@ -27,7 +27,7 @@ from . import graph_pb2 as graph__pb2
27
27
  from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2
28
28
 
29
29
 
30
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0e\x65xecutor.proto\x12\x08\x65xecutor\x1a\x0btypes.proto\x1a\x0bgraph.proto\x1a\x1cgoogle/protobuf/struct.proto\"\x13\n\x11ListGraphsRequest\")\n\x12ListGraphsResponse\x12\x13\n\x0bgraph_names\x18\x01 \x03(\t\"%\n\x0fGetGraphRequest\x12\x12\n\ngraph_name\x18\x01 \x01(\t\"D\n\x10GetGraphResponse\x12\x30\n\x10graph_definition\x18\x01 \x01(\x0b\x32\x16.graph.GraphDefinition\"\x8a\x02\n\x1d\x43hannelsFromCheckpointRequest\x12\x12\n\ngraph_name\x18\x01 \x01(\t\x12\x1e\n\x05specs\x18\x02 \x01(\x0b\x32\x0f.types.Channels\x12g\n\x19\x63heckpoint_channel_values\x18\x03 \x03(\x0b\x32\x44.executor.ChannelsFromCheckpointRequest.CheckpointChannelValuesEntry\x1aL\n\x1c\x43heckpointChannelValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.types.Value:\x02\x38\x01\"C\n\x1e\x43hannelsFromCheckpointResponse\x12!\n\x08\x63hannels\x18\x01 \x01(\x0b\x32\x0f.types.Channels\"\x88\x01\n\x12\x45xecuteTaskRequest\x12)\n\x04init\x18\x01 \x01(\x0b\x32\x19.executor.ExecuteTaskInitH\x00\x12<\n\x14\x63\x61\x63he_check_response\x18\x02 \x01(\x0b\x32\x1c.executor.CacheCheckResponseH\x00\x42\t\n\x07message\"\xd6\x01\n\x0f\x45xecuteTaskInit\x12\x19\n\x04task\x18\x01 \x01(\x0b\x32\x0b.types.Task\x12!\n\x08\x63hannels\x18\x02 \x01(\x0b\x32\x0f.types.Channels\x12\x14\n\x0cstream_modes\x18\x03 \x03(\t\x12\x0c\n\x04step\x18\x04 \x01(\x05\x12\x15\n\rcheckpoint_ns\x18\x05 \x03(\t\x12\x13\n\x0boutput_keys\x18\x06 \x03(\t\x12\x13\n\x0bstream_keys\x18\x07 \x03(\t\x12\x12\n\ngraph_name\x18\x08 \x01(\t\x12\x0c\n\x04stop\x18\t \x01(\x05\"\xf9\x01\n\x13\x45xecuteTaskResponse\x12+\n\x0btask_result\x18\x01 \x01(\x0b\x32\x14.executor.TaskResultH\x00\x12\x32\n\x18message_or_message_chunk\x18\x02 \x01(\x0b\x32\x0e.types.MessageH\x00\x12:\n\x13\x63\x61\x63he_check_request\x18\x03 \x01(\x0b\x32\x1b.executor.CacheCheckRequestH\x00\x12:\n\x13\x63ustom_stream_event\x18\x04 \x01(\x0b\x32\x1b.executor.CustomStreamEventH\x00\x42\t\n\x07message\"^\n\nTaskResult\x12(\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x14.types.ExecutorErrorH\x00\x88\x01\x01\x12\x1c\n\x06writes\x18\x02 \x03(\x0b\x32\x0c.types.WriteB\x08\n\x06_error\"=\n\x11\x43ustomStreamEvent\x12(\n\x07payload\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\"\xa4\x01\n\x12\x41pplyWritesRequest\x12%\n\ncheckpoint\x18\x01 \x01(\x0b\x32\x11.types.Checkpoint\x12!\n\x08\x63hannels\x18\x02 \x01(\x0b\x32\x0f.types.Channels\x12\x1a\n\x05tasks\x18\x03 \x03(\x0b\x32\x0b.types.Task\x12\x14\n\x0cnext_version\x18\x04 \x01(\t\x12\x12\n\ngraph_name\x18\x05 \x01(\t\"b\n\x13\x41pplyWritesResponse\x12!\n\x07updates\x18\x01 \x01(\x0b\x32\x0e.types.UpdatesH\x00\x12\x1d\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x0c.types.ValueH\x00\x42\t\n\x07message\"\xc8\x01\n\x17GenerateCacheKeyRequest\x12\x11\n\tnode_name\x18\x01 \x01(\t\x12\x16\n\x0einput_channels\x18\x02 \x03(\t\x12L\n\x0e\x63hannel_values\x18\x03 \x03(\x0b\x32\x34.executor.GenerateCacheKeyRequest.ChannelValuesEntry\x1a\x34\n\x12\x43hannelValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"-\n\x18GenerateCacheKeyResponse\x12\x11\n\tcache_key\x18\x01 \x01(\t\"Y\n\x11\x43\x61\x63heCheckRequest\x12\x17\n\x0f\x63\x61\x63he_namespace\x18\x01 \x03(\t\x12\x11\n\tcache_key\x18\x02 \x01(\t\x12\x10\n\x03ttl\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x06\n\x04_ttl\"\'\n\x12\x43\x61\x63heCheckResponse\x12\x11\n\tcache_hit\x18\x01 \x01(\x08\x32\x83\x04\n\x11LangGraphExecutor\x12G\n\nListGraphs\x12\x1b.executor.ListGraphsRequest\x1a\x1c.executor.ListGraphsResponse\x12\x41\n\x08GetGraph\x12\x19.executor.GetGraphRequest\x1a\x1a.executor.GetGraphResponse\x12k\n\x16\x43hannelsFromCheckpoint\x12\'.executor.ChannelsFromCheckpointRequest\x1a(.executor.ChannelsFromCheckpointResponse\x12N\n\x0b\x45xecuteTask\x12\x1c.executor.ExecuteTaskRequest\x1a\x1d.executor.ExecuteTaskResponse(\x01\x30\x01\x12J\n\x0b\x41pplyWrites\x12\x1c.executor.ApplyWritesRequest\x1a\x1d.executor.ApplyWritesResponse\x12Y\n\x10GenerateCacheKey\x12!.executor.GenerateCacheKeyRequest\x1a\".executor.GenerateCacheKeyResponseB1Z/github.com/langchain-ai/langgraph-go/runtime/pbb\x06proto3')
30
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0e\x65xecutor.proto\x12\x08\x65xecutor\x1a\x0btypes.proto\x1a\x0bgraph.proto\x1a\x1cgoogle/protobuf/struct.proto\"\x13\n\x11ListGraphsRequest\")\n\x12ListGraphsResponse\x12\x13\n\x0bgraph_names\x18\x01 \x03(\t\"%\n\x0fGetGraphRequest\x12\x12\n\ngraph_name\x18\x01 \x01(\t\"\x9a\x01\n\x10GetGraphResponse\x12\x30\n\x10graph_definition\x18\x01 \x01(\x0b\x32\x16.graph.GraphDefinition\x12\x18\n\x0bparent_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0c\x63heckpointer\x18\x03 \x01(\x08H\x01\x88\x01\x01\x42\x0e\n\x0c_parent_nameB\x0f\n\r_checkpointer\"\x15\n\x13GetAllGraphsRequest\"\x8a\x02\n\x1d\x43hannelsFromCheckpointRequest\x12\x12\n\ngraph_name\x18\x01 \x01(\t\x12\x1e\n\x05specs\x18\x02 \x01(\x0b\x32\x0f.types.Channels\x12g\n\x19\x63heckpoint_channel_values\x18\x03 \x03(\x0b\x32\x44.executor.ChannelsFromCheckpointRequest.CheckpointChannelValuesEntry\x1aL\n\x1c\x43heckpointChannelValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x1b\n\x05value\x18\x02 \x01(\x0b\x32\x0c.types.Value:\x02\x38\x01\"C\n\x1e\x43hannelsFromCheckpointResponse\x12!\n\x08\x63hannels\x18\x01 \x01(\x0b\x32\x0f.types.Channels\"\x88\x01\n\x12\x45xecuteTaskRequest\x12)\n\x04init\x18\x01 \x01(\x0b\x32\x19.executor.ExecuteTaskInitH\x00\x12<\n\x14\x63\x61\x63he_check_response\x18\x02 \x01(\x0b\x32\x1c.executor.CacheCheckResponseH\x00\x42\t\n\x07message\"\xd6\x01\n\x0f\x45xecuteTaskInit\x12\x19\n\x04task\x18\x01 \x01(\x0b\x32\x0b.types.Task\x12!\n\x08\x63hannels\x18\x02 \x01(\x0b\x32\x0f.types.Channels\x12\x14\n\x0cstream_modes\x18\x03 \x03(\t\x12\x0c\n\x04step\x18\x04 \x01(\x05\x12\x15\n\rcheckpoint_ns\x18\x05 \x03(\t\x12\x13\n\x0boutput_keys\x18\x06 \x03(\t\x12\x13\n\x0bstream_keys\x18\x07 \x03(\t\x12\x12\n\ngraph_name\x18\x08 \x01(\t\x12\x0c\n\x04stop\x18\t \x01(\x05\"\xf9\x01\n\x13\x45xecuteTaskResponse\x12+\n\x0btask_result\x18\x01 \x01(\x0b\x32\x14.executor.TaskResultH\x00\x12\x32\n\x18message_or_message_chunk\x18\x02 \x01(\x0b\x32\x0e.types.MessageH\x00\x12:\n\x13\x63\x61\x63he_check_request\x18\x03 \x01(\x0b\x32\x1b.executor.CacheCheckRequestH\x00\x12:\n\x13\x63ustom_stream_event\x18\x04 \x01(\x0b\x32\x1b.executor.CustomStreamEventH\x00\x42\t\n\x07message\"^\n\nTaskResult\x12(\n\x05\x65rror\x18\x01 \x01(\x0b\x32\x14.types.ExecutorErrorH\x00\x88\x01\x01\x12\x1c\n\x06writes\x18\x02 \x03(\x0b\x32\x0c.types.WriteB\x08\n\x06_error\"=\n\x11\x43ustomStreamEvent\x12(\n\x07payload\x18\x01 \x01(\x0b\x32\x17.google.protobuf.Struct\"\xa4\x01\n\x12\x41pplyWritesRequest\x12%\n\ncheckpoint\x18\x01 \x01(\x0b\x32\x11.types.Checkpoint\x12!\n\x08\x63hannels\x18\x02 \x01(\x0b\x32\x0f.types.Channels\x12\x1a\n\x05tasks\x18\x03 \x03(\x0b\x32\x0b.types.Task\x12\x14\n\x0cnext_version\x18\x04 \x01(\t\x12\x12\n\ngraph_name\x18\x05 \x01(\t\"b\n\x13\x41pplyWritesResponse\x12!\n\x07updates\x18\x01 \x01(\x0b\x32\x0e.types.UpdatesH\x00\x12\x1d\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x0c.types.ValueH\x00\x42\t\n\x07message\"\xc8\x01\n\x17GenerateCacheKeyRequest\x12\x11\n\tnode_name\x18\x01 \x01(\t\x12\x16\n\x0einput_channels\x18\x02 \x03(\t\x12L\n\x0e\x63hannel_values\x18\x03 \x03(\x0b\x32\x34.executor.GenerateCacheKeyRequest.ChannelValuesEntry\x1a\x34\n\x12\x43hannelValuesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c:\x02\x38\x01\"-\n\x18GenerateCacheKeyResponse\x12\x11\n\tcache_key\x18\x01 \x01(\t\"Y\n\x11\x43\x61\x63heCheckRequest\x12\x17\n\x0f\x63\x61\x63he_namespace\x18\x01 \x03(\t\x12\x11\n\tcache_key\x18\x02 \x01(\t\x12\x10\n\x03ttl\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x06\n\x04_ttl\"\'\n\x12\x43\x61\x63heCheckResponse\x12\x11\n\tcache_hit\x18\x01 \x01(\x08\x32\xd0\x04\n\x11LangGraphExecutor\x12G\n\nListGraphs\x12\x1b.executor.ListGraphsRequest\x1a\x1c.executor.ListGraphsResponse\x12\x41\n\x08GetGraph\x12\x19.executor.GetGraphRequest\x1a\x1a.executor.GetGraphResponse\x12K\n\x0cGetAllGraphs\x12\x1d.executor.GetAllGraphsRequest\x1a\x1a.executor.GetGraphResponse0\x01\x12k\n\x16\x43hannelsFromCheckpoint\x12\'.executor.ChannelsFromCheckpointRequest\x1a(.executor.ChannelsFromCheckpointResponse\x12N\n\x0b\x45xecuteTask\x12\x1c.executor.ExecuteTaskRequest\x1a\x1d.executor.ExecuteTaskResponse(\x01\x30\x01\x12J\n\x0b\x41pplyWrites\x12\x1c.executor.ApplyWritesRequest\x1a\x1d.executor.ApplyWritesResponse\x12Y\n\x10GenerateCacheKey\x12!.executor.GenerateCacheKeyRequest\x1a\".executor.GenerateCacheKeyResponseB1Z/github.com/langchain-ai/langgraph-go/runtime/pbb\x06proto3')
31
31
 
32
32
  _globals = globals()
33
33
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -45,38 +45,40 @@ if not _descriptor._USE_C_DESCRIPTORS:
45
45
  _globals['_LISTGRAPHSRESPONSE']._serialized_end=146
46
46
  _globals['_GETGRAPHREQUEST']._serialized_start=148
47
47
  _globals['_GETGRAPHREQUEST']._serialized_end=185
48
- _globals['_GETGRAPHRESPONSE']._serialized_start=187
49
- _globals['_GETGRAPHRESPONSE']._serialized_end=255
50
- _globals['_CHANNELSFROMCHECKPOINTREQUEST']._serialized_start=258
51
- _globals['_CHANNELSFROMCHECKPOINTREQUEST']._serialized_end=524
52
- _globals['_CHANNELSFROMCHECKPOINTREQUEST_CHECKPOINTCHANNELVALUESENTRY']._serialized_start=448
53
- _globals['_CHANNELSFROMCHECKPOINTREQUEST_CHECKPOINTCHANNELVALUESENTRY']._serialized_end=524
54
- _globals['_CHANNELSFROMCHECKPOINTRESPONSE']._serialized_start=526
55
- _globals['_CHANNELSFROMCHECKPOINTRESPONSE']._serialized_end=593
56
- _globals['_EXECUTETASKREQUEST']._serialized_start=596
57
- _globals['_EXECUTETASKREQUEST']._serialized_end=732
58
- _globals['_EXECUTETASKINIT']._serialized_start=735
59
- _globals['_EXECUTETASKINIT']._serialized_end=949
60
- _globals['_EXECUTETASKRESPONSE']._serialized_start=952
61
- _globals['_EXECUTETASKRESPONSE']._serialized_end=1201
62
- _globals['_TASKRESULT']._serialized_start=1203
63
- _globals['_TASKRESULT']._serialized_end=1297
64
- _globals['_CUSTOMSTREAMEVENT']._serialized_start=1299
65
- _globals['_CUSTOMSTREAMEVENT']._serialized_end=1360
66
- _globals['_APPLYWRITESREQUEST']._serialized_start=1363
67
- _globals['_APPLYWRITESREQUEST']._serialized_end=1527
68
- _globals['_APPLYWRITESRESPONSE']._serialized_start=1529
69
- _globals['_APPLYWRITESRESPONSE']._serialized_end=1627
70
- _globals['_GENERATECACHEKEYREQUEST']._serialized_start=1630
71
- _globals['_GENERATECACHEKEYREQUEST']._serialized_end=1830
72
- _globals['_GENERATECACHEKEYREQUEST_CHANNELVALUESENTRY']._serialized_start=1778
73
- _globals['_GENERATECACHEKEYREQUEST_CHANNELVALUESENTRY']._serialized_end=1830
74
- _globals['_GENERATECACHEKEYRESPONSE']._serialized_start=1832
75
- _globals['_GENERATECACHEKEYRESPONSE']._serialized_end=1877
76
- _globals['_CACHECHECKREQUEST']._serialized_start=1879
77
- _globals['_CACHECHECKREQUEST']._serialized_end=1968
78
- _globals['_CACHECHECKRESPONSE']._serialized_start=1970
79
- _globals['_CACHECHECKRESPONSE']._serialized_end=2009
80
- _globals['_LANGGRAPHEXECUTOR']._serialized_start=2012
81
- _globals['_LANGGRAPHEXECUTOR']._serialized_end=2527
48
+ _globals['_GETGRAPHRESPONSE']._serialized_start=188
49
+ _globals['_GETGRAPHRESPONSE']._serialized_end=342
50
+ _globals['_GETALLGRAPHSREQUEST']._serialized_start=344
51
+ _globals['_GETALLGRAPHSREQUEST']._serialized_end=365
52
+ _globals['_CHANNELSFROMCHECKPOINTREQUEST']._serialized_start=368
53
+ _globals['_CHANNELSFROMCHECKPOINTREQUEST']._serialized_end=634
54
+ _globals['_CHANNELSFROMCHECKPOINTREQUEST_CHECKPOINTCHANNELVALUESENTRY']._serialized_start=558
55
+ _globals['_CHANNELSFROMCHECKPOINTREQUEST_CHECKPOINTCHANNELVALUESENTRY']._serialized_end=634
56
+ _globals['_CHANNELSFROMCHECKPOINTRESPONSE']._serialized_start=636
57
+ _globals['_CHANNELSFROMCHECKPOINTRESPONSE']._serialized_end=703
58
+ _globals['_EXECUTETASKREQUEST']._serialized_start=706
59
+ _globals['_EXECUTETASKREQUEST']._serialized_end=842
60
+ _globals['_EXECUTETASKINIT']._serialized_start=845
61
+ _globals['_EXECUTETASKINIT']._serialized_end=1059
62
+ _globals['_EXECUTETASKRESPONSE']._serialized_start=1062
63
+ _globals['_EXECUTETASKRESPONSE']._serialized_end=1311
64
+ _globals['_TASKRESULT']._serialized_start=1313
65
+ _globals['_TASKRESULT']._serialized_end=1407
66
+ _globals['_CUSTOMSTREAMEVENT']._serialized_start=1409
67
+ _globals['_CUSTOMSTREAMEVENT']._serialized_end=1470
68
+ _globals['_APPLYWRITESREQUEST']._serialized_start=1473
69
+ _globals['_APPLYWRITESREQUEST']._serialized_end=1637
70
+ _globals['_APPLYWRITESRESPONSE']._serialized_start=1639
71
+ _globals['_APPLYWRITESRESPONSE']._serialized_end=1737
72
+ _globals['_GENERATECACHEKEYREQUEST']._serialized_start=1740
73
+ _globals['_GENERATECACHEKEYREQUEST']._serialized_end=1940
74
+ _globals['_GENERATECACHEKEYREQUEST_CHANNELVALUESENTRY']._serialized_start=1888
75
+ _globals['_GENERATECACHEKEYREQUEST_CHANNELVALUESENTRY']._serialized_end=1940
76
+ _globals['_GENERATECACHEKEYRESPONSE']._serialized_start=1942
77
+ _globals['_GENERATECACHEKEYRESPONSE']._serialized_end=1987
78
+ _globals['_CACHECHECKREQUEST']._serialized_start=1989
79
+ _globals['_CACHECHECKREQUEST']._serialized_end=2078
80
+ _globals['_CACHECHECKRESPONSE']._serialized_start=2080
81
+ _globals['_CACHECHECKRESPONSE']._serialized_end=2119
82
+ _globals['_LANGGRAPHEXECUTOR']._serialized_start=2122
83
+ _globals['_LANGGRAPHEXECUTOR']._serialized_end=2714
82
84
  # @@protoc_insertion_point(module_scope)
@@ -65,18 +65,40 @@ class GetGraphResponse(google.protobuf.message.Message):
65
65
  DESCRIPTOR: google.protobuf.descriptor.Descriptor
66
66
 
67
67
  GRAPH_DEFINITION_FIELD_NUMBER: builtins.int
68
+ PARENT_NAME_FIELD_NUMBER: builtins.int
69
+ CHECKPOINTER_FIELD_NUMBER: builtins.int
70
+ parent_name: builtins.str
71
+ checkpointer: builtins.bool
68
72
  @property
69
73
  def graph_definition(self) -> graph_pb2.GraphDefinition: ...
70
74
  def __init__(
71
75
  self,
72
76
  *,
73
77
  graph_definition: graph_pb2.GraphDefinition | None = ...,
78
+ parent_name: builtins.str | None = ...,
79
+ checkpointer: builtins.bool | None = ...,
74
80
  ) -> None: ...
75
- def HasField(self, field_name: typing.Literal["graph_definition", b"graph_definition"]) -> builtins.bool: ...
76
- def ClearField(self, field_name: typing.Literal["graph_definition", b"graph_definition"]) -> None: ...
81
+ def HasField(self, field_name: typing.Literal["_checkpointer", b"_checkpointer", "_parent_name", b"_parent_name", "checkpointer", b"checkpointer", "graph_definition", b"graph_definition", "parent_name", b"parent_name"]) -> builtins.bool: ...
82
+ def ClearField(self, field_name: typing.Literal["_checkpointer", b"_checkpointer", "_parent_name", b"_parent_name", "checkpointer", b"checkpointer", "graph_definition", b"graph_definition", "parent_name", b"parent_name"]) -> None: ...
83
+ @typing.overload
84
+ def WhichOneof(self, oneof_group: typing.Literal["_checkpointer", b"_checkpointer"]) -> typing.Literal["checkpointer"] | None: ...
85
+ @typing.overload
86
+ def WhichOneof(self, oneof_group: typing.Literal["_parent_name", b"_parent_name"]) -> typing.Literal["parent_name"] | None: ...
77
87
 
78
88
  global___GetGraphResponse = GetGraphResponse
79
89
 
90
+ @typing.final
91
+ class GetAllGraphsRequest(google.protobuf.message.Message):
92
+ """GetAllGraphs"""
93
+
94
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
95
+
96
+ def __init__(
97
+ self,
98
+ ) -> None: ...
99
+
100
+ global___GetAllGraphsRequest = GetAllGraphsRequest
101
+
80
102
  @typing.final
81
103
  class ChannelsFromCheckpointRequest(google.protobuf.message.Message):
82
104
  """GetChannelsFromCheckpoint"""