langgraph-executor 0.0.1a5__py3-none-any.whl → 0.0.1a6__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.
@@ -1,6 +1,7 @@
1
1
  import traceback
2
2
  from collections.abc import Mapping, Sequence
3
3
  from collections.abc import Sequence as SequenceType
4
+ from contextvars import ContextVar
4
5
  from typing import Any, cast
5
6
 
6
7
  from google.protobuf.json_format import MessageToDict
@@ -19,7 +20,12 @@ from langgraph._internal._constants import (
19
20
  from langgraph._internal._scratchpad import PregelScratchpad
20
21
  from langgraph._internal._typing import MISSING
21
22
  from langgraph.channels.base import BaseChannel, EmptyChannelError
22
- from langgraph.checkpoint.base import Checkpoint, PendingWrite
23
+ from langgraph.checkpoint.base import (
24
+ Checkpoint,
25
+ CheckpointMetadata,
26
+ CheckpointTuple,
27
+ PendingWrite,
28
+ )
23
29
  from langgraph.checkpoint.serde.jsonplus import JsonPlusSerializer
24
30
  from langgraph.errors import GraphBubbleUp, GraphInterrupt
25
31
  from langgraph.managed.base import ManagedValue, ManagedValueMapping
@@ -30,6 +36,10 @@ from langgraph.types import Command, Interrupt, Send
30
36
 
31
37
  from langgraph_executor.pb import types_pb2
32
38
 
39
+ var_child_runnable_config: ContextVar[RunnableConfig | None] = ContextVar(
40
+ "child_runnable_config", default=None
41
+ )
42
+
33
43
 
34
44
  def map_reserved_configurable(
35
45
  reserved_configurable: types_pb2.ReservedConfigurable,
@@ -108,13 +118,18 @@ def reconstruct_checkpoint(request_checkpoint: types_pb2.Checkpoint) -> Checkpoi
108
118
  versions_seen = {
109
119
  k: dict(v.channel_versions) for k, v in request_checkpoint.versions_seen.items()
110
120
  }
111
- # channel_values = unwrap_channel_values(request_checkpoint.channel_values)
121
+
122
+ channel_values = {}
123
+ if request_checkpoint.channel_values:
124
+ channel_values = {
125
+ k: pb_to_val(v) for k, v in request_checkpoint.channel_values.items()
126
+ }
112
127
 
113
128
  return Checkpoint(
114
129
  v=request_checkpoint.v,
115
130
  id=request_checkpoint.id,
116
131
  channel_versions=channel_versions,
117
- # channel_values=channel_values,
132
+ channel_values=channel_values,
118
133
  versions_seen=versions_seen,
119
134
  ts=request_checkpoint.ts,
120
135
  )
@@ -249,7 +264,8 @@ def command_to_pb(cmd: Command) -> types_pb2.Value:
249
264
  cmd_pb.graph = cmd.graph
250
265
  if cmd.update:
251
266
  if isinstance(cmd.update, dict):
252
- cmd_pb.update.update({k: val_to_pb(None, v) for k, v in cmd.update.items()})
267
+ for k, v in cmd.update.items():
268
+ cmd_pb.update[k].CopyFrom(val_to_pb(None, v))
253
269
  else:
254
270
  cmd_pb.update.update({"__root__": val_to_pb(None, cmd.update)})
255
271
  if cmd.resume:
@@ -393,3 +409,40 @@ def pb_to_pending_writes(
393
409
  return None
394
410
 
395
411
  return [(pw.task_id, pw.channel, pb_to_val(pw.value)) for pw in pb]
412
+
413
+
414
+ def reconstruct_pending_writes(
415
+ pb: SequenceType[types_pb2.PendingWrite],
416
+ ) -> list[PendingWrite] | None:
417
+ if not pb:
418
+ return None
419
+
420
+ return [(pw.task_id, pw.channel, pb_to_val(pw.value)) for pw in pb]
421
+
422
+
423
+ def reconstruct_checkpoint_tuple(
424
+ checkpoint_tuple_pb: types_pb2.CheckpointTuple,
425
+ ) -> CheckpointTuple | None:
426
+ if not checkpoint_tuple_pb:
427
+ return None
428
+
429
+ return CheckpointTuple(
430
+ config=reconstruct_config(checkpoint_tuple_pb.config),
431
+ checkpoint=reconstruct_checkpoint(checkpoint_tuple_pb.checkpoint),
432
+ metadata=reconstruct_checkpoint_metadata(checkpoint_tuple_pb.metadata),
433
+ parent_config=reconstruct_config(checkpoint_tuple_pb.parent_config),
434
+ pending_writes=reconstruct_pending_writes(checkpoint_tuple_pb.pending_writes),
435
+ )
436
+
437
+
438
+ def reconstruct_checkpoint_metadata(
439
+ metadata_pb: types_pb2.CheckpointMetadata,
440
+ ) -> CheckpointMetadata | None:
441
+ if not metadata_pb:
442
+ return None
443
+
444
+ return CheckpointMetadata(
445
+ source=metadata_pb.source,
446
+ step=metadata_pb.step,
447
+ parents=metadata_pb.parents,
448
+ )
@@ -16,8 +16,14 @@ from langgraph_executor.pb.executor_pb2_grpc import (
16
16
  # Internal helpers
17
17
  LOGGER = logging.getLogger(__name__)
18
18
 
19
+ DEFAULT_RUNTIME_ADDRESS = "127.0.0.1:50051"
19
20
 
20
- def create_server(graphs: dict[str, Pregel], address: str) -> grpc.aio.Server:
21
+
22
+ def create_server(
23
+ graphs: dict[str, Pregel],
24
+ address: str,
25
+ runtime_address: str = DEFAULT_RUNTIME_ADDRESS,
26
+ ) -> grpc.aio.Server:
21
27
  graphs, subgraph_map = _load_graphs(graphs)
22
28
  server = grpc.aio.server(
23
29
  # Be permissive: allow client pings without active RPCs and accept intervals
@@ -30,8 +36,16 @@ def create_server(graphs: dict[str, Pregel], address: str) -> grpc.aio.Server:
30
36
  ]
31
37
  )
32
38
  getter = functools.partial(get_graph, graphs=graphs)
39
+ # lazy connection, doesn't matter if runtime service is ready
40
+ # also thread-safe, so we can process multiple subgraphs concurrently
41
+ runtime_channel = grpc.insecure_channel(runtime_address)
33
42
  add_LangGraphExecutorServicer_to_server(
34
- LangGraphExecutorServicer(graphs, subgraph_map=subgraph_map, get_graph=getter),
43
+ LangGraphExecutorServicer(
44
+ graphs,
45
+ subgraph_map=subgraph_map,
46
+ get_graph=getter,
47
+ runtime_channel=runtime_channel,
48
+ ),
35
49
  server,
36
50
  )
37
51
  server.add_insecure_port(address)
@@ -55,14 +69,14 @@ def _load_graphs(graphs: dict[str, Pregel]) -> tuple[dict[str, Pregel], dict[str
55
69
 
56
70
  # Then, collect all subgraphs and mappings
57
71
  all_subgraphs: dict[str, Pregel] = {}
58
- subgraph_to_parent: dict[str, str] = {}
72
+ # subgraph_to_parent: dict[str, str] = {}
59
73
 
60
- for root_graph in graphs.values():
61
- subgraphs, mappings = _collect_subgraphs(root_graph, root_graph.name)
62
- all_subgraphs.update(subgraphs)
63
- subgraph_to_parent.update(mappings)
74
+ # for root_graph in graphs.values():
75
+ # subgraphs, mappings = _collect_subgraphs(root_graph, root_graph.name)
76
+ # all_subgraphs.update(subgraphs)
77
+ # subgraph_to_parent.update(mappings)
64
78
 
65
- subgraph_map.update(subgraph_to_parent)
79
+ # subgraph_map.update(subgraph_to_parent)
66
80
 
67
81
  # Now build self.graphs in hierarchical order (parents before children)
68
82
  for root_name in sorted(graphs.keys()):
@@ -3,6 +3,7 @@ import contextlib
3
3
  import functools
4
4
  import logging
5
5
  import uuid
6
+ from collections import deque
6
7
  from collections.abc import (
7
8
  AsyncIterator,
8
9
  Awaitable,
@@ -11,22 +12,36 @@ from collections.abc import (
11
12
  Iterator,
12
13
  Sequence,
13
14
  )
15
+ from functools import partial
14
16
  from typing import Any, Protocol, cast
15
17
 
16
18
  import grpc
17
19
  import grpc.aio
18
20
  from google.protobuf.struct_pb2 import Struct # type: ignore[import-untyped]
19
21
  from langchain_core.messages import BaseMessage, BaseMessageChunk
20
- from langchain_core.runnables import RunnableConfig
22
+ from langchain_core.runnables import RunnableConfig, RunnableSequence
23
+ from langgraph._internal._config import patch_config
24
+ from langgraph._internal._constants import (
25
+ CONFIG_KEY_READ,
26
+ CONFIG_KEY_SEND,
27
+ CONFIG_KEY_TASK_ID,
28
+ INTERRUPT,
29
+ )
21
30
  from langgraph.checkpoint.base import Checkpoint
22
- from langgraph.errors import GraphBubbleUp, GraphInterrupt
31
+ from langgraph.errors import GraphBubbleUp, GraphInterrupt, InvalidUpdateError
23
32
  from langgraph.pregel import Pregel
24
- from langgraph.pregel._algo import apply_writes
33
+ from langgraph.pregel._algo import (
34
+ PregelTaskWrites,
35
+ _scratchpad,
36
+ apply_writes,
37
+ local_read,
38
+ )
25
39
  from langgraph.pregel._checkpoint import channels_from_checkpoint
26
40
  from langgraph.pregel._retry import arun_with_retry
27
41
  from langgraph.store.base import BaseStore
28
42
  from langgraph.types import PregelExecutableTask
29
43
 
44
+ from langgraph_executor.client.patch import _patch_pregel
30
45
  from langgraph_executor.common import (
31
46
  checkpoint_to_proto,
32
47
  exception_to_pb,
@@ -37,6 +52,7 @@ from langgraph_executor.common import (
37
52
  reconstruct_config,
38
53
  reconstruct_task_writes,
39
54
  updates_to_proto,
55
+ var_child_runnable_config,
40
56
  )
41
57
  from langgraph_executor.execute_task import (
42
58
  extract_writes,
@@ -44,6 +60,7 @@ from langgraph_executor.execute_task import (
44
60
  )
45
61
  from langgraph_executor.extract_graph import extract_graph
46
62
  from langgraph_executor.pb import executor_pb2, executor_pb2_grpc, types_pb2
63
+ from langgraph_executor.pb.runtime_pb2_grpc import LangGraphRuntimeStub
47
64
  from langgraph_executor.stream_utils import ExecutorStreamHandler
48
65
 
49
66
 
@@ -72,6 +89,7 @@ class LangGraphExecutorServicer(executor_pb2_grpc.LangGraphExecutorServicer):
72
89
  *,
73
90
  subgraph_map: dict[str, str],
74
91
  get_graph: GetGraph,
92
+ runtime_channel: grpc.Channel | None = None,
75
93
  logger: Logger | None = None,
76
94
  on_message: Callable[
77
95
  [
@@ -98,7 +116,15 @@ class LangGraphExecutorServicer(executor_pb2_grpc.LangGraphExecutorServicer):
98
116
  self.graph_names = sorted(self.graphs)
99
117
  self.subgraph_map = subgraph_map
100
118
  self.get_graph = get_graph
119
+ self.runtime_channel = runtime_channel
120
+ self.runtime_client: LangGraphRuntimeStub | None = (
121
+ LangGraphRuntimeStub(runtime_channel)
122
+ if runtime_channel is not None
123
+ else None
124
+ )
101
125
  _patch_base_message_with_ids()
126
+ if self.runtime_client is not None:
127
+ _patch_pregel(self.runtime_client, self.logger)
102
128
  self._graph_definition_cache: dict[str, executor_pb2.GetGraphResponse] = {}
103
129
  self.on_message = on_message
104
130
  self.on_custom = on_custom
@@ -351,6 +377,66 @@ class LangGraphExecutorServicer(executor_pb2_grpc.LangGraphExecutorServicer):
351
377
  self.logger.exception(f"ApplyWrites error: {e}")
352
378
  await context.abort(grpc.StatusCode.INTERNAL, str(e))
353
379
 
380
+ async def StateUpdate(
381
+ self,
382
+ request: executor_pb2.StateUpdateRequest,
383
+ context: grpc.aio.ServicerContext,
384
+ ) -> executor_pb2.TaskResult | None:
385
+ self.logger.debug("StateUpdate called")
386
+
387
+ try:
388
+ async with self.get_graph(request.graph_name, RunnableConfig()) as graph:
389
+ config = reconstruct_config(request.config)
390
+ channels, managed = reconstruct_channels(
391
+ request.channels.channels,
392
+ graph,
393
+ scratchpad=None, # type: ignore[invalid-arg-type]
394
+ )
395
+ writes: deque[tuple[str, Any]] = deque()
396
+ writers = graph.nodes[request.node_name].flat_writers
397
+ if not writers:
398
+ raise InvalidUpdateError(f"Node {request.node_name} has no writers")
399
+ task = PregelTaskWrites((), request.node_name, writes, [INTERRUPT])
400
+ task_id = request.task_id
401
+
402
+ run = RunnableSequence(*writers) if len(writers) > 1 else writers[0]
403
+
404
+ input = pb_to_val(request.values)
405
+
406
+ run.invoke(
407
+ input,
408
+ patch_config(
409
+ config,
410
+ run_name=graph.name + "UpdateState",
411
+ configurable={
412
+ # deque.extend is thread-safe
413
+ CONFIG_KEY_SEND: writes.extend,
414
+ CONFIG_KEY_TASK_ID: task_id,
415
+ CONFIG_KEY_READ: partial(
416
+ local_read,
417
+ _scratchpad(
418
+ None,
419
+ [],
420
+ task_id,
421
+ "",
422
+ None,
423
+ request.step,
424
+ request.step + 2,
425
+ ),
426
+ channels,
427
+ managed,
428
+ task,
429
+ ),
430
+ },
431
+ ),
432
+ )
433
+
434
+ return executor_pb2.TaskResult(writes=extract_writes(task.writes))
435
+
436
+ except Exception as e:
437
+ self.logger.exception(f"StateUpdate error: {e}")
438
+ await context.abort(grpc.StatusCode.INTERNAL, str(e))
439
+
354
440
  async def GenerateCacheKey(
355
441
  self,
356
442
  request: executor_pb2.GenerateCacheKeyRequest,
@@ -369,6 +455,8 @@ async def _run_task(
369
455
  logger: Logger,
370
456
  stream_queue: asyncio.Queue[executor_pb2.ExecuteTaskResponse],
371
457
  ) -> types_pb2.ExecutorError | None:
458
+ # Set config
459
+ var_child_runnable_config.set(task.config)
372
460
  try:
373
461
  await arun_with_retry(
374
462
  task,
@@ -117,6 +117,18 @@ def extract_trigger_to_nodes(
117
117
  return trigger_map
118
118
 
119
119
 
120
+ def extract_string_or_slice(
121
+ val: str | Sequence[str] | None,
122
+ ) -> types_pb2.StringOrSlice | None:
123
+ if val is None:
124
+ return None
125
+ if isinstance(val, str):
126
+ return types_pb2.StringOrSlice(values=[val], is_string=True)
127
+ if isinstance(val, list):
128
+ return types_pb2.StringOrSlice(values=val, is_string=False)
129
+ raise NotImplementedError(f"Cannot extract field value {val} as string or slice")
130
+
131
+
120
132
  def extract_graph(graph: Pregel, name: str | None = None) -> graph_pb2.GraphDefinition:
121
133
  """Extract graph information from a compiled LangGraph graph.
122
134
 
@@ -134,13 +146,7 @@ def extract_graph(graph: Pregel, name: str | None = None) -> graph_pb2.GraphDefi
134
146
  else graph.stream_mode
135
147
  ),
136
148
  stream_eager=bool(graph.stream_eager),
137
- stream_channels=(
138
- [graph.stream_channels]
139
- if isinstance(graph.stream_channels, str)
140
- else list(graph.stream_channels)
141
- if graph.stream_channels
142
- else []
143
- ),
149
+ stream_channels=extract_string_or_slice(graph.stream_channels),
144
150
  step_timeout=float(graph.step_timeout) if graph.step_timeout else 0.0,
145
151
  debug=bool(graph.debug),
146
152
  # TODO retry policy
@@ -150,24 +156,11 @@ def extract_graph(graph: Pregel, name: str | None = None) -> graph_pb2.GraphDefi
150
156
  config=extract_config(graph.config) if graph.config else None,
151
157
  nodes=extract_nodes(graph.nodes),
152
158
  trigger_to_nodes=extract_trigger_to_nodes(graph.trigger_to_nodes),
159
+ stream_channels_asis=extract_string_or_slice(graph.stream_channels_asis),
160
+ input_channels=extract_string_or_slice(graph.input_channels),
161
+ output_channels=extract_string_or_slice(graph.output_channels),
153
162
  )
154
163
 
155
- # Set input_channels and input_channels_is_list flag based on type
156
- if isinstance(graph.input_channels, str):
157
- graph_def.input_channels.extend([graph.input_channels])
158
- graph_def.input_channels_is_list = False
159
- else:
160
- graph_def.input_channels.extend(graph.input_channels)
161
- graph_def.input_channels_is_list = True
162
-
163
- # Set output_channels and output_channels_is_list flag based on type
164
- if isinstance(graph.output_channels, str):
165
- graph_def.output_channels.extend([graph.output_channels])
166
- graph_def.output_channels_is_list = False
167
- else:
168
- graph_def.output_channels.extend(graph.output_channels)
169
- graph_def.output_channels_is_list = True
170
-
171
164
  return graph_def
172
165
 
173
166
 
@@ -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\"\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')
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\"\xc2\x01\n\x12StateUpdateRequest\x12\x11\n\tnode_name\x18\x01 \x01(\t\x12\x0f\n\x07task_id\x18\x02 \x01(\t\x12\x12\n\ngraph_name\x18\x03 \x01(\t\x12\x0c\n\x04step\x18\x04 \x01(\x05\x12!\n\x08\x63hannels\x18\x05 \x01(\x0b\x32\x0f.types.Channels\x12\x1c\n\x06values\x18\x06 \x01(\x0b\x32\x0c.types.Value\x12%\n\x06\x63onfig\x18\x07 \x01(\x0b\x32\x15.types.RunnableConfig\"\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\x93\x05\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.GenerateCacheKeyResponse\x12\x41\n\x0bStateUpdate\x12\x1c.executor.StateUpdateRequest\x1a\x14.executor.TaskResultB1Z/github.com/langchain-ai/langgraph-go/runtime/pbb\x06proto3')
31
31
 
32
32
  _globals = globals()
33
33
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -39,46 +39,48 @@ if not _descriptor._USE_C_DESCRIPTORS:
39
39
  _globals['_CHANNELSFROMCHECKPOINTREQUEST_CHECKPOINTCHANNELVALUESENTRY']._serialized_options = b'8\001'
40
40
  _globals['_GENERATECACHEKEYREQUEST_CHANNELVALUESENTRY']._loaded_options = None
41
41
  _globals['_GENERATECACHEKEYREQUEST_CHANNELVALUESENTRY']._serialized_options = b'8\001'
42
- _globals['_LISTGRAPHSREQUEST']._serialized_start=84
43
- _globals['_LISTGRAPHSREQUEST']._serialized_end=103
44
- _globals['_LISTGRAPHSRESPONSE']._serialized_start=105
45
- _globals['_LISTGRAPHSRESPONSE']._serialized_end=146
46
- _globals['_GETGRAPHREQUEST']._serialized_start=148
47
- _globals['_GETGRAPHREQUEST']._serialized_end=185
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
42
+ _globals['_STATEUPDATEREQUEST']._serialized_start=85
43
+ _globals['_STATEUPDATEREQUEST']._serialized_end=279
44
+ _globals['_LISTGRAPHSREQUEST']._serialized_start=281
45
+ _globals['_LISTGRAPHSREQUEST']._serialized_end=300
46
+ _globals['_LISTGRAPHSRESPONSE']._serialized_start=302
47
+ _globals['_LISTGRAPHSRESPONSE']._serialized_end=343
48
+ _globals['_GETGRAPHREQUEST']._serialized_start=345
49
+ _globals['_GETGRAPHREQUEST']._serialized_end=382
50
+ _globals['_GETGRAPHRESPONSE']._serialized_start=385
51
+ _globals['_GETGRAPHRESPONSE']._serialized_end=539
52
+ _globals['_GETALLGRAPHSREQUEST']._serialized_start=541
53
+ _globals['_GETALLGRAPHSREQUEST']._serialized_end=562
54
+ _globals['_CHANNELSFROMCHECKPOINTREQUEST']._serialized_start=565
55
+ _globals['_CHANNELSFROMCHECKPOINTREQUEST']._serialized_end=831
56
+ _globals['_CHANNELSFROMCHECKPOINTREQUEST_CHECKPOINTCHANNELVALUESENTRY']._serialized_start=755
57
+ _globals['_CHANNELSFROMCHECKPOINTREQUEST_CHECKPOINTCHANNELVALUESENTRY']._serialized_end=831
58
+ _globals['_CHANNELSFROMCHECKPOINTRESPONSE']._serialized_start=833
59
+ _globals['_CHANNELSFROMCHECKPOINTRESPONSE']._serialized_end=900
60
+ _globals['_EXECUTETASKREQUEST']._serialized_start=903
61
+ _globals['_EXECUTETASKREQUEST']._serialized_end=1039
62
+ _globals['_EXECUTETASKINIT']._serialized_start=1042
63
+ _globals['_EXECUTETASKINIT']._serialized_end=1256
64
+ _globals['_EXECUTETASKRESPONSE']._serialized_start=1259
65
+ _globals['_EXECUTETASKRESPONSE']._serialized_end=1508
66
+ _globals['_TASKRESULT']._serialized_start=1510
67
+ _globals['_TASKRESULT']._serialized_end=1604
68
+ _globals['_CUSTOMSTREAMEVENT']._serialized_start=1606
69
+ _globals['_CUSTOMSTREAMEVENT']._serialized_end=1667
70
+ _globals['_APPLYWRITESREQUEST']._serialized_start=1670
71
+ _globals['_APPLYWRITESREQUEST']._serialized_end=1834
72
+ _globals['_APPLYWRITESRESPONSE']._serialized_start=1836
73
+ _globals['_APPLYWRITESRESPONSE']._serialized_end=1934
74
+ _globals['_GENERATECACHEKEYREQUEST']._serialized_start=1937
75
+ _globals['_GENERATECACHEKEYREQUEST']._serialized_end=2137
76
+ _globals['_GENERATECACHEKEYREQUEST_CHANNELVALUESENTRY']._serialized_start=2085
77
+ _globals['_GENERATECACHEKEYREQUEST_CHANNELVALUESENTRY']._serialized_end=2137
78
+ _globals['_GENERATECACHEKEYRESPONSE']._serialized_start=2139
79
+ _globals['_GENERATECACHEKEYRESPONSE']._serialized_end=2184
80
+ _globals['_CACHECHECKREQUEST']._serialized_start=2186
81
+ _globals['_CACHECHECKREQUEST']._serialized_end=2275
82
+ _globals['_CACHECHECKRESPONSE']._serialized_start=2277
83
+ _globals['_CACHECHECKRESPONSE']._serialized_end=2316
84
+ _globals['_LANGGRAPHEXECUTOR']._serialized_start=2319
85
+ _globals['_LANGGRAPHEXECUTOR']._serialized_end=2978
84
86
  # @@protoc_insertion_point(module_scope)
@@ -15,6 +15,45 @@ import typing
15
15
 
16
16
  DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
17
17
 
18
+ @typing.final
19
+ class StateUpdateRequest(google.protobuf.message.Message):
20
+ """StateUpdate"""
21
+
22
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
23
+
24
+ NODE_NAME_FIELD_NUMBER: builtins.int
25
+ TASK_ID_FIELD_NUMBER: builtins.int
26
+ GRAPH_NAME_FIELD_NUMBER: builtins.int
27
+ STEP_FIELD_NUMBER: builtins.int
28
+ CHANNELS_FIELD_NUMBER: builtins.int
29
+ VALUES_FIELD_NUMBER: builtins.int
30
+ CONFIG_FIELD_NUMBER: builtins.int
31
+ node_name: builtins.str
32
+ task_id: builtins.str
33
+ graph_name: builtins.str
34
+ step: builtins.int
35
+ @property
36
+ def channels(self) -> types_pb2.Channels: ...
37
+ @property
38
+ def values(self) -> types_pb2.Value: ...
39
+ @property
40
+ def config(self) -> types_pb2.RunnableConfig: ...
41
+ def __init__(
42
+ self,
43
+ *,
44
+ node_name: builtins.str = ...,
45
+ task_id: builtins.str = ...,
46
+ graph_name: builtins.str = ...,
47
+ step: builtins.int = ...,
48
+ channels: types_pb2.Channels | None = ...,
49
+ values: types_pb2.Value | None = ...,
50
+ config: types_pb2.RunnableConfig | None = ...,
51
+ ) -> None: ...
52
+ def HasField(self, field_name: typing.Literal["channels", b"channels", "config", b"config", "values", b"values"]) -> builtins.bool: ...
53
+ def ClearField(self, field_name: typing.Literal["channels", b"channels", "config", b"config", "graph_name", b"graph_name", "node_name", b"node_name", "step", b"step", "task_id", b"task_id", "values", b"values"]) -> None: ...
54
+
55
+ global___StateUpdateRequest = StateUpdateRequest
56
+
18
57
  @typing.final
19
58
  class ListGraphsRequest(google.protobuf.message.Message):
20
59
  """ListGraphs"""
@@ -70,6 +70,11 @@ class LangGraphExecutorStub(object):
70
70
  request_serializer=executor__pb2.GenerateCacheKeyRequest.SerializeToString,
71
71
  response_deserializer=executor__pb2.GenerateCacheKeyResponse.FromString,
72
72
  _registered_method=True)
73
+ self.StateUpdate = channel.unary_unary(
74
+ '/executor.LangGraphExecutor/StateUpdate',
75
+ request_serializer=executor__pb2.StateUpdateRequest.SerializeToString,
76
+ response_deserializer=executor__pb2.TaskResult.FromString,
77
+ _registered_method=True)
73
78
 
74
79
 
75
80
  class LangGraphExecutorServicer(object):
@@ -125,6 +130,13 @@ class LangGraphExecutorServicer(object):
125
130
  context.set_details('Method not implemented!')
126
131
  raise NotImplementedError('Method not implemented!')
127
132
 
133
+ def StateUpdate(self, request, context):
134
+ """State update
135
+ """
136
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
137
+ context.set_details('Method not implemented!')
138
+ raise NotImplementedError('Method not implemented!')
139
+
128
140
 
129
141
  def add_LangGraphExecutorServicer_to_server(servicer, server):
130
142
  rpc_method_handlers = {
@@ -163,6 +175,11 @@ def add_LangGraphExecutorServicer_to_server(servicer, server):
163
175
  request_deserializer=executor__pb2.GenerateCacheKeyRequest.FromString,
164
176
  response_serializer=executor__pb2.GenerateCacheKeyResponse.SerializeToString,
165
177
  ),
178
+ 'StateUpdate': grpc.unary_unary_rpc_method_handler(
179
+ servicer.StateUpdate,
180
+ request_deserializer=executor__pb2.StateUpdateRequest.FromString,
181
+ response_serializer=executor__pb2.TaskResult.SerializeToString,
182
+ ),
166
183
  }
167
184
  generic_handler = grpc.method_handlers_generic_handler(
168
185
  'executor.LangGraphExecutor', rpc_method_handlers)
@@ -363,3 +380,30 @@ class LangGraphExecutor(object):
363
380
  timeout,
364
381
  metadata,
365
382
  _registered_method=True)
383
+
384
+ @staticmethod
385
+ def StateUpdate(request,
386
+ target,
387
+ options=(),
388
+ channel_credentials=None,
389
+ call_credentials=None,
390
+ insecure=False,
391
+ compression=None,
392
+ wait_for_ready=None,
393
+ timeout=None,
394
+ metadata=None):
395
+ return grpc.experimental.unary_unary(
396
+ request,
397
+ target,
398
+ '/executor.LangGraphExecutor/StateUpdate',
399
+ executor__pb2.StateUpdateRequest.SerializeToString,
400
+ executor__pb2.TaskResult.FromString,
401
+ options,
402
+ channel_credentials,
403
+ insecure,
404
+ call_credentials,
405
+ compression,
406
+ wait_for_ready,
407
+ timeout,
408
+ metadata,
409
+ _registered_method=True)
@@ -63,6 +63,12 @@ class LangGraphExecutorStub:
63
63
  ]
64
64
  """Generate cache key for a node execution"""
65
65
 
66
+ StateUpdate: grpc.UnaryUnaryMultiCallable[
67
+ executor_pb2.StateUpdateRequest,
68
+ executor_pb2.TaskResult,
69
+ ]
70
+ """State update"""
71
+
66
72
  class LangGraphExecutorAsyncStub:
67
73
  """Main service for LangGraph runtime operations"""
68
74
 
@@ -108,6 +114,12 @@ class LangGraphExecutorAsyncStub:
108
114
  ]
109
115
  """Generate cache key for a node execution"""
110
116
 
117
+ StateUpdate: grpc.aio.UnaryUnaryMultiCallable[
118
+ executor_pb2.StateUpdateRequest,
119
+ executor_pb2.TaskResult,
120
+ ]
121
+ """State update"""
122
+
111
123
  class LangGraphExecutorServicer(metaclass=abc.ABCMeta):
112
124
  """Main service for LangGraph runtime operations"""
113
125
 
@@ -167,4 +179,12 @@ class LangGraphExecutorServicer(metaclass=abc.ABCMeta):
167
179
  ) -> typing.Union[executor_pb2.GenerateCacheKeyResponse, collections.abc.Awaitable[executor_pb2.GenerateCacheKeyResponse]]:
168
180
  """Generate cache key for a node execution"""
169
181
 
182
+ @abc.abstractmethod
183
+ def StateUpdate(
184
+ self,
185
+ request: executor_pb2.StateUpdateRequest,
186
+ context: _ServicerContext,
187
+ ) -> typing.Union[executor_pb2.TaskResult, collections.abc.Awaitable[executor_pb2.TaskResult]]:
188
+ """State update"""
189
+
170
190
  def add_LangGraphExecutorServicer_to_server(servicer: LangGraphExecutorServicer, server: typing.Union[grpc.Server, grpc.aio.Server]) -> None: ...