diff --git a/langgraph/channels/any_value.py b/langgraph/channels/any_value.py index d6a2d4e52..caddc05bf 100644 --- a/langgraph/channels/any_value.py +++ b/langgraph/channels/any_value.py @@ -3,7 +3,8 @@ from typing import Generator, Generic, Optional, Sequence, Type from typing_extensions import Self -from langgraph.channels.base import BaseChannel, EmptyChannelError, Value +from langgraph.channels.base import BaseChannel, Value +from langgraph.errors import EmptyChannelError class AnyValue(Generic[Value], BaseChannel[Value, Value, Value]): diff --git a/langgraph/channels/base.py b/langgraph/channels/base.py index 368910523..0b8083cf0 100644 --- a/langgraph/channels/base.py +++ b/langgraph/channels/base.py @@ -15,25 +15,13 @@ from typing import ( from typing_extensions import Self from langgraph.checkpoint.base import Checkpoint +from langgraph.errors import EmptyChannelError Value = TypeVar("Value") Update = TypeVar("Update") C = TypeVar("C") -class EmptyChannelError(Exception): - """Raised when attempting to get the value of a channel that hasn't been updated - for the first time yet.""" - - pass - - -class InvalidUpdateError(Exception): - """Raised when attempting to update a channel with an invalid sequence of updates.""" - - pass - - class BaseChannel(Generic[Value, Update, C], ABC): @property @abstractmethod diff --git a/langgraph/channels/binop.py b/langgraph/channels/binop.py index 53a6c9f5d..6cef26cee 100644 --- a/langgraph/channels/binop.py +++ b/langgraph/channels/binop.py @@ -3,7 +3,8 @@ from typing import Callable, Generator, Generic, Optional, Sequence, Type from typing_extensions import Self -from langgraph.channels.base import BaseChannel, EmptyChannelError, Value +from langgraph.channels.base import BaseChannel, Value +from langgraph.errors import EmptyChannelError class BinaryOperatorAggregate(Generic[Value], BaseChannel[Value, Value, Value]): diff --git a/langgraph/channels/context.py b/langgraph/channels/context.py index fca05d950..205f9d6d3 100644 --- a/langgraph/channels/context.py +++ b/langgraph/channels/context.py @@ -14,12 +14,8 @@ from typing import ( from typing_extensions import Self -from langgraph.channels.base import ( - BaseChannel, - EmptyChannelError, - InvalidUpdateError, - Value, -) +from langgraph.channels.base import BaseChannel, Value +from langgraph.errors import EmptyChannelError, InvalidUpdateError class Context(Generic[Value], BaseChannel[Value, None, None]): diff --git a/langgraph/channels/dynamic_barrier_value.py b/langgraph/channels/dynamic_barrier_value.py index efb9dc68b..40758bc0a 100644 --- a/langgraph/channels/dynamic_barrier_value.py +++ b/langgraph/channels/dynamic_barrier_value.py @@ -3,12 +3,8 @@ from typing import Generator, Generic, NamedTuple, Optional, Sequence, Type, Uni from typing_extensions import Self -from langgraph.channels.base import ( - BaseChannel, - EmptyChannelError, - InvalidUpdateError, - Value, -) +from langgraph.channels.base import BaseChannel, Value +from langgraph.errors import EmptyChannelError, InvalidUpdateError class WaitForNames(NamedTuple): diff --git a/langgraph/channels/ephemeral_value.py b/langgraph/channels/ephemeral_value.py index fb0a27e2f..b880f9f2f 100644 --- a/langgraph/channels/ephemeral_value.py +++ b/langgraph/channels/ephemeral_value.py @@ -3,12 +3,8 @@ from typing import Generator, Generic, Optional, Sequence, Type from typing_extensions import Self -from langgraph.channels.base import ( - BaseChannel, - EmptyChannelError, - InvalidUpdateError, - Value, -) +from langgraph.channels.base import BaseChannel, Value +from langgraph.errors import EmptyChannelError, InvalidUpdateError class EphemeralValue(Generic[Value], BaseChannel[Value, Value, Value]): diff --git a/langgraph/channels/last_value.py b/langgraph/channels/last_value.py index fd7495e02..c3748b7f9 100644 --- a/langgraph/channels/last_value.py +++ b/langgraph/channels/last_value.py @@ -3,12 +3,8 @@ from typing import Generator, Generic, Optional, Sequence, Type from typing_extensions import Self -from langgraph.channels.base import ( - BaseChannel, - EmptyChannelError, - InvalidUpdateError, - Value, -) +from langgraph.channels.base import BaseChannel, Value +from langgraph.errors import EmptyChannelError, InvalidUpdateError class LastValue(Generic[Value], BaseChannel[Value, Value, Value]): diff --git a/langgraph/channels/named_barrier_value.py b/langgraph/channels/named_barrier_value.py index 0b42686ed..5c6072155 100644 --- a/langgraph/channels/named_barrier_value.py +++ b/langgraph/channels/named_barrier_value.py @@ -3,12 +3,8 @@ from typing import Generator, Generic, Optional, Sequence, Type from typing_extensions import Self -from langgraph.channels.base import ( - BaseChannel, - EmptyChannelError, - InvalidUpdateError, - Value, -) +from langgraph.channels.base import BaseChannel, Value +from langgraph.errors import EmptyChannelError, InvalidUpdateError class NamedBarrierValue(Generic[Value], BaseChannel[Value, Value, set[Value]]): diff --git a/langgraph/errors.py b/langgraph/errors.py new file mode 100644 index 000000000..55fd3fc96 --- /dev/null +++ b/langgraph/errors.py @@ -0,0 +1,15 @@ +class GraphRecursionError(RecursionError): + pass + + +class EmptyChannelError(Exception): + """Raised when attempting to get the value of a channel that hasn't been updated + for the first time yet.""" + + pass + + +class InvalidUpdateError(Exception): + """Raised when attempting to update a channel with an invalid sequence of updates.""" + + pass diff --git a/langgraph/graph/state.py b/langgraph/graph/state.py index c2e6e1a00..6b180a701 100644 --- a/langgraph/graph/state.py +++ b/langgraph/graph/state.py @@ -7,7 +7,7 @@ from langchain_core.pydantic_v1 import BaseModel from langchain_core.runnables import Runnable, RunnableConfig from langchain_core.runnables.base import RunnableLike -from langgraph.channels.base import BaseChannel, InvalidUpdateError +from langgraph.channels.base import BaseChannel from langgraph.channels.binop import BinaryOperatorAggregate from langgraph.channels.dynamic_barrier_value import DynamicBarrierValue, WaitForNames from langgraph.channels.ephemeral_value import EphemeralValue @@ -15,6 +15,7 @@ from langgraph.channels.last_value import LastValue from langgraph.channels.named_barrier_value import NamedBarrierValue from langgraph.checkpoint import BaseCheckpointSaver from langgraph.constants import TAG_HIDDEN +from langgraph.errors import InvalidUpdateError from langgraph.graph.graph import END, START, Branch, CompiledGraph, Graph from langgraph.pregel.read import ChannelRead, PregelNode from langgraph.pregel.types import All diff --git a/langgraph/pregel/__init__.py b/langgraph/pregel/__init__.py index 75321bf46..4289bd5a3 100644 --- a/langgraph/pregel/__init__.py +++ b/langgraph/pregel/__init__.py @@ -52,7 +52,6 @@ from langgraph.channels.base import ( BaseChannel, ChannelsManager, EmptyChannelError, - InvalidUpdateError, create_checkpoint, ) from langgraph.checkpoint.base import ( @@ -67,6 +66,7 @@ from langgraph.constants import ( INTERRUPT, TAG_HIDDEN, ) +from langgraph.errors import GraphRecursionError, InvalidUpdateError from langgraph.pregel.debug import ( map_debug_checkpoint, map_debug_task_results, @@ -101,10 +101,6 @@ WriteValue = Union[ ] -class GraphRecursionError(RecursionError): - pass - - def _coerce_write_value(value: WriteValue) -> Runnable[Input, Output]: if not isinstance(value, Runnable) and not callable(value): return coerce_to_runnable(lambda _: value) diff --git a/tests/test_channels.py b/tests/test_channels.py index 6f24ba765..313b4373a 100644 --- a/tests/test_channels.py +++ b/tests/test_channels.py @@ -6,11 +6,11 @@ import httpx import pytest from pytest_mock import MockerFixture -from langgraph.channels.base import EmptyChannelError, InvalidUpdateError from langgraph.channels.binop import BinaryOperatorAggregate from langgraph.channels.context import Context from langgraph.channels.last_value import LastValue from langgraph.channels.topic import Topic +from langgraph.errors import EmptyChannelError, InvalidUpdateError def test_last_value() -> None: diff --git a/tests/test_pregel.py b/tests/test_pregel.py index c4f8e1e74..47dc14e79 100644 --- a/tests/test_pregel.py +++ b/tests/test_pregel.py @@ -12,12 +12,12 @@ from langchain_core.runnables import RunnableLambda, RunnablePassthrough from pytest_mock import MockerFixture from syrupy import SnapshotAssertion -from langgraph.channels.base import InvalidUpdateError from langgraph.channels.binop import BinaryOperatorAggregate from langgraph.channels.context import Context from langgraph.channels.last_value import LastValue from langgraph.channels.topic import Topic from langgraph.checkpoint.sqlite import SqliteSaver +from langgraph.errors import InvalidUpdateError from langgraph.graph import END, Graph from langgraph.graph.message import MessageGraph from langgraph.graph.state import StateGraph diff --git a/tests/test_pregel_async.py b/tests/test_pregel_async.py index d0cf8a161..381c9b906 100644 --- a/tests/test_pregel_async.py +++ b/tests/test_pregel_async.py @@ -20,12 +20,12 @@ from langchain_core.runnables import RunnableConfig, RunnableLambda, RunnablePas from pytest_mock import MockerFixture from syrupy import SnapshotAssertion -from langgraph.channels.base import InvalidUpdateError from langgraph.channels.binop import BinaryOperatorAggregate from langgraph.channels.context import Context from langgraph.channels.last_value import LastValue from langgraph.channels.topic import Topic from langgraph.checkpoint.aiosqlite import AsyncSqliteSaver +from langgraph.errors import InvalidUpdateError from langgraph.graph import END, Graph, StateGraph from langgraph.graph.message import MessageGraph from langgraph.prebuilt.chat_agent_executor import (