mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-07 18:27:52 +02:00
Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03776f058e | ||
|
|
11c6a54de9 | ||
|
|
78581b80c2 | ||
|
|
5fee0d9d66 | ||
|
|
68e3d70967 | ||
|
|
dc9f2b1109 | ||
|
|
dbf1c28ccd | ||
|
|
cb25ef985d | ||
|
|
5ddc24ba85 | ||
|
|
0362840d0b | ||
|
|
44099d27c8 | ||
|
|
50449af1a9 | ||
|
|
c2fa33e055 | ||
|
|
644a6c3b63 | ||
|
|
847b9c13ac | ||
|
|
b6963d35aa |
@@ -17,8 +17,58 @@ Here's how to customize the included and excluded headers:
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
The `include` and `exclude` lists accept exact header names or patterns using `*` to match any number of characters. For your security, no other regex patterns are supported.
|
||||
|
||||
## Using within your graph
|
||||
|
||||
You can access the included headers in your graph using the `config` argument of any node.
|
||||
|
||||
```python
|
||||
def my_node(state, config):
|
||||
organization_id = config["configurable"].get("x-organization-id")
|
||||
...
|
||||
```
|
||||
|
||||
Or by fetching from context (useful in tools and or within other nested functions).
|
||||
|
||||
```python
|
||||
from langgraph.config import get_config
|
||||
|
||||
def search_everything(query: str):
|
||||
organization_id = get_config()["configurable"].get("x-organization-id")
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
You can even use this to dynamically compile the graph.
|
||||
|
||||
```python
|
||||
# my_graph.py.
|
||||
import contextlib
|
||||
|
||||
@contextlib.asynccontextmanager
|
||||
async def generate_agent(config):
|
||||
organization_id = config["configurable"].get("x-organization-id")
|
||||
if organization_id == "org1":
|
||||
graph = ...
|
||||
yield graph
|
||||
else:
|
||||
graph = ...
|
||||
yield graph
|
||||
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"graphs": {"agent": "my_grph.py:generate_agent"}
|
||||
}
|
||||
```
|
||||
|
||||
For more examples on how to use runtime configuration, check out the [configuration how-to](../../how-tos/configuration.ipynb).
|
||||
|
||||
### Opt-out of configurable headers
|
||||
|
||||
If you'd like to opt-out of configurable headers, you can simply set a wildcard pattern in the `exclude` list:
|
||||
|
||||
```json
|
||||
@@ -31,4 +81,6 @@ If you'd like to opt-out of configurable headers, you can simply set a wildcard
|
||||
}
|
||||
```
|
||||
|
||||
This will exclude all headers from being added to your run's configuration.
|
||||
This will exclude all headers from being added to your run's configuration.
|
||||
|
||||
Note that exclusions take precedence over inclusions.
|
||||
@@ -440,6 +440,22 @@ Upon **resuming** the graph, the counter will be incremented a second time, resu
|
||||
The value of counter is: 2
|
||||
```
|
||||
|
||||
### Resuming multiple interrupts with one invocation
|
||||
|
||||
If you have multiple interrupts in the task queue, you can use `Command.resume` with a dictionary mapping
|
||||
of interrupt ids to resume values to resume multiple interrupts with a single `invoke` / `stream` call.
|
||||
|
||||
For example, once your graph has been interrupted (multiple times, theoretically) and is stalled:
|
||||
|
||||
```python
|
||||
resume_map = {
|
||||
i.interrupt_id: f"human input for prompt {i.value}"
|
||||
for i in parent.get_state(thread_config).interrupts
|
||||
}
|
||||
|
||||
parent_graph.invoke(Command(resume=resume_map), config=thread_config)
|
||||
```
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
### Side-effects
|
||||
|
||||
@@ -691,7 +691,8 @@
|
||||
"\n",
|
||||
"checkpointer = InMemorySaver()\n",
|
||||
"graph = create_react_agent(\n",
|
||||
" model,\n",
|
||||
" # limit the output size to ensure consistent behavior\n",
|
||||
" model.bind(max_tokens=256),\n",
|
||||
" tools,\n",
|
||||
" # highlight-next-line\n",
|
||||
" pre_model_hook=summarization_node,\n",
|
||||
|
||||
@@ -102,6 +102,8 @@ CONF = cast(Literal["configurable"], sys.intern("configurable"))
|
||||
# key for the configurable dict in RunnableConfig
|
||||
NULL_TASK_ID = sys.intern("00000000-0000-0000-0000-000000000000")
|
||||
# the task_id to use for writes that are not associated with a task
|
||||
CONFIG_KEY_RESUME_MAP = sys.intern("__pregel_resume_map")
|
||||
# holds a mapping of task ns -> resume value for resuming tasks
|
||||
|
||||
RESERVED = {
|
||||
TAG_HIDDEN,
|
||||
|
||||
@@ -853,6 +853,7 @@ class Pregel(PregelProtocol):
|
||||
created_at=None,
|
||||
parent_config=None,
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# migrate checkpoint if needed
|
||||
@@ -937,6 +938,12 @@ class Pregel(PregelProtocol):
|
||||
next_tasks[tid].writes.append((k, v))
|
||||
if tasks := [t for t in next_tasks.values() if t.writes]:
|
||||
apply_writes(saved.checkpoint, channels, tasks, None)
|
||||
tasks_with_writes = tasks_w_writes(
|
||||
next_tasks.values(),
|
||||
saved.pending_writes,
|
||||
task_states,
|
||||
self.stream_channels_asis,
|
||||
)
|
||||
# assemble the state snapshot
|
||||
return StateSnapshot(
|
||||
read_channels(channels, self.stream_channels_asis),
|
||||
@@ -945,12 +952,8 @@ class Pregel(PregelProtocol):
|
||||
saved.metadata,
|
||||
saved.checkpoint["ts"],
|
||||
patch_checkpoint_map(saved.parent_config, saved.metadata),
|
||||
tasks_w_writes(
|
||||
next_tasks.values(),
|
||||
saved.pending_writes,
|
||||
task_states,
|
||||
self.stream_channels_asis,
|
||||
),
|
||||
tasks_with_writes,
|
||||
tuple([i for task in tasks_with_writes for i in task.interrupts]),
|
||||
)
|
||||
|
||||
async def _aprepare_state_snapshot(
|
||||
@@ -969,6 +972,7 @@ class Pregel(PregelProtocol):
|
||||
created_at=None,
|
||||
parent_config=None,
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# migrate checkpoint if needed
|
||||
@@ -1056,6 +1060,13 @@ class Pregel(PregelProtocol):
|
||||
next_tasks[tid].writes.append((k, v))
|
||||
if tasks := [t for t in next_tasks.values() if t.writes]:
|
||||
apply_writes(saved.checkpoint, channels, tasks, None)
|
||||
|
||||
tasks_with_writes = tasks_w_writes(
|
||||
next_tasks.values(),
|
||||
saved.pending_writes,
|
||||
task_states,
|
||||
self.stream_channels_asis,
|
||||
)
|
||||
# assemble the state snapshot
|
||||
return StateSnapshot(
|
||||
read_channels(channels, self.stream_channels_asis),
|
||||
@@ -1064,12 +1075,8 @@ class Pregel(PregelProtocol):
|
||||
saved.metadata,
|
||||
saved.checkpoint["ts"],
|
||||
patch_checkpoint_map(saved.parent_config, saved.metadata),
|
||||
tasks_w_writes(
|
||||
next_tasks.values(),
|
||||
saved.pending_writes,
|
||||
task_states,
|
||||
self.stream_channels_asis,
|
||||
),
|
||||
tasks_with_writes,
|
||||
tuple([i for task in tasks_with_writes for i in task.interrupts]),
|
||||
)
|
||||
|
||||
def get_state(
|
||||
|
||||
@@ -40,6 +40,7 @@ from langgraph.constants import (
|
||||
CONFIG_KEY_CHECKPOINTER,
|
||||
CONFIG_KEY_PREVIOUS,
|
||||
CONFIG_KEY_READ,
|
||||
CONFIG_KEY_RESUME_MAP,
|
||||
CONFIG_KEY_SCRATCHPAD,
|
||||
CONFIG_KEY_SEND,
|
||||
CONFIG_KEY_STORE,
|
||||
@@ -594,6 +595,8 @@ def prepare_single_task(
|
||||
config[CONF].get(CONFIG_KEY_SCRATCHPAD),
|
||||
pending_writes,
|
||||
task_id,
|
||||
xxh3_128_hexdigest(task_checkpoint_ns.encode()),
|
||||
config[CONF].get(CONFIG_KEY_RESUME_MAP),
|
||||
),
|
||||
},
|
||||
),
|
||||
@@ -704,6 +707,8 @@ def prepare_single_task(
|
||||
config[CONF].get(CONFIG_KEY_SCRATCHPAD),
|
||||
pending_writes,
|
||||
task_id,
|
||||
xxh3_128_hexdigest(task_checkpoint_ns.encode()),
|
||||
config[CONF].get(CONFIG_KEY_RESUME_MAP),
|
||||
),
|
||||
CONFIG_KEY_PREVIOUS: checkpoint["channel_values"].get(
|
||||
PREVIOUS, None
|
||||
@@ -830,6 +835,8 @@ def prepare_single_task(
|
||||
config[CONF].get(CONFIG_KEY_SCRATCHPAD),
|
||||
pending_writes,
|
||||
task_id,
|
||||
xxh3_128_hexdigest(task_checkpoint_ns.encode()),
|
||||
config[CONF].get(CONFIG_KEY_RESUME_MAP),
|
||||
),
|
||||
CONFIG_KEY_PREVIOUS: checkpoint["channel_values"].get(
|
||||
PREVIOUS, None
|
||||
@@ -881,6 +888,8 @@ def _scratchpad(
|
||||
parent_scratchpad: Optional[PregelScratchpad],
|
||||
pending_writes: list[PendingWrite],
|
||||
task_id: str,
|
||||
namespace_hash: str,
|
||||
resume_map: Optional[dict[str, Any]],
|
||||
) -> PregelScratchpad:
|
||||
if len(pending_writes) > 0:
|
||||
# find global resume value
|
||||
@@ -892,6 +901,7 @@ def _scratchpad(
|
||||
# None cannot be used as a resume value, because it would be difficult to
|
||||
# distinguish from missing when used over http
|
||||
null_resume_write = None
|
||||
|
||||
# find task-specific resume value
|
||||
for w in pending_writes:
|
||||
if w[0] == task_id and w[1] == RESUME:
|
||||
@@ -901,8 +911,13 @@ def _scratchpad(
|
||||
break
|
||||
else:
|
||||
task_resume_write = []
|
||||
# clear var
|
||||
del w
|
||||
|
||||
# find namespace and task-specific resume value
|
||||
if resume_map and namespace_hash in resume_map:
|
||||
mapped_resume_write = resume_map[namespace_hash]
|
||||
task_resume_write.append(mapped_resume_write)
|
||||
|
||||
else:
|
||||
null_resume_write = None
|
||||
task_resume_write = []
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
from collections import Counter
|
||||
from collections.abc import Iterator, Mapping, Sequence
|
||||
from typing import Any, Literal, Optional, TypeVar, Union
|
||||
from uuid import UUID
|
||||
|
||||
from langchain_core.runnables.utils import AddableDict
|
||||
|
||||
from langgraph.channels.base import BaseChannel, EmptyChannelError
|
||||
from langgraph.checkpoint.base import PendingWrite
|
||||
from langgraph.constants import (
|
||||
EMPTY_SEQ,
|
||||
ERROR,
|
||||
@@ -24,15 +22,6 @@ from langgraph.pregel.log import logger
|
||||
from langgraph.types import Command, PregelExecutableTask, Send
|
||||
|
||||
|
||||
def is_task_id(task_id: str) -> bool:
|
||||
"""Check if a string is a valid task id."""
|
||||
try:
|
||||
UUID(task_id)
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def read_channel(
|
||||
channels: Mapping[str, BaseChannel],
|
||||
chan: str,
|
||||
@@ -66,9 +55,7 @@ def read_channels(
|
||||
return values
|
||||
|
||||
|
||||
def map_command(
|
||||
cmd: Command, pending_writes: list[PendingWrite]
|
||||
) -> Iterator[tuple[str, str, Any]]:
|
||||
def map_command(cmd: Command) -> Iterator[tuple[str, str, Any]]:
|
||||
"""Map input chunk to a sequence of pending writes in the form (channel, value)."""
|
||||
if cmd.graph == Command.PARENT:
|
||||
raise InvalidUpdateError("There is no parent graph")
|
||||
@@ -87,15 +74,7 @@ def map_command(
|
||||
f"In Command.goto, expected Send/str, got {type(send).__name__}"
|
||||
)
|
||||
if cmd.resume is not None:
|
||||
if isinstance(cmd.resume, dict) and all(is_task_id(k) for k in cmd.resume):
|
||||
for tid, resume in cmd.resume.items():
|
||||
existing: list[Any] = next(
|
||||
(w[2] for w in pending_writes if w[0] == tid and w[1] == RESUME), []
|
||||
)
|
||||
existing.append(resume)
|
||||
yield (tid, RESUME, existing)
|
||||
else:
|
||||
yield (NULL_TASK_ID, RESUME, cmd.resume)
|
||||
yield (NULL_TASK_ID, RESUME, cmd.resume)
|
||||
if cmd.update:
|
||||
for k, v in cmd._update_as_tuples():
|
||||
yield (NULL_TASK_ID, k, v)
|
||||
|
||||
@@ -47,6 +47,7 @@ from langgraph.constants import (
|
||||
CONFIG_KEY_DEDUPE_TASKS,
|
||||
CONFIG_KEY_DELEGATE,
|
||||
CONFIG_KEY_ENSURE_LATEST,
|
||||
CONFIG_KEY_RESUME_MAP,
|
||||
CONFIG_KEY_RESUMING,
|
||||
CONFIG_KEY_SCRATCHPAD,
|
||||
CONFIG_KEY_STREAM,
|
||||
@@ -112,7 +113,7 @@ from langgraph.pregel.io import (
|
||||
)
|
||||
from langgraph.pregel.manager import AsyncChannelsManager, ChannelsManager
|
||||
from langgraph.pregel.read import PregelNode
|
||||
from langgraph.pregel.utils import get_new_channel_versions
|
||||
from langgraph.pregel.utils import get_new_channel_versions, is_xxh3_128_hexdigest
|
||||
from langgraph.store.base import BaseStore
|
||||
from langgraph.types import (
|
||||
All,
|
||||
@@ -649,14 +650,21 @@ class PregelLoop(LoopProtocol):
|
||||
|
||||
# map command to writes
|
||||
if isinstance(self.input, Command):
|
||||
if self.input.resume is not None and not self.checkpointer:
|
||||
if resume_is_map := (
|
||||
(resume := self.input.resume) is not None
|
||||
and isinstance(resume, dict)
|
||||
and all(is_xxh3_128_hexdigest(k) for k in resume)
|
||||
):
|
||||
self.config[CONF][CONFIG_KEY_RESUME_MAP] = self.input.resume
|
||||
if resume is not None and not self.checkpointer:
|
||||
raise RuntimeError(
|
||||
"Cannot use Command(resume=...) without checkpointer"
|
||||
)
|
||||
writes: defaultdict[str, list[tuple[str, Any]]] = defaultdict(list)
|
||||
# group writes by task ID
|
||||
for tid, c, v in map_command(self.input, self.checkpoint_pending_writes):
|
||||
writes[tid].append((c, v))
|
||||
for tid, c, v in map_command(cmd=self.input):
|
||||
if not (c == RESUME and resume_is_map):
|
||||
writes[tid].append((c, v))
|
||||
if not writes:
|
||||
raise EmptyInputError("Received empty Command input")
|
||||
# save writes
|
||||
|
||||
@@ -241,7 +241,7 @@ class RemoteGraph(PregelProtocol):
|
||||
)
|
||||
|
||||
def _create_state_snapshot(self, state: ThreadState) -> StateSnapshot:
|
||||
tasks = []
|
||||
tasks: list[PregelTask] = []
|
||||
for task in state["tasks"]:
|
||||
interrupts = []
|
||||
for interrupt in task["interrupts"]:
|
||||
@@ -289,6 +289,7 @@ class RemoteGraph(PregelProtocol):
|
||||
if state["parent_checkpoint"]
|
||||
else None,
|
||||
tasks=tuple(tasks),
|
||||
interrupts=tuple([i for task in tasks for i in task.interrupts]),
|
||||
)
|
||||
|
||||
def _get_checkpoint(self, config: Optional[RunnableConfig]) -> Optional[Checkpoint]:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import ast
|
||||
import inspect
|
||||
import re
|
||||
import textwrap
|
||||
from typing import Any, Callable, Optional
|
||||
|
||||
@@ -207,3 +208,8 @@ class NonLocals(ast.NodeVisitor):
|
||||
parent = parent.value
|
||||
if isinstance(parent, ast.Name):
|
||||
self.loads.add(parent.id + "." + attr_expr)
|
||||
|
||||
|
||||
def is_xxh3_128_hexdigest(value: str) -> bool:
|
||||
"""Check if the given string matches the format of xxh3_128_hexdigest."""
|
||||
return bool(re.fullmatch(r"[0-9a-f]{32}", value))
|
||||
|
||||
@@ -147,7 +147,7 @@ class Interrupt:
|
||||
"""Generate a unique ID for the interrupt based on its namespace."""
|
||||
if self.ns is None:
|
||||
return "placeholder-id"
|
||||
return xxh3_128_hexdigest("".join(self.ns).encode())
|
||||
return xxh3_128_hexdigest("|".join(self.ns).encode())
|
||||
|
||||
|
||||
class StateUpdate(NamedTuple):
|
||||
@@ -192,19 +192,21 @@ class StateSnapshot(NamedTuple):
|
||||
"""Snapshot of the state of the graph at the beginning of a step."""
|
||||
|
||||
values: Union[dict[str, Any], Any]
|
||||
"""Current values of channels"""
|
||||
"""Current values of channels."""
|
||||
next: tuple[str, ...]
|
||||
"""The name of the node to execute in each task for this step."""
|
||||
config: RunnableConfig
|
||||
"""Config used to fetch this snapshot"""
|
||||
"""Config used to fetch this snapshot."""
|
||||
metadata: Optional[CheckpointMetadata]
|
||||
"""Metadata associated with this snapshot"""
|
||||
"""Metadata associated with this snapshot."""
|
||||
created_at: Optional[str]
|
||||
"""Timestamp of snapshot creation"""
|
||||
"""Timestamp of snapshot creation."""
|
||||
parent_config: Optional[RunnableConfig]
|
||||
"""Config used to fetch the parent snapshot, if any"""
|
||||
"""Config used to fetch the parent snapshot, if any."""
|
||||
tasks: tuple[PregelTask, ...]
|
||||
"""Tasks to execute in this step. If already attempted, may contain an error."""
|
||||
interrupts: tuple[Interrupt, ...]
|
||||
"""Interrupts that occurred in this step that are pending resolution."""
|
||||
|
||||
|
||||
class Send:
|
||||
@@ -294,6 +296,10 @@ class Command(Generic[N], ToolOutputMixin):
|
||||
- Command.PARENT: closest parent graph
|
||||
update: update to apply to the graph's state.
|
||||
resume: value to resume execution with. To be used together with [`interrupt()`][langgraph.types.interrupt].
|
||||
Can be one of the following:
|
||||
|
||||
- mapping of interrupt ids to resume values
|
||||
- a single value with which to resume the next interrupt
|
||||
goto: can be one of the following:
|
||||
|
||||
- name of the node to navigate to next (any node that belongs to the specified `graph`)
|
||||
@@ -304,7 +310,7 @@ class Command(Generic[N], ToolOutputMixin):
|
||||
|
||||
graph: Optional[str] = None
|
||||
update: Optional[Any] = None
|
||||
resume: Optional[Union[Any, dict[str, Any]]] = None
|
||||
resume: Optional[Union[dict[str, Any], Any]] = None
|
||||
goto: Union[Send, Sequence[Union[Send, str]], str] = ()
|
||||
|
||||
def __repr__(self) -> str:
|
||||
|
||||
@@ -63,6 +63,7 @@ def get_expected_history(*, exc_task_results: int = 0) -> list[StateSnapshot]:
|
||||
}
|
||||
},
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={
|
||||
@@ -113,6 +114,15 @@ def get_expected_history(*, exc_task_results: int = 0) -> list[StateSnapshot]:
|
||||
else {"answer": "doc1,doc2,doc3,doc4"},
|
||||
),
|
||||
),
|
||||
interrupts=()
|
||||
if exc_task_results
|
||||
else (
|
||||
Interrupt(
|
||||
value="",
|
||||
resumable=True,
|
||||
ns=[AnyStr("qa:")],
|
||||
),
|
||||
),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={
|
||||
@@ -156,6 +166,7 @@ def get_expected_history(*, exc_task_results: int = 0) -> list[StateSnapshot]:
|
||||
result=None if exc_task_results else {"docs": ["doc1", "doc2"]},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"query": "query: what is weather in sf", "docs": []},
|
||||
@@ -206,6 +217,7 @@ def get_expected_history(*, exc_task_results: int = 0) -> list[StateSnapshot]:
|
||||
else {"docs": ["doc3", "doc4"]},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"query": "what is weather in sf", "docs": []},
|
||||
@@ -245,6 +257,7 @@ def get_expected_history(*, exc_task_results: int = 0) -> list[StateSnapshot]:
|
||||
else {"query": "query: what is weather in sf"},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"docs": []},
|
||||
@@ -276,6 +289,7 @@ def get_expected_history(*, exc_task_results: int = 0) -> list[StateSnapshot]:
|
||||
result={"query": "what is weather in sf"},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1731,6 +1745,7 @@ def test_saved_checkpoint_state_graph(
|
||||
created_at=AnyStr(),
|
||||
parent_config=latest_state.parent_config,
|
||||
tasks=latest_state.tasks,
|
||||
interrupts=latest_state.interrupts,
|
||||
)
|
||||
== history[0]
|
||||
)
|
||||
@@ -1802,6 +1817,7 @@ async def test_saved_checkpoint_state_graph_async(
|
||||
created_at=AnyStr(),
|
||||
parent_config=latest_state.parent_config,
|
||||
tasks=latest_state.tasks,
|
||||
interrupts=latest_state.interrupts,
|
||||
)
|
||||
== history[0]
|
||||
)
|
||||
|
||||
@@ -144,6 +144,7 @@ def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[1].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"inbox": 4, "output": 4, "input": 3},
|
||||
@@ -165,6 +166,7 @@ def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[2].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"inbox": 21, "output": 4, "input": 3},
|
||||
@@ -186,6 +188,7 @@ def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[3].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"inbox": 21, "output": 4, "input": 20},
|
||||
@@ -207,6 +210,7 @@ def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[4].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"inbox": 3, "output": 4, "input": 20},
|
||||
@@ -228,6 +232,7 @@ def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[5].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"inbox": 3, "output": 4, "input": 2},
|
||||
@@ -249,6 +254,7 @@ def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[6].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"inbox": 3, "input": 2},
|
||||
@@ -270,6 +276,7 @@ def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[7].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"input": 2},
|
||||
@@ -291,6 +298,7 @@ def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -358,6 +366,7 @@ def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[1].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=5,
|
||||
@@ -379,6 +388,7 @@ def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[2].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=4,
|
||||
@@ -400,6 +410,7 @@ def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[3].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=3,
|
||||
@@ -421,6 +432,7 @@ def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[4].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=2,
|
||||
@@ -442,6 +454,7 @@ def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[5].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=1,
|
||||
@@ -463,6 +476,7 @@ def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[6].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=0,
|
||||
@@ -484,6 +498,7 @@ def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -776,6 +791,7 @@ def test_conditional_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
assert (
|
||||
app_w_interrupt.checkpointer.get_tuple(config).config["configurable"][
|
||||
@@ -838,6 +854,7 @@ def test_conditional_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -969,6 +986,7 @@ def test_conditional_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# test state get/update methods with interrupt_before
|
||||
@@ -1035,6 +1053,7 @@ def test_conditional_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
app_w_interrupt.update_state(
|
||||
@@ -1091,6 +1110,7 @@ def test_conditional_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -1222,6 +1242,7 @@ def test_conditional_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# test re-invoke to continue with interrupt_before
|
||||
@@ -1288,6 +1309,7 @@ def test_conditional_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -1684,6 +1706,7 @@ def test_conditional_state_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
with assert_ctx_once():
|
||||
@@ -1737,6 +1760,7 @@ def test_conditional_state_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
with assert_ctx_once():
|
||||
@@ -1824,6 +1848,7 @@ def test_conditional_state_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# test state get/update methods with interrupt_before
|
||||
@@ -1886,6 +1911,7 @@ def test_conditional_state_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
app_w_interrupt.update_state(
|
||||
@@ -1938,6 +1964,7 @@ def test_conditional_state_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -2023,6 +2050,7 @@ def test_conditional_state_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# test w interrupt before all
|
||||
@@ -2066,6 +2094,7 @@ def test_conditional_state_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -2116,6 +2145,7 @@ def test_conditional_state_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -2187,6 +2217,7 @@ def test_conditional_state_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -2260,6 +2291,7 @@ def test_conditional_state_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -2331,6 +2363,7 @@ def test_conditional_state_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -3071,6 +3104,7 @@ def test_state_graph_packets(
|
||||
if "shallow" in checkpointer_name
|
||||
else [*app_w_interrupt.checkpointer.list(config, limit=2)][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# modify ai message
|
||||
@@ -3135,6 +3169,7 @@ def test_state_graph_packets(
|
||||
if "shallow" in checkpointer_name
|
||||
else [*app_w_interrupt.checkpointer.list(config, limit=2)][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -3254,6 +3289,7 @@ def test_state_graph_packets(
|
||||
if "shallow" in checkpointer_name
|
||||
else [*app_w_interrupt.checkpointer.list(config, limit=2)][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
app_w_interrupt.update_state(
|
||||
@@ -3315,6 +3351,7 @@ def test_state_graph_packets(
|
||||
if "shallow" in checkpointer_name
|
||||
else [*app_w_interrupt.checkpointer.list(config, limit=2)][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# interrupt before tools
|
||||
@@ -3404,6 +3441,7 @@ def test_state_graph_packets(
|
||||
if "shallow" in checkpointer_name
|
||||
else [*app_w_interrupt.checkpointer.list(config, limit=2)][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# modify ai message
|
||||
@@ -3462,6 +3500,7 @@ def test_state_graph_packets(
|
||||
if "shallow" in checkpointer_name
|
||||
else [*app_w_interrupt.checkpointer.list(config, limit=2)][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -3579,6 +3618,7 @@ def test_state_graph_packets(
|
||||
if "shallow" in checkpointer_name
|
||||
else [*app_w_interrupt.checkpointer.list(config, limit=2)][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
app_w_interrupt.update_state(
|
||||
@@ -3640,6 +3680,7 @@ def test_state_graph_packets(
|
||||
if "shallow" in checkpointer_name
|
||||
else [*app_w_interrupt.checkpointer.list(config, limit=2)][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -3936,6 +3977,7 @@ def test_message_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# modify ai message
|
||||
@@ -3987,6 +4029,7 @@ def test_message_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -4080,6 +4123,7 @@ def test_message_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
app_w_interrupt.update_state(
|
||||
@@ -4131,6 +4175,7 @@ def test_message_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
app_w_interrupt = workflow.compile(
|
||||
@@ -4206,6 +4251,7 @@ def test_message_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# modify ai message
|
||||
@@ -4263,6 +4309,7 @@ def test_message_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -4356,6 +4403,7 @@ def test_message_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
app_w_interrupt.update_state(
|
||||
@@ -4408,6 +4456,7 @@ def test_message_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# add an extra message as if it came from "tools" node
|
||||
@@ -4460,6 +4509,7 @@ def test_message_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -4759,6 +4809,7 @@ def test_root_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# modify ai message
|
||||
@@ -4810,6 +4861,7 @@ def test_root_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -4904,6 +4956,7 @@ def test_root_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
app_w_interrupt.update_state(
|
||||
@@ -4956,6 +5009,7 @@ def test_root_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
app_w_interrupt = workflow.compile(
|
||||
@@ -5031,6 +5085,7 @@ def test_root_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# modify ai message
|
||||
@@ -5088,6 +5143,7 @@ def test_root_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config)] == [
|
||||
@@ -5182,6 +5238,7 @@ def test_root_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
app_w_interrupt.update_state(
|
||||
@@ -5233,6 +5290,7 @@ def test_root_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# add an extra message as if it came from "tools" node
|
||||
@@ -5285,6 +5343,7 @@ def test_root_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(app_w_interrupt.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# create new graph with one more state key, reuse previous thread history
|
||||
@@ -5368,6 +5427,7 @@ def test_root_graph(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(new_app.checkpointer.list(config, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# new input is merged to old state
|
||||
@@ -5775,6 +5835,13 @@ def test_dynamic_interrupt(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread1, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(
|
||||
Interrupt(
|
||||
value="Just because...",
|
||||
resumable=True,
|
||||
ns=[AnyStr("tool_two:")],
|
||||
),
|
||||
),
|
||||
)
|
||||
# clear the interrupt and next tasks
|
||||
tool_two.update_state(thread1, None, as_node=END)
|
||||
@@ -5803,6 +5870,7 @@ def test_dynamic_interrupt(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread1, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -5964,6 +6032,13 @@ def test_copy_checkpoint(
|
||||
if "shallow" in checkpointer_name
|
||||
else [*tool_two.checkpointer.list(thread1, limit=2)][-1].config
|
||||
),
|
||||
interrupts=(
|
||||
Interrupt(
|
||||
value="Just because...",
|
||||
resumable=True,
|
||||
ns=[AnyStr("tool_two:")],
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
if "shallow" in checkpointer_name:
|
||||
@@ -6009,6 +6084,7 @@ def test_copy_checkpoint(
|
||||
parent_config=(
|
||||
[*tool_two.checkpointer.list(thread1, limit=2)][-1].parent_config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -6184,6 +6260,13 @@ def test_dynamic_interrupt_subgraph(
|
||||
)
|
||||
)[-1].config
|
||||
),
|
||||
interrupts=(
|
||||
Interrupt(
|
||||
value="Just because...",
|
||||
resumable=True,
|
||||
ns=[AnyStr("tool_two:"), AnyStr("do:")],
|
||||
),
|
||||
),
|
||||
)
|
||||
# clear the interrupt and next tasks
|
||||
tool_two.update_state(thread1, None, as_node=END)
|
||||
@@ -6216,6 +6299,7 @@ def test_dynamic_interrupt_subgraph(
|
||||
)
|
||||
)[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -6334,6 +6418,7 @@ def test_start_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread1, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert tool_two.invoke(None, thread1, debug=1) == {
|
||||
@@ -6365,6 +6450,7 @@ def test_start_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread1, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
thread2 = {"configurable": {"thread_id": "2", "assistant_id": "a"}}
|
||||
@@ -6398,6 +6484,7 @@ def test_start_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread2, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert tool_two.invoke(None, thread2, debug=1) == {
|
||||
@@ -6429,6 +6516,7 @@ def test_start_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread2, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
thread3 = {"configurable": {"thread_id": "3", "assistant_id": "b"}}
|
||||
@@ -6462,6 +6550,7 @@ def test_start_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread3, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# update state
|
||||
tool_two.update_state(thread3, {"my_key": "key"}) # appends to my_key
|
||||
@@ -6490,6 +6579,7 @@ def test_start_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread3, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert tool_two.invoke(None, thread3, debug=1) == {
|
||||
@@ -6521,6 +6611,7 @@ def test_start_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread3, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -6900,6 +6991,7 @@ def test_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread1, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert tool_two.invoke(None, thread1, debug=1) == {
|
||||
@@ -6930,6 +7022,7 @@ def test_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread1, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
thread2 = {"configurable": {"thread_id": "2"}}
|
||||
@@ -6962,6 +7055,7 @@ def test_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread2, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert tool_two.invoke(None, thread2, debug=1) == {
|
||||
@@ -6992,6 +7086,7 @@ def test_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread2, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
tool_two = tool_two_graph.compile(
|
||||
@@ -7032,6 +7127,7 @@ def test_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread1, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# update state
|
||||
@@ -7063,6 +7159,7 @@ def test_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread1, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
tool_two = tool_two_graph.compile(
|
||||
@@ -7103,6 +7200,7 @@ def test_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread1, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert tool_two.invoke(None, thread1, debug=1) == {
|
||||
@@ -7133,6 +7231,7 @@ def test_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread1, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
thread2 = {"configurable": {"thread_id": "22"}}
|
||||
@@ -7165,6 +7264,7 @@ def test_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread2, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert tool_two.invoke(None, thread2, debug=1) == {
|
||||
@@ -7195,6 +7295,7 @@ def test_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread2, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
thread3 = {"configurable": {"thread_id": "23"}}
|
||||
@@ -7221,6 +7322,7 @@ def test_branch_then(
|
||||
"thread_id": "23",
|
||||
},
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
)
|
||||
# run from this point
|
||||
assert tool_two.invoke(None, thread3) == {
|
||||
@@ -7252,6 +7354,7 @@ def test_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread3, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert tool_two.invoke(None, thread3, debug=1) == {
|
||||
@@ -7282,6 +7385,7 @@ def test_branch_then(
|
||||
if "shallow" in checkpointer_name
|
||||
else list(tool_two.checkpointer.list(thread3, limit=2))[-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -7423,6 +7527,7 @@ def test_send_dedupe_on_resume(
|
||||
}
|
||||
},
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=[
|
||||
@@ -7469,6 +7574,7 @@ def test_send_dedupe_on_resume(
|
||||
result=["3"],
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=[
|
||||
@@ -7536,6 +7642,7 @@ def test_send_dedupe_on_resume(
|
||||
result=["3"],
|
||||
),
|
||||
),
|
||||
interrupts=(Interrupt(value="Bahh", resumable=False, ns=None),),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=["0", "1"],
|
||||
@@ -7591,6 +7698,7 @@ def test_send_dedupe_on_resume(
|
||||
result=["3.1"],
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=["0"],
|
||||
@@ -7628,6 +7736,7 @@ def test_send_dedupe_on_resume(
|
||||
result=["1"],
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=[],
|
||||
@@ -7648,6 +7757,7 @@ def test_send_dedupe_on_resume(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
tasks=(
|
||||
PregelTask(
|
||||
id=AnyStr(),
|
||||
@@ -7762,6 +7872,7 @@ def test_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# now, get_state with subgraphs state
|
||||
assert app.get_state(config, subgraphs=True) == StateSnapshot(
|
||||
@@ -7828,6 +7939,7 @@ def test_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -7858,6 +7970,7 @@ def test_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# get_state_history returns outer graph checkpoints
|
||||
history = list(app.get_state_history(config))
|
||||
@@ -7904,6 +8017,7 @@ def test_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "my value"},
|
||||
@@ -7938,6 +8052,7 @@ def test_nested_graph_state(
|
||||
"checkpoint_id": AnyStr(),
|
||||
}
|
||||
},
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={},
|
||||
@@ -7966,6 +8081,7 @@ def test_nested_graph_state(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -8022,6 +8138,7 @@ def test_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
tasks=(PregelTask(AnyStr(), "inner_2", (PULL, "inner_2")),),
|
||||
),
|
||||
StateSnapshot(
|
||||
@@ -8071,6 +8188,7 @@ def test_nested_graph_state(
|
||||
},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={},
|
||||
@@ -8099,6 +8217,7 @@ def test_nested_graph_state(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
tasks=(
|
||||
PregelTask(
|
||||
AnyStr(),
|
||||
@@ -8150,6 +8269,7 @@ def test_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# test full history at the end
|
||||
actual_history = list(app.get_state_history(config))
|
||||
@@ -8186,6 +8306,7 @@ def test_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value here and there"},
|
||||
@@ -8220,6 +8341,7 @@ def test_nested_graph_state(
|
||||
"checkpoint_id": AnyStr(),
|
||||
}
|
||||
},
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value"},
|
||||
@@ -8257,6 +8379,7 @@ def test_nested_graph_state(
|
||||
"checkpoint_id": AnyStr(),
|
||||
}
|
||||
},
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "my value"},
|
||||
@@ -8291,6 +8414,7 @@ def test_nested_graph_state(
|
||||
"checkpoint_id": AnyStr(),
|
||||
}
|
||||
},
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={},
|
||||
@@ -8319,6 +8443,7 @@ def test_nested_graph_state(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
),
|
||||
]
|
||||
if "shallow" in checkpointer_name:
|
||||
@@ -8439,6 +8564,7 @@ def test_doubly_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
child_state = app.get_state(outer_state.tasks[0].state)
|
||||
assert child_state == StateSnapshot(
|
||||
@@ -8500,6 +8626,7 @@ def test_doubly_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
grandchild_state = app.get_state(child_state.tasks[0].state)
|
||||
assert grandchild_state == StateSnapshot(
|
||||
@@ -8562,6 +8689,7 @@ def test_doubly_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# get state with subgraphs
|
||||
assert app.get_state(config, subgraphs=True) == StateSnapshot(
|
||||
@@ -8649,6 +8777,7 @@ def test_doubly_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -8690,6 +8819,7 @@ def test_doubly_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -8720,6 +8850,7 @@ def test_doubly_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# # resume
|
||||
assert [c for c in app.stream(None, config, subgraphs=True)] == [
|
||||
@@ -8767,6 +8898,7 @@ def test_doubly_nested_graph_state(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -8804,6 +8936,7 @@ def test_doubly_nested_graph_state(
|
||||
"checkpoint_id": AnyStr(),
|
||||
}
|
||||
},
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value here and there"},
|
||||
@@ -8838,6 +8971,7 @@ def test_doubly_nested_graph_state(
|
||||
result={"my_key": "hi my value here and there and back again"},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value"},
|
||||
@@ -8878,6 +9012,7 @@ def test_doubly_nested_graph_state(
|
||||
"checkpoint_id": AnyStr(),
|
||||
}
|
||||
},
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "my value"},
|
||||
@@ -8912,6 +9047,7 @@ def test_doubly_nested_graph_state(
|
||||
result={"my_key": "hi my value"},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={},
|
||||
@@ -8932,6 +9068,7 @@ def test_doubly_nested_graph_state(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
tasks=(
|
||||
PregelTask(
|
||||
id=AnyStr(),
|
||||
@@ -8982,6 +9119,7 @@ def test_doubly_nested_graph_state(
|
||||
}
|
||||
},
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value"},
|
||||
@@ -9033,6 +9171,7 @@ def test_doubly_nested_graph_state(
|
||||
result={"my_key": "hi my value here and there"},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={},
|
||||
@@ -9061,6 +9200,7 @@ def test_doubly_nested_graph_state(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
tasks=(
|
||||
PregelTask(
|
||||
id=AnyStr(),
|
||||
@@ -9127,6 +9267,7 @@ def test_doubly_nested_graph_state(
|
||||
}
|
||||
},
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value here"},
|
||||
@@ -9188,6 +9329,7 @@ def test_doubly_nested_graph_state(
|
||||
result={"my_key": "hi my value here and there"},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value"},
|
||||
@@ -9249,6 +9391,7 @@ def test_doubly_nested_graph_state(
|
||||
result={"my_key": "hi my value here"},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={},
|
||||
@@ -9289,6 +9432,7 @@ def test_doubly_nested_graph_state(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
tasks=(
|
||||
PregelTask(
|
||||
id=AnyStr(),
|
||||
@@ -9565,6 +9709,7 @@ def test_send_react_interrupt(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
tasks=(
|
||||
PregelTask(
|
||||
id=AnyStr(),
|
||||
@@ -9628,6 +9773,7 @@ def test_send_react_interrupt(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
tasks=(),
|
||||
)
|
||||
|
||||
@@ -9725,6 +9871,7 @@ def test_send_react_interrupt(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
tasks=(
|
||||
PregelTask(
|
||||
id=AnyStr(),
|
||||
@@ -9816,6 +9963,7 @@ def test_send_react_interrupt(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
tasks=(
|
||||
PregelTask(
|
||||
id=AnyStr(),
|
||||
@@ -10046,6 +10194,7 @@ def test_send_react_interrupt_control(
|
||||
result=None,
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# remove the tool call, clearing the pending task
|
||||
@@ -10098,6 +10247,7 @@ def test_send_react_interrupt_control(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
tasks=(),
|
||||
)
|
||||
|
||||
@@ -10300,6 +10450,7 @@ def test_weather_subgraph(
|
||||
},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# update
|
||||
@@ -10442,9 +10593,11 @@ def test_weather_subgraph(
|
||||
path=(PULL, "weather_node"),
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
graph.update_state(
|
||||
state.tasks[0].state.config,
|
||||
@@ -10547,10 +10700,12 @@ def test_weather_subgraph(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
tasks=(),
|
||||
),
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
assert [
|
||||
c
|
||||
|
||||
@@ -141,6 +141,7 @@ async def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[1].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"inbox": 4, "output": 4, "input": 3},
|
||||
@@ -164,6 +165,7 @@ async def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[2].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"inbox": 21, "output": 4, "input": 3},
|
||||
@@ -187,6 +189,7 @@ async def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[3].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"inbox": 21, "output": 4, "input": 20},
|
||||
@@ -208,6 +211,7 @@ async def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[4].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"inbox": 3, "output": 4, "input": 20},
|
||||
@@ -231,6 +235,7 @@ async def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[5].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"inbox": 3, "output": 4, "input": 2},
|
||||
@@ -252,6 +257,7 @@ async def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[6].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"inbox": 3, "input": 2},
|
||||
@@ -275,6 +281,7 @@ async def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[7].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"input": 2},
|
||||
@@ -298,6 +305,7 @@ async def test_invoke_two_processes_in_out_interrupt(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -374,6 +382,7 @@ async def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[1].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=5,
|
||||
@@ -395,6 +404,7 @@ async def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[2].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=4,
|
||||
@@ -416,6 +426,7 @@ async def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[3].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=3,
|
||||
@@ -437,6 +448,7 @@ async def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[4].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=2,
|
||||
@@ -458,6 +470,7 @@ async def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[5].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=1,
|
||||
@@ -479,6 +492,7 @@ async def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=history[6].config,
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=0,
|
||||
@@ -502,6 +516,7 @@ async def test_fork_always_re_runs_nodes(
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -858,6 +873,7 @@ async def test_conditional_graph(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
await app_w_interrupt.aupdate_state(
|
||||
@@ -916,6 +932,7 @@ async def test_conditional_graph(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c async for c in app_w_interrupt.astream(None, config)] == [
|
||||
@@ -1049,6 +1066,7 @@ async def test_conditional_graph(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# test state get/update methods with interrupt_before
|
||||
@@ -1124,6 +1142,7 @@ async def test_conditional_graph(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
await app_w_interrupt.aupdate_state(
|
||||
@@ -1182,6 +1201,7 @@ async def test_conditional_graph(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c async for c in app_w_interrupt.astream(None, config)] == [
|
||||
@@ -1315,6 +1335,7 @@ async def test_conditional_graph(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# test re-invoke to continue with interrupt_before
|
||||
@@ -1390,6 +1411,7 @@ async def test_conditional_graph(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c async for c in app_w_interrupt.astream(None, config)] == [
|
||||
@@ -1819,6 +1841,7 @@ async def test_conditional_graph_state(
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
async with assert_ctx_once():
|
||||
@@ -1874,6 +1897,7 @@ async def test_conditional_graph_state(
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
async with assert_ctx_once():
|
||||
@@ -1963,6 +1987,7 @@ async def test_conditional_graph_state(
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# test state get/update methods with interrupt_before
|
||||
@@ -2031,6 +2056,7 @@ async def test_conditional_graph_state(
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
await app_w_interrupt.aupdate_state(
|
||||
@@ -2085,6 +2111,7 @@ async def test_conditional_graph_state(
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c async for c in app_w_interrupt.astream(None, config)] == [
|
||||
@@ -2172,6 +2199,7 @@ async def test_conditional_graph_state(
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -2796,6 +2824,7 @@ async def test_state_graph_packets(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# modify ai message
|
||||
@@ -2854,6 +2883,7 @@ async def test_state_graph_packets(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c async for c in app_w_interrupt.astream(None, config)] == [
|
||||
@@ -2968,6 +2998,7 @@ async def test_state_graph_packets(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
await app_w_interrupt.aupdate_state(
|
||||
@@ -3022,6 +3053,7 @@ async def test_state_graph_packets(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# interrupt before tools
|
||||
@@ -3109,6 +3141,7 @@ async def test_state_graph_packets(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# modify ai message
|
||||
@@ -3167,6 +3200,7 @@ async def test_state_graph_packets(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c async for c in app_w_interrupt.astream(None, config)] == [
|
||||
@@ -3281,6 +3315,7 @@ async def test_state_graph_packets(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
await app_w_interrupt.aupdate_state(
|
||||
@@ -3335,6 +3370,7 @@ async def test_state_graph_packets(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -3600,6 +3636,7 @@ async def test_message_graph(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# modify ai message
|
||||
@@ -3654,6 +3691,7 @@ async def test_message_graph(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c async for c in app_w_interrupt.astream(None, config)] == [
|
||||
@@ -3744,6 +3782,7 @@ async def test_message_graph(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
await app_w_interrupt.aupdate_state(
|
||||
@@ -3792,6 +3831,7 @@ async def test_message_graph(checkpointer_name: str) -> None:
|
||||
c async for c in app_w_interrupt.checkpointer.alist(config, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -4131,6 +4171,7 @@ async def test_start_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert await tool_two.ainvoke(None, thread1, debug=1) == {
|
||||
@@ -4164,6 +4205,7 @@ async def test_start_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
thread2 = {"configurable": {"thread_id": "2", "assistant_id": "a"}}
|
||||
@@ -4199,6 +4241,7 @@ async def test_start_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert await tool_two.ainvoke(None, thread2, debug=1) == {
|
||||
@@ -4232,6 +4275,7 @@ async def test_start_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
thread3 = {"configurable": {"thread_id": "3", "assistant_id": "b"}}
|
||||
@@ -4267,6 +4311,7 @@ async def test_start_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# update state
|
||||
await tool_two.aupdate_state(thread3, {"my_key": "key"}) # appends to my_key
|
||||
@@ -4297,6 +4342,7 @@ async def test_start_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert await tool_two.ainvoke(None, thread3, debug=1) == {
|
||||
@@ -4330,6 +4376,7 @@ async def test_start_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -4872,6 +4919,7 @@ async def test_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert await tool_two.ainvoke(None, thread1, debug=1) == {
|
||||
@@ -4904,6 +4952,7 @@ async def test_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
thread2 = {"configurable": {"thread_id": "12"}}
|
||||
@@ -4938,6 +4987,7 @@ async def test_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert await tool_two.ainvoke(None, thread2, debug=1) == {
|
||||
@@ -4970,6 +5020,7 @@ async def test_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
tool_two = tool_two_graph.compile(
|
||||
@@ -5012,6 +5063,7 @@ async def test_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert await tool_two.ainvoke(None, thread1, debug=1) == {
|
||||
@@ -5044,6 +5096,7 @@ async def test_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
thread2 = {"configurable": {"thread_id": "22"}}
|
||||
@@ -5078,6 +5131,7 @@ async def test_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert await tool_two.ainvoke(None, thread2, debug=1) == {
|
||||
@@ -5110,6 +5164,7 @@ async def test_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
thread3 = {"configurable": {"thread_id": "23"}}
|
||||
@@ -5132,6 +5187,7 @@ async def test_branch_then(checkpointer_name: str) -> None:
|
||||
"thread_id": "23",
|
||||
},
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
)
|
||||
# run from this point
|
||||
assert await tool_two.ainvoke(None, thread3) == {
|
||||
@@ -5159,6 +5215,7 @@ async def test_branch_then(checkpointer_name: str) -> None:
|
||||
"thread_id": "23",
|
||||
},
|
||||
parent_config=(None if "shallow" in checkpointer_name else uconfig),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume, for same result as above
|
||||
assert await tool_two.ainvoke(None, thread3, debug=1) == {
|
||||
@@ -5191,6 +5248,7 @@ async def test_branch_then(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -5287,6 +5345,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# now, get_state with subgraphs state
|
||||
assert await app.aget_state(config, subgraphs=True) == StateSnapshot(
|
||||
@@ -5353,6 +5412,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -5383,6 +5443,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# get_state_history returns outer graph checkpoints
|
||||
history = [c async for c in app.aget_state_history(config)]
|
||||
@@ -5429,6 +5490,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "my value"},
|
||||
@@ -5463,6 +5525,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
"checkpoint_id": AnyStr(),
|
||||
}
|
||||
},
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={},
|
||||
@@ -5491,6 +5554,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -5550,6 +5614,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
),
|
||||
tasks=(PregelTask(AnyStr(), "inner_2", (PULL, "inner_2")),),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value"},
|
||||
@@ -5598,6 +5663,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={},
|
||||
@@ -5634,6 +5700,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
result={"my_key": "hi my value"},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -5677,6 +5744,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# test full history at the end
|
||||
actual_history = [c async for c in app.aget_state_history(config)]
|
||||
@@ -5715,6 +5783,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value here and there"},
|
||||
@@ -5749,6 +5818,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
"checkpoint_id": AnyStr(),
|
||||
}
|
||||
},
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value"},
|
||||
@@ -5789,6 +5859,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
"checkpoint_id": AnyStr(),
|
||||
}
|
||||
},
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "my value"},
|
||||
@@ -5823,6 +5894,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
"checkpoint_id": AnyStr(),
|
||||
}
|
||||
},
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={},
|
||||
@@ -5851,6 +5923,7 @@ async def test_nested_graph_state(checkpointer_name: str) -> None:
|
||||
},
|
||||
created_at=AnyStr(),
|
||||
parent_config=None,
|
||||
interrupts=(),
|
||||
),
|
||||
]
|
||||
if "shallow" in checkpointer_name:
|
||||
@@ -5970,6 +6043,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
child_state = await app.aget_state(outer_state.tasks[0].state)
|
||||
assert child_state == StateSnapshot(
|
||||
@@ -6031,6 +6105,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
grandchild_state = await app.aget_state(child_state.tasks[0].state)
|
||||
assert grandchild_state == StateSnapshot(
|
||||
@@ -6095,6 +6170,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# get state with subgraphs
|
||||
assert await app.aget_state(config, subgraphs=True) == StateSnapshot(
|
||||
@@ -6186,6 +6262,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -6229,6 +6306,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -6259,6 +6337,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# resume
|
||||
assert [c async for c in app.astream(None, config, subgraphs=True)] == [
|
||||
@@ -6311,6 +6390,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -6352,6 +6432,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
"checkpoint_id": AnyStr(),
|
||||
}
|
||||
},
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value here and there"},
|
||||
@@ -6383,6 +6464,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
id=AnyStr(), name="parent_2", path=(PULL, "parent_2")
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value"},
|
||||
@@ -6422,6 +6504,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
"checkpoint_id": AnyStr(),
|
||||
}
|
||||
},
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "my value"},
|
||||
@@ -6453,6 +6536,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
id=AnyStr(), name="parent_1", path=(PULL, "parent_1")
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={},
|
||||
@@ -6478,6 +6562,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
id=AnyStr(), name="__start__", path=(PULL, "__start__")
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
][0]
|
||||
)
|
||||
@@ -6523,6 +6608,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
},
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value"},
|
||||
@@ -6574,6 +6660,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
result={"my_key": "hi my value here and there"},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={},
|
||||
@@ -6610,6 +6697,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
result={"my_key": "hi my value"},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
]
|
||||
# get grandchild graph history
|
||||
@@ -6674,6 +6762,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
}
|
||||
},
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value here"},
|
||||
@@ -6737,6 +6826,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
result={"my_key": "hi my value here and there"},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={"my_key": "hi my value"},
|
||||
@@ -6800,6 +6890,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
result={"my_key": "hi my value here"},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values={},
|
||||
@@ -6850,6 +6941,7 @@ async def test_doubly_nested_graph_state(checkpointer_name: str) -> None:
|
||||
result={"my_key": "hi my value"},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -7131,6 +7223,7 @@ async def test_weather_subgraph(
|
||||
},
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
# confirm that list() delegates to alist() correctly
|
||||
assert await asyncio.to_thread(get_first_in_list) == state
|
||||
@@ -7270,6 +7363,7 @@ async def test_weather_subgraph(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
tasks=(
|
||||
PregelTask(
|
||||
id=AnyStr(),
|
||||
@@ -7280,6 +7374,7 @@ async def test_weather_subgraph(
|
||||
),
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
await graph.aupdate_state(
|
||||
state.tasks[0].state.config,
|
||||
@@ -7319,6 +7414,7 @@ async def test_weather_subgraph(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
tasks=(
|
||||
PregelTask(
|
||||
id=AnyStr(),
|
||||
@@ -7385,6 +7481,7 @@ async def test_weather_subgraph(
|
||||
}
|
||||
),
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -2491,6 +2491,7 @@ def test_in_one_fan_out_state_graph_waiting_edge(
|
||||
"thread_id": "2",
|
||||
},
|
||||
parent_config=expected_parent_config,
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
assert [c for c in app_w_interrupt.stream(None, config, debug=1)] == [
|
||||
@@ -5224,6 +5225,7 @@ def test_parent_command(request: pytest.FixtureRequest, checkpointer_name: str)
|
||||
}
|
||||
),
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -650,6 +650,13 @@ async def test_dynamic_interrupt(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(
|
||||
Interrupt(
|
||||
value="Just because...",
|
||||
resumable=True,
|
||||
ns=[AnyStr("tool_two:")],
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
# clear the interrupt and next tasks
|
||||
@@ -676,6 +683,7 @@ async def test_dynamic_interrupt(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -848,6 +856,13 @@ async def test_dynamic_interrupt_subgraph(checkpointer_name: str) -> None:
|
||||
c async for c in tool_two.checkpointer.alist(thread1root, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(
|
||||
Interrupt(
|
||||
value="Just because...",
|
||||
resumable=True,
|
||||
ns=[AnyStr("tool_two:"), AnyStr("do:")],
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
# clear the interrupt and next tasks
|
||||
@@ -874,6 +889,7 @@ async def test_dynamic_interrupt_subgraph(checkpointer_name: str) -> None:
|
||||
c async for c in tool_two.checkpointer.alist(thread1root, limit=2)
|
||||
][-1].config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -1047,6 +1063,13 @@ async def test_copy_checkpoint(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].config
|
||||
),
|
||||
interrupts=(
|
||||
Interrupt(
|
||||
value="Just because...",
|
||||
resumable=True,
|
||||
ns=[AnyStr("tool_two:")],
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
if "shallow" in checkpointer_name:
|
||||
@@ -1088,6 +1111,7 @@ async def test_copy_checkpoint(checkpointer_name: str) -> None:
|
||||
-1
|
||||
].parent_config
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -2900,6 +2924,7 @@ async def test_send_dedupe_on_resume(
|
||||
}
|
||||
},
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=[
|
||||
@@ -2946,6 +2971,7 @@ async def test_send_dedupe_on_resume(
|
||||
result=["3"],
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=[
|
||||
@@ -3013,6 +3039,7 @@ async def test_send_dedupe_on_resume(
|
||||
result=["3"],
|
||||
),
|
||||
),
|
||||
interrupts=(Interrupt(value="Bahh", resumable=False, ns=None),),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=["0", "1"],
|
||||
@@ -3068,6 +3095,7 @@ async def test_send_dedupe_on_resume(
|
||||
result=["3.1"],
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=["0"],
|
||||
@@ -3105,6 +3133,7 @@ async def test_send_dedupe_on_resume(
|
||||
result=["1"],
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
StateSnapshot(
|
||||
values=[],
|
||||
@@ -3136,6 +3165,7 @@ async def test_send_dedupe_on_resume(
|
||||
result=["0"],
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
),
|
||||
]
|
||||
if checkpoint_during:
|
||||
@@ -3338,6 +3368,7 @@ async def test_send_react_interrupt(checkpointer_name: str) -> None:
|
||||
result=None,
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# remove the tool call, clearing the pending task
|
||||
@@ -3391,6 +3422,7 @@ async def test_send_react_interrupt(checkpointer_name: str) -> None:
|
||||
}
|
||||
),
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# tool call not executed
|
||||
@@ -3496,6 +3528,7 @@ async def test_send_react_interrupt(checkpointer_name: str) -> None:
|
||||
result=None,
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# replace the tool call, should clear previous send, create new one
|
||||
@@ -3587,6 +3620,7 @@ async def test_send_react_interrupt(checkpointer_name: str) -> None:
|
||||
result=None,
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# prev tool call not executed, new tool call is
|
||||
@@ -3804,6 +3838,7 @@ async def test_send_react_interrupt_control(
|
||||
result=None,
|
||||
),
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# remove the tool call, clearing the pending task
|
||||
@@ -3857,6 +3892,7 @@ async def test_send_react_interrupt_control(
|
||||
}
|
||||
),
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
# tool call not executed
|
||||
@@ -4937,6 +4973,7 @@ async def test_in_one_fan_out_state_graph_waiting_edge_custom_state_class(
|
||||
}
|
||||
}
|
||||
),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
async with assert_ctx_once():
|
||||
@@ -6635,6 +6672,7 @@ async def test_parent_command(checkpointer_name: str) -> None:
|
||||
}
|
||||
),
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -183,6 +183,7 @@ def test_get_state():
|
||||
created_at="timestamp",
|
||||
parent_config=None,
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -240,6 +241,7 @@ async def test_aget_state():
|
||||
}
|
||||
},
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -290,6 +292,7 @@ def test_get_state_history():
|
||||
created_at="timestamp",
|
||||
parent_config=None,
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
@@ -343,6 +346,7 @@ async def test_aget_state_history():
|
||||
created_at="timestamp",
|
||||
parent_config=None,
|
||||
tasks=(),
|
||||
interrupts=(),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user