diff --git a/CHANGELOG.md b/CHANGELOG.md index 03a2243ed..ee61c44c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,10 @@ to include examples, links to docs, or any other relevant information. ### Changed +- The `deepagents` extra now requires `deepagents>=0.7,<0.8` (was `<0.7`). Because + deepagents 0.7 requires `langsmith>=0.10.9`, the `langsmith` extra now allows + `langsmith<0.13` (was `<0.9`). + ### Deprecated ### :boom: Breaking Changes @@ -52,6 +56,10 @@ to include examples, links to docs, or any other relevant information. ### Fixed +- `temporalio.contrib.deepagents.TemporalBackend` is fixed for deepagents 0.7 compatibility + (e.g., adding `delete` / `adelete`). +- `temporalio.contrib.deepagents.TemporalBackend` now forwards the per-command `timeout` of + deepagents' `execute` tool for a wrapped sandbox backend such as `LocalShellBackend`. - `GoogleAdkPlugin` now passes the optional `anthropic`, `litellm`, and `openai` SDKs through the workflow sandbox. - `contrib.deepagents`: prevent duplicate input messages after continue-as-new. diff --git a/pyproject.toml b/pyproject.toml index a83b34cd7..9da89917d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,11 +31,11 @@ pydantic = ["pydantic>=2.0.0,<3"] openai-agents = ["openai-agents>=0.19.2,<0.20", "mcp>=1.9.4, <2"] google-adk = ["google-adk>=2.8.0,<3", "mcp>=1.24,<2"] langgraph = ["langgraph>=1.1.0"] -langsmith = ["langsmith>=0.7.34,<0.9"] +langsmith = ["langsmith>=0.7.34,<0.13"] deepagents = [ - "deepagents>=0.6.12,<0.7; python_version >= '3.11'", - "langchain>=1.3.11,<2; python_version >= '3.11'", - "langchain-core>=1.4.8,<2; python_version >= '3.11'", + "deepagents>=0.7,<0.8; python_version >= '3.11'", + "langchain>=1.3.14,<2; python_version >= '3.11'", + "langchain-core>=1.5.0,<2; python_version >= '3.11'", ] lambda-worker-otel = [ "opentelemetry-api>=1.26,<2", @@ -96,11 +96,11 @@ dev = [ "pytest-xdist>=3.6,<4", "moto[s3,server]>=5", "langgraph>=1.1.0", - "langsmith>=0.7.34,<0.9", - "deepagents>=0.6.12,<0.7; python_version >= '3.11'", - "langchain>=1.3.11,<2; python_version >= '3.11'", - "langchain-core>=1.4.8,<2; python_version >= '3.11'", - "langchain-anthropic>=1.4.7; python_version >= '3.11'", + "langsmith>=0.7.34,<0.13", + "deepagents>=0.7,<0.8; python_version >= '3.11'", + "langchain>=1.3.14,<2; python_version >= '3.11'", + "langchain-core>=1.5.0,<2; python_version >= '3.11'", + "langchain-anthropic>=1.5.3; python_version >= '3.11'", "setuptools<82", "opentelemetry-exporter-otlp-proto-grpc>=1.11.1,<2", "opentelemetry-semantic-conventions>=0.40b0,<1", diff --git a/temporalio/contrib/deepagents/_tools.py b/temporalio/contrib/deepagents/_tools.py index b0d8d705f..05b3da8b8 100644 --- a/temporalio/contrib/deepagents/_tools.py +++ b/temporalio/contrib/deepagents/_tools.py @@ -27,6 +27,7 @@ from __future__ import annotations import importlib +import inspect import threading import uuid as _uuid import warnings @@ -386,6 +387,7 @@ def _is_coroutine(fn: Any) -> bool: "adownload_files": "download_files", "aupload_files": "upload_files", "aexecute": "execute", + "adelete": "delete", } _original_backend_async_defaults: dict[str, Any] = {} @@ -462,6 +464,7 @@ def uninstall_backend_async_patch() -> None: "download_files", "upload_files", "execute", + "delete", # Async twins (what FilesystemMiddleware actually calls). "als", "als_info", @@ -475,8 +478,20 @@ def uninstall_backend_async_patch() -> None: "adownload_files", "aupload_files", "aexecute", + "adelete", ) +# Capability-gated ops. deepagents decides whether a backend has ``delete`` from +# the CLASS (``type(backend).delete`` against the protocol default) and whether +# it can ``execute`` from a nominal ``isinstance`` check against +# ``SandboxBackendProtocol`` (an ABC subclass, not a structural Protocol). +# Neither can be answered per instance, so the wrapper mirrors the inner +# backend at class level; see :func:`_wrapper_class_for`. Some probes read the +# method's SIGNATURE as well (``execute_accepts_timeout`` looks for a +# ``timeout`` parameter on ``type(backend).execute``), so these dispatchers +# also carry the inner method's signature; see :func:`_make_backend_op`. +_OPTIONAL_OPS = frozenset({"delete", "adelete", "execute", "aexecute"}) + class TemporalBackend: """Route a real-I/O backend's operations through Temporal activities. @@ -491,6 +506,25 @@ class TemporalBackend: metadata / configuration the agent reads (but that does no I/O) still works. """ + def __new__( + cls, + inner: Any, + *, + activity_options: Mapping[str, Any] | None = None, + ) -> "TemporalBackend": + """Pick the wrapper class that mirrors ``inner``'s optional capabilities. + + Applies to subclasses too: a user's ``class MyBackend(TemporalBackend)`` + gets a mirrored subclass of ``MyBackend``, so ``isinstance`` and any + methods it defines are preserved. + """ + target: type[TemporalBackend] = ( + cls + if getattr(cls, "_temporal_mirror_of", None) is not None + else _wrapper_class_for(inner, cls) + ) + return object.__new__(target) + def __init__( self, inner: Any, @@ -533,14 +567,113 @@ async def _dispatch(self, op: str, *args: Any, **kwargs: Any) -> Any: return _serde.load_backend_result(output.result) def __getattr__(self, name: str) -> Any: - """Bound-method access for a known I/O op returns an activity dispatcher. + """Forward anything that is not an I/O op to the inner backend unchanged.""" + return getattr(self._inner, name) - Everything else forwards to the inner backend unchanged. - """ - if name in _BACKEND_OPS: - async def _op(*args: Any, **kwargs: Any) -> Any: - return await self._dispatch(name, *args, **kwargs) +def _make_backend_op(name: str, mirror: Any = None) -> Callable[..., Any]: + """Build the activity dispatcher for backend op ``name``. + + ``mirror`` is the inner backend's own method for the op. When given, the + dispatcher advertises that method's signature (through ``__signature__``; + it still accepts and forwards any arguments). deepagents probes some + capabilities by signature: ``execute_accepts_timeout`` looks for a + ``timeout`` parameter on ``type(backend).execute`` and, unlike the + ``max_count`` probe, does not take ``**kwargs`` as a stand-in, so a bare + ``(*args, **kwargs)`` dispatcher made a wrapped ``LocalShellBackend`` + refuse the per-command ``timeout`` its unwrapped self accepts. Carrying the + inner signature keeps every such probe answering exactly as it does for the + inner backend, including for a sandbox that does *not* accept ``timeout`` + (deepagents then declines the call up front instead of the activity failing + on an unexpected keyword). + """ - return _op - return getattr(self._inner, name) + async def _op(self: TemporalBackend, *args: Any, **kwargs: Any) -> Any: + return await self._dispatch(name, *args, **kwargs) + + _op.__name__ = _op.__qualname__ = name + if mirror is not None: + try: + signature = inspect.signature(mirror) + except (TypeError, ValueError): + pass + else: + setattr(_op, "__signature__", signature) + return _op + + +# The I/O ops are real class-level methods, not ``__getattr__`` products, so +# class-based capability checks in deepagents see them. +for _op_name in _BACKEND_OPS: + if _op_name not in _OPTIONAL_OPS: + setattr(TemporalBackend, _op_name, _make_backend_op(_op_name)) + +_wrapper_classes: dict[tuple[type, type, bool, bool], type[TemporalBackend]] = {} + + +def _wrapper_class_for( + inner: Any, base: type[TemporalBackend] +) -> type[TemporalBackend]: + """Return the subclass of ``base`` whose optional capabilities mirror ``inner``. + + ``delete`` / ``adelete``: a delete-capable inner backend gets dispatchers + like every other op; any other inner backend keeps the protocol defaults, + so deepagents disables its delete tool exactly as it would for the + unwrapped backend. Execution: deepagents offers its shell tool only to a + nominal ``SandboxBackendProtocol`` instance, so when deepagents reports the + inner backend as execution-capable the mirror also derives from that class + (with ``execute`` / ``aexecute`` dispatchers and ``id`` forwarded); a wrapper + around a plain filesystem or store backend stays a non-sandbox class. The + dispatchers built here carry the inner methods' signatures, which deepagents + reads for finer probes such as ``execute_accepts_timeout``; see + :func:`_make_backend_op`. An op that ``base`` already defines (a user + subclass) is left alone. Without deepagents installed there is nothing to + mirror and ``base`` is used as-is. + """ + try: + protocol = importlib.import_module("deepagents.backends.protocol") + filesystem = importlib.import_module("deepagents.middleware.filesystem") + except ImportError: + return base + inner_cls = type(inner) + default_delete = protocol.BackendProtocol.delete + has_delete = getattr(inner_cls, "delete", default_delete) is not default_delete + has_execute = bool(filesystem.supports_execution(inner)) + # Keyed by the inner CLASS too, since the dispatchers carry its method + # signatures. ``has_execute`` stays in the key: for a ``CompositeBackend`` + # deepagents answers it per instance, from the default backend. + key = (base, inner_cls, has_delete, has_execute) + cls = _wrapper_classes.get(key) + if cls is None: + namespace: dict[str, Any] = { + "__module__": base.__module__, + "__qualname__": base.__qualname__, + "__doc__": base.__doc__, + "_temporal_mirror_of": base, + } + for op in ("delete", "adelete"): + if hasattr(base, op): + continue + namespace[op] = ( + _make_backend_op(op, mirror=getattr(inner_cls, op, None)) + if has_delete + else getattr(protocol.BackendProtocol, op) + ) + bases: tuple[type, ...] = (base,) + if has_execute: + sandbox_cls = protocol.SandboxBackendProtocol + if not issubclass(base, sandbox_cls): + bases = (base, sandbox_cls) + for op in ("execute", "aexecute"): + if not hasattr(base, op): + namespace[op] = _make_backend_op( + op, mirror=getattr(inner_cls, op, None) + ) + if not hasattr(base, "id"): + # The sandbox class defines ``id``; keep reading the inner + # backend's, which ``__getattr__`` would otherwise have served. + namespace["id"] = property(lambda self: self._inner.id) + # Workflow tasks run on a thread pool, so two runs can build the same + # key at once; the first class stored wins for both callers. + cls = _wrapper_classes.setdefault(key, type(base.__name__, bases, namespace)) + return cls diff --git a/temporalio/contrib/langsmith/_interceptor.py b/temporalio/contrib/langsmith/_interceptor.py index a7eea0714..46d460d4b 100644 --- a/temporalio/contrib/langsmith/_interceptor.py +++ b/temporalio/contrib/langsmith/_interceptor.py @@ -336,8 +336,13 @@ def end(self, **kwargs: Any) -> None: kwargs.setdefault("end_time", temporalio.workflow.now()) self._run.end(**kwargs) - def patch(self, *, exclude_inputs: bool = False) -> None: - """Patch the run to LangSmith, skipping during replay.""" + def patch(self, *, exclude_inputs: bool | None = None) -> None: + """Patch the run to LangSmith, skipping during replay. + + ``exclude_inputs`` is forwarded untouched so LangSmith's own default + applies (a plain ``False`` before 0.11; the + ``LANGSMITH_EXCLUDE_INPUTS_ON_PATCH`` setting from 0.11 on). + """ if temporalio.workflow.in_workflow(): if _is_replaying(): return @@ -394,7 +399,7 @@ def post(self, exclude_child_runs: bool = True) -> NoReturn: """Factory must never be posted.""" raise RuntimeError("_RootReplaySafeRunTreeFactory must never be posted") - def patch(self, *, exclude_inputs: bool = False) -> NoReturn: + def patch(self, *, exclude_inputs: bool | None = None) -> NoReturn: """Factory must never be patched.""" raise RuntimeError("_RootReplaySafeRunTreeFactory must never be patched") diff --git a/tests/contrib/deepagents/test_backends.py b/tests/contrib/deepagents/test_backends.py index d21f812a0..997f1cc0a 100644 --- a/tests/contrib/deepagents/test_backends.py +++ b/tests/contrib/deepagents/test_backends.py @@ -13,6 +13,7 @@ from __future__ import annotations import gc +import inspect import sys import uuid from datetime import timedelta @@ -57,6 +58,14 @@ def read(self, file_path: str) -> str: async def aread(self, file_path: str) -> str: return f"acontents of {file_path}" + # ``delete`` is optional in the protocol (deepagents >= 0.7); a backend that + # has it must still cross the activity boundary like every other op. + async def adelete(self, file_path: str) -> str: + return f"deleted {file_path}" + + def delete(self, file_path: str) -> str: + return f"deleted {file_path}" + @workflow.defn class BackendWorkflow: @@ -68,7 +77,8 @@ async def run(self, path: str) -> str: ) sync_out = await backend.read(path) async_out = await backend.aread(path) - return f"{sync_out}|{async_out}" + deleted = await backend.adelete(path) + return f"{sync_out}|{async_out}|{deleted}" # Bind deepagents symbols off the module importorskip returns: a static @@ -79,6 +89,7 @@ async def run(self, path: str) -> str: _backends_mod = pytest.importorskip("deepagents.backends") create_deep_agent = _deepagents_mod.create_deep_agent FilesystemBackend = _backends_mod.FilesystemBackend +LocalShellBackend = _backends_mod.LocalShellBackend StateBackend = _backends_mod.StateBackend @@ -136,12 +147,241 @@ async def test_temporal_backend_op_activity(env: WorkflowEnvironment) -> None: ) out = await handle.result() - assert out == "contents of notes.txt|acontents of notes.txt" + assert out == "contents of notes.txt|acontents of notes.txt|deleted notes.txt" + counts = await count_scheduled_activities(handle) + # One activity per op — the sync read, the async aread, and the optional + # adelete all cross. + assert counts[BACKEND_OP] == 3, counts + + +def test_temporal_backend_mirrors_inner_delete_support() -> None: + # deepagents decides delete support from the wrapper CLASS, so a wrapper + # around a delete-capable backend must advertise it and one around a + # backend without delete must not (or the agent gets a delete tool that + # can only fail). + protocol = pytest.importorskip("deepagents.backends.protocol") + + class NoDelete: + def read(self, file_path: str) -> str: + return f"contents of {file_path}" + + with_delete = TemporalBackend(RecordingBackend()) + without_delete = TemporalBackend(NoDelete()) + assert protocol._supports_delete(with_delete) is True + assert protocol._supports_delete(without_delete) is False + assert isinstance(with_delete, TemporalBackend) + assert isinstance(without_delete, TemporalBackend) + # The real deepagents backends resolve the same way wrapped or not. + state_backend = StateBackend() + assert protocol._supports_delete( + TemporalBackend(state_backend) + ) is protocol._supports_delete(state_backend) + + +def test_temporal_backend_mirrors_inner_execution_support(tmp_path: Path) -> None: + # deepagents offers its shell tool when the backend passes an isinstance + # check against the sandbox protocol, i.e. when execute/aexecute exist on + # the object. A wrapper must only grow them when the inner backend is + # execution-capable, or a plain filesystem backend gets a shell tool whose + # every call fails in the activity. + supports_execution = pytest.importorskip( + "deepagents.middleware.filesystem" + ).supports_execution + + plain = TemporalBackend( + FilesystemBackend(root_dir=str(tmp_path), virtual_mode=True) + ) + assert supports_execution(plain) is False + assert not hasattr(plain, "aexecute") + + shell_inner = LocalShellBackend(root_dir=str(tmp_path)) + shell = TemporalBackend(shell_inner) + assert supports_execution(shell) is True + # The op is the activity dispatcher, not the inner backend's own method. + assert getattr(type(shell), "aexecute") is not type(shell_inner).aexecute + assert supports_execution(shell_inner) is True + + +def test_temporal_backend_mirrors_execute_timeout_support(tmp_path: Path) -> None: + # deepagents gates the execute tool's per-command ``timeout`` on a + # SIGNATURE probe: ``execute_accepts_timeout(type(backend))`` looks for a + # ``timeout`` parameter on ``execute`` and, unlike the ``max_count`` probe, + # does not take ``**kwargs`` as a stand-in. A bare ``(*args, **kwargs)`` + # dispatcher read False, so a wrapped LocalShellBackend refused a timeout + # its unwrapped self accepts. + protocol = pytest.importorskip("deepagents.backends.protocol") + + shell_inner = LocalShellBackend(root_dir=str(tmp_path)) + shell = TemporalBackend(shell_inner) + assert protocol.execute_accepts_timeout(type(shell_inner)) is True + assert protocol.execute_accepts_timeout(type(shell)) is True + for op in ("execute", "aexecute"): + assert inspect.signature(getattr(type(shell), op)) == inspect.signature( + getattr(type(shell_inner), op) + ) + # The ``max_count`` probe, which does accept ``**kwargs``, still passes. + assert protocol._method_accepts_max_count(type(shell), "grep") is True + + # A sandbox whose execute takes no timeout (deepagents' "older backend + # package" case) must read False wrapped too: deepagents then declines the + # call up front instead of the forwarded keyword failing inside the + # activity. Built with type(): a class statement cannot name its base off + # the importorskip module for the type checkers. + def execute_without_timeout(_self: Any, command: str) -> str: + return command + + NoTimeoutSandbox = type( + "NoTimeoutSandbox", + (protocol.SandboxBackendProtocol,), + {"execute": execute_without_timeout}, + ) + no_timeout = TemporalBackend(NoTimeoutSandbox()) + assert protocol.execute_accepts_timeout(NoTimeoutSandbox) is False + assert protocol.execute_accepts_timeout(type(no_timeout)) is False + assert type(no_timeout) is not type(shell) + + +def test_temporal_backend_subclass_keeps_capability_mirroring() -> None: + protocol = pytest.importorskip("deepagents.backends.protocol") + + class MyBackend(TemporalBackend): + def extra(self) -> str: + return "extra" + + class NoDelete: + def read(self, file_path: str) -> str: + return f"contents of {file_path}" + + class OwnDelete(TemporalBackend): + def delete(self, file_path: str) -> str: + return f"own {file_path}" + + wrapped = MyBackend(RecordingBackend()) + assert isinstance(wrapped, MyBackend) + assert wrapped.extra() == "extra" + assert protocol._supports_delete(wrapped) is True + assert protocol._supports_delete(MyBackend(NoDelete())) is False + # An op the subclass defines itself is left alone. + own = OwnDelete(NoDelete()) + assert getattr(type(own), "delete") is OwnDelete.delete + + +@workflow.defn +class ShellBackendWorkflow: + @workflow.run + async def run(self, root_dir: str) -> str: + backend = TemporalBackend( + LocalShellBackend(root_dir=root_dir), + activity_options={"start_to_close_timeout": timedelta(seconds=30)}, + ) + result = await backend.aexecute("echo shell-ok") + # The per-command timeout deepagents forwards to a timeout-capable + # sandbox crosses the activity boundary along with the command. + timed = await backend.aexecute("echo shell-timeout-ok", timeout=5) + return f"{getattr(result, 'output', result)}|{getattr(timed, 'output', timed)}" + + +@pytest.mark.asyncio +async def test_temporal_backend_execute_runs_as_activity( + env: WorkflowEnvironment, tmp_path: Path +) -> None: + plugin = DeepAgentsPlugin() + async with Worker( + env.client, + task_queue="da-shell-backend", + workflows=[ShellBackendWorkflow], + plugins=[plugin], + ): + handle = await env.client.start_workflow( + ShellBackendWorkflow.run, + str(tmp_path), + id=f"da-shell-backend-{uuid.uuid4()}", + task_queue="da-shell-backend", + ) + out = await handle.result() + + assert "shell-ok" in out + assert "shell-timeout-ok" in out counts = await count_scheduled_activities(handle) - # One activity per op — the sync read AND the async aread both cross. + # One activity per execute call; the second carried ``timeout=5``. assert counts[BACKEND_OP] == 2, counts +@workflow.defn +class ShellAgentWorkflow: + @workflow.run + async def run(self, root_dir: str) -> str: + backend = TemporalBackend( + LocalShellBackend(root_dir=root_dir), + activity_options={"start_to_close_timeout": timedelta(seconds=30)}, + ) + agent = create_deep_agent( + model="anthropic:claude-sonnet-4-5", + backend=backend, + system_prompt="Run the command, then report its output.", + ) + result = await agent.ainvoke( + {"messages": [{"role": "user", "content": "Run it."}]} + ) + # The execute tool's own message says whether deepagents ran the + # command or declined the timeout up front. + return "\n".join(str(m.content) for m in result["messages"] if m.type == "tool") + + +@pytest.mark.asyncio +async def test_agent_execute_tool_forwards_timeout_through_backend( + env: WorkflowEnvironment, tmp_path: Path +) -> None: + """deepagents' built-in ``execute`` tool, called WITH a per-command + ``timeout``, runs through a TemporalBackend-wrapped LocalShellBackend. + + Regression: deepagents gates the timeout on + ``execute_accepts_timeout(type(backend))``, a signature probe for a + ``timeout`` parameter on ``execute``. The dispatcher's bare + ``(*args, **kwargs)`` read False, so the tool answered "does not support + per-command timeout overrides" for a backend that accepts one unwrapped. + """ + from langchain_core.messages import AIMessage + + from temporalio.contrib.deepagents.testing import mock_model_provider + + execute_turn = AIMessage( + content="", + tool_calls=[ + { + "name": "execute", + "args": {"command": "echo tool-timeout-ok", "timeout": 5}, + "id": "call-execute", + } + ], + ) + final = AIMessage(content="Done.") + plugin = DeepAgentsPlugin( + model_provider=mock_model_provider([execute_turn, final]), + ) + async with Worker( + env.client, + task_queue="da-shell-agent", + workflows=[ShellAgentWorkflow], + plugins=[plugin], + max_cached_workflows=0, + ): + handle = await env.client.start_workflow( + ShellAgentWorkflow.run, + str(tmp_path), + id=f"da-shell-agent-{uuid.uuid4()}", + task_queue="da-shell-agent", + ) + out = await handle.result() + + assert "tool-timeout-ok" in out, out + assert "does not support per-command timeout" not in out, out + counts = await count_scheduled_activities(handle) + # The command ran as an activity, not in the workflow. + assert counts[BACKEND_OP] == 1, counts + assert counts["deepagents.invoke_model"] == 2, counts + + def test_temporal_backend_unregisters_on_gc() -> None: # A wrapper is typically constructed per workflow run; its registry entry # must not outlive it, or a long-lived worker leaks one entry per run. diff --git a/tests/contrib/langsmith/test_background_io.py b/tests/contrib/langsmith/test_background_io.py index 79c48eeef..4ddd61b3d 100644 --- a/tests/contrib/langsmith/test_background_io.py +++ b/tests/contrib/langsmith/test_background_io.py @@ -235,7 +235,9 @@ def test_patch_submits_to_executor_in_workflow( tree.patch() executor.shutdown(wait=True) - mock_run.patch.assert_called_once() + # No argument means "LangSmith's default": forwarded as None, never + # resolved to a bool here (0.11 reads LANGSMITH_EXCLUDE_INPUTS_ON_PATCH). + mock_run.patch.assert_called_once_with(exclude_inputs=None) @patch(_PATCH_IN_WORKFLOW, return_value=False) def test_post_delegates_directly_outside_workflow(self, _mock_in_wf: Any) -> None: @@ -259,6 +261,19 @@ def test_patch_delegates_directly_outside_workflow(self, _mock_in_wf: Any) -> No mock_run.patch.assert_called_once_with(exclude_inputs=True) + @patch(_PATCH_IN_WORKFLOW, return_value=False) + def test_patch_forwards_langsmith_default_outside_workflow( + self, _mock_in_wf: Any + ) -> None: + """No argument is forwarded as None so LangSmith's own default applies.""" + executor = _make_executor() + mock_run = _make_mock_run() + tree = _ReplaySafeRunTree(mock_run, executor=executor) + + tree.patch() + + mock_run.patch.assert_called_once_with(exclude_inputs=None) + @patch(_PATCH_IS_REPLAYING, return_value=False) @patch(_PATCH_IN_WORKFLOW, return_value=True) def test_post_error_logged_via_done_callback( diff --git a/uv.lock b/uv.lock index cee51de68..38aba4841 100644 --- a/uv.lock +++ b/uv.lock @@ -4,12 +4,13 @@ requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.14'", "python_full_version == '3.13.*'", - "python_full_version >= '3.11' and python_full_version < '3.13'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten'", + "(python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten') or (python_full_version == '3.11.*' and sys_platform == 'emscripten')", "python_full_version < '3.11'", ] [options] -exclude-newer = "2026-08-31T19:12:49.465398Z" +exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. exclude-newer-span = "P2W" [[package]] @@ -254,21 +255,20 @@ wheels = [ [[package]] name = "anthropic" -version = "0.117.0" +version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "anyio", marker = "python_full_version >= '3.11'" }, - { name = "distro", marker = "python_full_version >= '3.11'" }, - { name = "docstring-parser", marker = "python_full_version >= '3.11'" }, - { name = "httpx", marker = "python_full_version >= '3.11'" }, - { name = "jiter", marker = "python_full_version >= '3.11'" }, - { name = "pydantic", marker = "python_full_version >= '3.11'" }, - { name = "sniffio", marker = "python_full_version >= '3.11'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.11'" }, + { name = "anyio" }, + { name = "docstring-parser" }, + { name = "httpx2" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/41/0d/8f71d535edb0d438f023bd825fb65f67c14fa88a2bd6b75f292a58a63de4/anthropic-0.117.0.tar.gz", hash = "sha256:98107f2b76439641e0ae2a1754087534b8f178dbab99d6eb1bc4b7bc8c744496", size = 989933, upload-time = "2026-07-16T19:36:13.07Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b4/50/463166f02179ab279edb61de1589a6f69cb3838d6a2fb6f2c92a3f8042f1/anthropic-1.3.0.tar.gz", hash = "sha256:6873492a77ede8849a161ab1bc78bc9a1e492a006d0b5bb4c57ac77845df838a", size = 1148177, upload-time = "2026-09-01T17:37:10.392Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/4c/917d21d6619a4475cdafc6d13a69fdb3b901ddac57e76caca5a25c117b6d/anthropic-0.117.0-py3-none-any.whl", hash = "sha256:451a0a6905f11dff7663d13e4ee5dbf909eb8942b1d049803c7b937a13ac47ec", size = 998327, upload-time = "2026-07-16T19:36:11.225Z" }, + { url = "https://files.pythonhosted.org/packages/2c/5d/7863a9961d320c23787c7b594956afe4e878f9c0ae2376b11a20e416791d/anthropic-1.3.0-py3-none-any.whl", hash = "sha256:e7e7dbebf9f3c84a23954ab989378af6ae10a4d1804c81e9fea4b5ced695ce75", size = 1296959, upload-time = "2026-09-01T17:37:08.525Z" }, ] [[package]] @@ -939,19 +939,20 @@ wheels = [ [[package]] name = "deepagents" -version = "0.6.12" +version = "0.7.12" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "langchain", marker = "python_full_version >= '3.11'" }, - { name = "langchain-anthropic", marker = "python_full_version >= '3.11'" }, - { name = "langchain-core", marker = "python_full_version >= '3.11'" }, - { name = "langchain-google-genai", marker = "python_full_version >= '3.11'" }, - { name = "langsmith", marker = "python_full_version >= '3.11'" }, - { name = "wcmatch", marker = "python_full_version >= '3.11'" }, + { name = "langchain" }, + { name = "langchain-anthropic" }, + { name = "langchain-core", version = "1.6.1", source = { registry = "https://pypi.org/simple" } }, + { name = "langchain-google-genai" }, + { name = "langsmith" }, + { name = "packaging" }, + { name = "wcmatch" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e0/db/a6acdc72a9e90c3f07ed10de35c951734a02d4facb693bb59684ad368801/deepagents-0.6.12.tar.gz", hash = "sha256:1f281c0bc5a63132f62e2ee345c1dc593b23188da6e23016401f6879fbe54b5f", size = 211364, upload-time = "2026-06-25T17:26:52.775Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b9/af/35d8adf1181a27f2d98f535d81246d73328297a5daf99c4130a5c667494e/deepagents-0.7.12.tar.gz", hash = "sha256:e5968af37f505d79bea2bf7217dad0bdaff6689950e33a1a0f82c25f7ac9fd7e", size = 297304, upload-time = "2026-09-01T18:50:18.6Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/98/49/af7219b3c13520fee047bb807cfaefba17f8e4584c551d946773589a4f08/deepagents-0.6.12-py3-none-any.whl", hash = "sha256:28b8fa0119ca0a689e3e18e288c4634e4046062acfc87a1cb34289d3af3a1c88", size = 236120, upload-time = "2026-06-25T17:26:51.736Z" }, + { url = "https://files.pythonhosted.org/packages/8b/1f/1b0080e0c76c5dfe00dfb752ebee4d3ff0778e56463fd9df19dbf8357fcd/deepagents-0.7.12-py3-none-any.whl", hash = "sha256:5df1818b515bb83098057b59a6f3dcbdd632657e17560c49a516e8d13b6b768b", size = 324239, upload-time = "2026-09-01T18:50:17.335Z" }, ] [[package]] @@ -1022,7 +1023,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1591,6 +1592,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, ] +[[package]] +name = "httpcore2" +version = "2.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "h11" }, + { name = "truststore" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/be/ad/f4f0e57345f1870f3e8cb624e058d7eca6e5a27d33bcc3311d9b618734cd/httpcore2-2.12.0.tar.gz", hash = "sha256:9293522bba0aa7c4c8e9e3f040c16575bd8868e155a77fa30c7a9085a5eae648", size = 67548, upload-time = "2026-08-18T13:22:08.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/74/d370e55600d9bcfa0d9794b0166126d49291a3d2b20c268fc98c453a4948/httpcore2-2.12.0-py3-none-any.whl", hash = "sha256:7e04258ce01013d7d615e5b910a3b27fac937d7a95038227e79652b4ba3b4ceb", size = 83074, upload-time = "2026-08-18T13:22:05.854Z" }, +] + [[package]] name = "httpx" version = "0.28.1" @@ -1615,6 +1629,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" }, ] +[[package]] +name = "httpx2" +version = "2.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio", marker = "sys_platform != 'emscripten'" }, + { name = "httpcore2", marker = "sys_platform != 'emscripten'" }, + { name = "httpx2-jsfetch", marker = "python_full_version >= '3.12' and sys_platform == 'emscripten'" }, + { name = "idna" }, + { name = "truststore", marker = "sys_platform != 'emscripten'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7f/f8/579a8b51e42e38ee32647df9f08aa25643ae788e275cc625b199829c4671/httpx2-2.12.0.tar.gz", hash = "sha256:7631fe9887a8a2275f4a2540e053aa670fcc50742864a9ae7c66e609fdcf12cf", size = 100040, upload-time = "2026-08-18T13:22:09.086Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/95/411ba65569158e862368917aaf56597f3e5fa3b91b0502919638465a08f3/httpx2-2.12.0-py3-none-any.whl", hash = "sha256:cc8b6eecb8661c146b8f89a60e97456ee086e91a784ed31ac450c3a9e613dd36", size = 95427, upload-time = "2026-08-18T13:22:06.834Z" }, +] + +[[package]] +name = "httpx2-jsfetch" +version = "1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/c4/0e5636363151a2a1795e0a77617168b9ca438e1748ec05fc9b5687f93d64/httpx2_jsfetch-1.0.tar.gz", hash = "sha256:70a0e3eabfef7cce5ad9c629f7d01ca05e418f586646f4ddf14782e4c1454c60", size = 6872, upload-time = "2026-08-07T00:13:07.492Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/43/832f631d32e4f1211caa2ba368317739fe71f0b8530e4c9d15dc454bac2a/httpx2_jsfetch-1.0-py3-none-any.whl", hash = "sha256:cb916b707601e69a07721aabc8f3f6659be3a6893bc1ff5c6f9e02241df2da32", size = 6382, upload-time = "2026-08-07T00:13:06.567Z" }, +] + [[package]] name = "huggingface-hub" version = "1.23.0" @@ -1969,36 +2009,39 @@ wheels = [ [[package]] name = "langchain" -version = "1.3.14" +version = "1.3.18" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "langchain-core", marker = "python_full_version >= '3.11'" }, - { name = "langgraph", marker = "python_full_version >= '3.11'" }, - { name = "pydantic", marker = "python_full_version >= '3.11'" }, + { name = "langchain-core", version = "1.6.1", source = { registry = "https://pypi.org/simple" } }, + { name = "langgraph", version = "1.2.11", source = { registry = "https://pypi.org/simple" } }, + { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/29/68/a6dbad9c22df4087a0f9e79ddd46226c442b30128bfeee538d5889492a73/langchain-1.3.14.tar.gz", hash = "sha256:1b6696c72ba3bbbce54d745e0180742c9f6ece8bbc59ed5a46c3e20b9a435929", size = 645181, upload-time = "2026-07-16T13:28:18.29Z" } +sdist = { url = "https://files.pythonhosted.org/packages/31/e9/0e5425e522b624d7c5c0911957b467b82890b36b0099bf727951f2ee3059/langchain-1.3.18.tar.gz", hash = "sha256:74ce99294f6f2c82ee64c3df39daa6a22085ee1449a718065b3604a88d78bf4d", size = 637052, upload-time = "2026-08-27T17:33:12.702Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/ec/0f942e78a621f8e3162ff1ed24284f469aaf51fb4607ee5831c626f2b2bc/langchain-1.3.14-py3-none-any.whl", hash = "sha256:4d10dbe91005952cddd56d0dc77aa108964da6bae90ab20063653957e901f782", size = 139560, upload-time = "2026-07-16T13:28:16.498Z" }, + { url = "https://files.pythonhosted.org/packages/f7/04/374f6014ed6959dbdab92962c2b09e4d0223ed6a82f65694870b46d2c13f/langchain-1.3.18-py3-none-any.whl", hash = "sha256:f29cbef985848e5cfff5398f3c8c1568994a3a6f2a8f4fa720df30b6e0668b9c", size = 148007, upload-time = "2026-08-27T17:33:11.23Z" }, ] [[package]] name = "langchain-anthropic" -version = "1.4.8" +version = "1.7.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "anthropic", marker = "python_full_version >= '3.11'" }, - { name = "langchain-core", marker = "python_full_version >= '3.11'" }, - { name = "pydantic", marker = "python_full_version >= '3.11'" }, + { name = "anthropic" }, + { name = "langchain-core", version = "1.6.1", source = { registry = "https://pypi.org/simple" } }, + { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/98/22/40ab129b08329ca295b391aa1d48267692b42594757084c6918e22b655ac/langchain_anthropic-1.4.8.tar.gz", hash = "sha256:c76891b2044d56105ff13c106ed12650637b53bd598a4bdf15b4796eefa2a4ec", size = 708524, upload-time = "2026-06-26T21:28:46.916Z" } +sdist = { url = "https://files.pythonhosted.org/packages/56/fc/52f6d1d6069bafb08626e204c89c49c8dd4a536eedbb94f0b7e78668594d/langchain_anthropic-1.7.0.tar.gz", hash = "sha256:d48e3c118ff8d3eea83f17b50234a2d2ff491a2375d565f212eb990e7e3856cb", size = 750068, upload-time = "2026-08-27T15:23:59.261Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/14/746235c4da89d9bc6a608c5f489f628e03feb8f697195c146e452c8f23c8/langchain_anthropic-1.4.8-py3-none-any.whl", hash = "sha256:778e9301b6fd517824f76ec1776975ce8add97a1f6a36c50ae3c2f4b03a66f7f", size = 52366, upload-time = "2026-06-26T21:28:45.535Z" }, + { url = "https://files.pythonhosted.org/packages/8e/ce/e4367713080bc750e1dba845409c058f196543d1a0dc99683e2ef062f581/langchain_anthropic-1.7.0-py3-none-any.whl", hash = "sha256:68b34369aa01dad0c67bc690b8c47e09d06bd30fb28f320ad19ddc71c4445dc0", size = 60475, upload-time = "2026-08-27T15:23:57.989Z" }, ] [[package]] name = "langchain-core" version = "1.4.9" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] dependencies = [ { name = "jsonpatch" }, { name = "langchain-protocol" }, @@ -2015,19 +2058,46 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/84/70/ade2fada52772798ef815b6352b59e71b116aa0c32c3aef5be3dc2cbed12/langchain_core-1.4.9-py3-none-any.whl", hash = "sha256:28e3909e2a10cc81504952d795ac0a9e014c0018121ef89d48dd396fa09ec624", size = 558293, upload-time = "2026-07-08T20:06:52.382Z" }, ] +[[package]] +name = "langchain-core" +version = "1.6.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version == '3.13.*'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten'", + "(python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten') or (python_full_version == '3.11.*' and sys_platform == 'emscripten')", +] +dependencies = [ + { name = "httpx" }, + { name = "jsonpatch" }, + { name = "langchain-protocol" }, + { name = "langsmith" }, + { name = "packaging" }, + { name = "pydantic" }, + { name = "pyyaml" }, + { name = "tenacity" }, + { name = "typing-extensions" }, + { name = "uuid-utils" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/90/12/aff76ca89c219ebe6f9dd3c5dbc4e3b1cf5450e9fc7037dccad23d45cd7a/langchain_core-1.6.1.tar.gz", hash = "sha256:1b156cb395aac4f009a8a1b38a574c7d948fe2d5f74c96e0d8a5017b4149e04f", size = 1003359, upload-time = "2026-08-27T19:31:14.956Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/25/f50dd65673c819aa33d3c34df58c115dbb6ec627d19f93e6e401dd0fc8d7/langchain_core-1.6.1-py3-none-any.whl", hash = "sha256:954a84132a5cb0435d27b910e336347b6744ecc18fbeef1e2de7029a0959841a", size = 571478, upload-time = "2026-08-27T19:31:13.34Z" }, +] + [[package]] name = "langchain-google-genai" -version = "4.2.7" +version = "4.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "filetype", marker = "python_full_version >= '3.11'" }, - { name = "google-genai", marker = "python_full_version >= '3.11'" }, - { name = "langchain-core", marker = "python_full_version >= '3.11'" }, - { name = "pydantic", marker = "python_full_version >= '3.11'" }, + { name = "filetype" }, + { name = "google-genai" }, + { name = "langchain-core", version = "1.6.1", source = { registry = "https://pypi.org/simple" } }, + { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1d/0c/bc60dabc362ca7c6ffe8c4bcc2f724c7e566b43eb230cee51419f88f784c/langchain_google_genai-4.2.7.tar.gz", hash = "sha256:03b1463ffe4d42435f43c7870467f2215f684bb46400d2543435d10157c80ac7", size = 281605, upload-time = "2026-07-06T13:51:58.724Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cf/4e/41798c80b574d958d189e049f13d64eb9246a66623465290f2cbfd641759/langchain_google_genai-4.4.0.tar.gz", hash = "sha256:7871beec56ac07b719f77c46997845db6ff2267b817bffb0f97877053b0895d7", size = 378415, upload-time = "2026-09-01T20:15:45.816Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b2/f9/d73d1e712591723aaddb7a7b1e94978cd2320c29acfe0d26b6169a2f26f0/langchain_google_genai-4.2.7-py3-none-any.whl", hash = "sha256:0d9c388d0e6c629718fca6abb19c6fdca728a9a7873d0324c1ec821288b5b571", size = 70702, upload-time = "2026-07-06T13:51:57.499Z" }, + { url = "https://files.pythonhosted.org/packages/2c/10/83bb535e78c2cf767a6193c2f3b00b2894c1581a36ef85911ebaa3b9a891/langchain_google_genai-4.4.0-py3-none-any.whl", hash = "sha256:8e23a1307bd2158590bbf9d99f1d658fc84a9d9ddb77fb1b372f8875a2bafbbf", size = 81617, upload-time = "2026-09-01T20:15:44.533Z" }, ] [[package]] @@ -2046,8 +2116,11 @@ wheels = [ name = "langgraph" version = "1.2.9" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] dependencies = [ - { name = "langchain-core" }, + { name = "langchain-core", version = "1.4.9", source = { registry = "https://pypi.org/simple" } }, { name = "langgraph-checkpoint" }, { name = "langgraph-prebuilt" }, { name = "langgraph-sdk" }, @@ -2059,12 +2132,36 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/41/16/0b8dc48823f1326f3e0c8012a3c07a40da6f194299e2ec080df236287baf/langgraph-1.2.9-py3-none-any.whl", hash = "sha256:c2d98ad94333937922ba04148641c1da2bfe45b5b8e55d7b6dcb0bb2df809e76", size = 247473, upload-time = "2026-07-10T01:30:13.733Z" }, ] +[[package]] +name = "langgraph" +version = "1.2.11" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version == '3.13.*'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten'", + "(python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten') or (python_full_version == '3.11.*' and sys_platform == 'emscripten')", +] +dependencies = [ + { name = "langchain-core", version = "1.6.1", source = { registry = "https://pypi.org/simple" } }, + { name = "langgraph-checkpoint" }, + { name = "langgraph-prebuilt" }, + { name = "langgraph-sdk" }, + { name = "pydantic" }, + { name = "xxhash" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/56/0d/c8e7ee98896659e1b6555db0ab115a9ca899844744645d5d894032bab1d7/langgraph-1.2.11.tar.gz", hash = "sha256:9ecfe11e50d338b34b15cf4d8a442642de103e8ae6971320efba84e4542eb363", size = 725753, upload-time = "2026-08-11T14:00:36.945Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/7f/c5c30e4be99ff821029c7ac872a480676bb179c9f3df85ea3f38d13f86d4/langgraph-1.2.11-py3-none-any.whl", hash = "sha256:8bab70de7b2d00b5300fb289bcf38d8b241400f3184c1e95e8ce706fb0e8686b", size = 248854, upload-time = "2026-08-11T14:00:35.494Z" }, +] + [[package]] name = "langgraph-checkpoint" version = "4.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "langchain-core" }, + { name = "langchain-core", version = "1.4.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "langchain-core", version = "1.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "ormsgpack" }, ] sdist = { url = "https://files.pythonhosted.org/packages/83/47/886af6f886f0bff2273164a45f008694e48a96ff3cd25ff0228f2aa9480e/langgraph_checkpoint-4.1.1.tar.gz", hash = "sha256:6c2bdb530c91f91d7d9c1bd100925d0fc4f498d418c17f3587d1526279482a25", size = 184020, upload-time = "2026-05-22T16:57:38.503Z" } @@ -2077,7 +2174,8 @@ name = "langgraph-prebuilt" version = "1.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "langchain-core" }, + { name = "langchain-core", version = "1.4.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "langchain-core", version = "1.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "langgraph-checkpoint" }, ] sdist = { url = "https://files.pythonhosted.org/packages/29/66/ed9b93f56bc17ef22d551892f0ac2b225a97fe0fcf23a511b857f70d590b/langgraph_prebuilt-1.1.0.tar.gz", hash = "sha256:3c579cf6eed2d17f9c157c2d0fcaddcd8688524e7022d3b22b37a3bf4589d528", size = 178833, upload-time = "2026-05-12T03:37:49.332Z" } @@ -2091,7 +2189,8 @@ version = "0.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "httpx" }, - { name = "langchain-core" }, + { name = "langchain-core", version = "1.4.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "langchain-core", version = "1.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "langchain-protocol" }, { name = "orjson" }, { name = "websockets" }, @@ -2103,23 +2202,27 @@ wheels = [ [[package]] name = "langsmith" -version = "0.8.18" +version = "0.12.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "httpx" }, + { name = "anyio" }, + { name = "distro" }, + { name = "httpx2" }, { name = "orjson", marker = "platform_python_implementation != 'PyPy'" }, { name = "packaging" }, { name = "pydantic" }, { name = "requests" }, { name = "requests-toolbelt" }, + { name = "sniffio" }, + { name = "typing-extensions" }, { name = "uuid-utils" }, { name = "websockets" }, { name = "xxhash" }, { name = "zstandard" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9a/d9/a6681aa9847bbbc5ec21abe20a5e233b94e5edcfe39624db607ac7e8ccb4/langsmith-0.8.18.tar.gz", hash = "sha256:32dde9c0e67e053e0fb738921fc8ced768af7b8fa83d7a0e3fd63597cf8776dd", size = 4526988, upload-time = "2026-06-19T13:12:17.123Z" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/9a/b07aa9c457265e4bd04a868afbd35b0b6b12d655459bf274f7dba0b70be5/langsmith-0.12.1.tar.gz", hash = "sha256:8916c1a8daa4282511f311f569fd5cb2f0aba8d89a4d1761620ed37b57f72c00", size = 4851951, upload-time = "2026-09-01T17:43:55.828Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/03/70/0e0cc80a3b064c8d6c8d697c3125ed86e39d5a7393ec6dc8b07cb1cf13c4/langsmith-0.8.18-py3-none-any.whl", hash = "sha256:3940183349993faef48e6c7d08e4822ee9cefd906b362d0e3c2d650314d2f282", size = 508108, upload-time = "2026-06-19T13:12:15.348Z" }, + { url = "https://files.pythonhosted.org/packages/e9/61/a61db7922016b77afe212c97744cd8b0aad54430a1d3df23fc792fb963bf/langsmith-0.12.1-py3-none-any.whl", hash = "sha256:34574d4411947f62825e8368fd172cad2505ddfb73bf5d8ed7c0e7a41e4c4879", size = 758328, upload-time = "2026-09-01T17:43:53.319Z" }, ] [[package]] @@ -2722,7 +2825,8 @@ source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14'", "python_full_version == '3.13.*'", - "python_full_version >= '3.11' and python_full_version < '3.13'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten'", + "(python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten') or (python_full_version == '3.11.*' and sys_platform == 'emscripten')", ] sdist = { url = "https://files.pythonhosted.org/packages/6a/51/63fe664f3908c97be9d2e4f1158eb633317598cfa6e1fc14af5383f17512/networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509", size = 2517025, upload-time = "2025-12-08T17:02:39.908Z" } wheels = [ @@ -2839,7 +2943,7 @@ wheels = [ [package.optional-dependencies] litellm = [ - { name = "litellm", marker = "python_full_version < '3.14'" }, + { name = "litellm" }, ] [[package]] @@ -4369,7 +4473,8 @@ source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14'", "python_full_version == '3.13.*'", - "python_full_version >= '3.11' and python_full_version < '3.13'", + "python_full_version == '3.12.*' and sys_platform == 'emscripten'", + "(python_full_version >= '3.11' and python_full_version < '3.13' and sys_platform != 'emscripten') or (python_full_version == '3.11.*' and sys_platform == 'emscripten')", ] sdist = { url = "https://files.pythonhosted.org/packages/aa/2a/9618a122aeb2a169a28b03889a2995fe297588964333d4a7d67bdf46e147/rpds_py-2026.6.3.tar.gz", hash = "sha256:1cebd1337c242e4ec2293e541f712b2da849b29f48f0c293684b71c0632625d4", size = 64051, upload-time = "2026-06-30T07:17:53.009Z" } wheels = [ @@ -4722,7 +4827,7 @@ cloud-run-worker-otel = [ deepagents = [ { name = "deepagents", marker = "python_full_version >= '3.11'" }, { name = "langchain", marker = "python_full_version >= '3.11'" }, - { name = "langchain-core", marker = "python_full_version >= '3.11'" }, + { name = "langchain-core", version = "1.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] google-adk = [ { name = "google-adk" }, @@ -4742,7 +4847,8 @@ lambda-worker-otel = [ { name = "opentelemetry-semantic-conventions" }, ] langgraph = [ - { name = "langgraph" }, + { name = "langgraph", version = "1.2.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "langgraph", version = "1.2.11", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] langsmith = [ { name = "langsmith" }, @@ -4774,8 +4880,9 @@ dev = [ { name = "httpx" }, { name = "langchain", marker = "python_full_version >= '3.11'" }, { name = "langchain-anthropic", marker = "python_full_version >= '3.11'" }, - { name = "langchain-core", marker = "python_full_version >= '3.11'" }, - { name = "langgraph" }, + { name = "langchain-core", version = "1.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "langgraph", version = "1.2.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "langgraph", version = "1.2.11", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, { name = "langsmith" }, { name = "litellm" }, { name = "maturin" }, @@ -4813,14 +4920,14 @@ dev = [ [package.metadata] requires-dist = [ { name = "aioboto3", marker = "extra == 'aioboto3'", specifier = ">=10.4.0" }, - { name = "deepagents", marker = "python_full_version >= '3.11' and extra == 'deepagents'", specifier = ">=0.6.12,<0.7" }, + { name = "deepagents", marker = "python_full_version >= '3.11' and extra == 'deepagents'", specifier = ">=0.7,<0.8" }, { name = "google-adk", marker = "extra == 'google-adk'", specifier = ">=2.8.0,<3" }, { name = "google-genai", marker = "extra == 'google-genai'", specifier = ">=2.21.0,<3.0.0" }, { name = "grpcio", marker = "extra == 'grpc'", specifier = ">=1.48.2,<2" }, - { name = "langchain", marker = "python_full_version >= '3.11' and extra == 'deepagents'", specifier = ">=1.3.11,<2" }, - { name = "langchain-core", marker = "python_full_version >= '3.11' and extra == 'deepagents'", specifier = ">=1.4.8,<2" }, + { name = "langchain", marker = "python_full_version >= '3.11' and extra == 'deepagents'", specifier = ">=1.3.14,<2" }, + { name = "langchain-core", marker = "python_full_version >= '3.11' and extra == 'deepagents'", specifier = ">=1.5.0,<2" }, { name = "langgraph", marker = "extra == 'langgraph'", specifier = ">=1.1.0" }, - { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.34,<0.9" }, + { name = "langsmith", marker = "extra == 'langsmith'", specifier = ">=0.7.34,<0.13" }, { name = "mcp", marker = "extra == 'google-adk'", specifier = ">=1.24,<2" }, { name = "mcp", marker = "extra == 'openai-agents'", specifier = ">=1.9.4,<2" }, { name = "nexus-rpc", specifier = "==1.4.0" }, @@ -4852,15 +4959,15 @@ dev = [ { name = "basedpyright", specifier = "==1.34.0" }, { name = "cibuildwheel", specifier = ">=2.22.0,<3" }, { name = "cryptography", specifier = ">=46" }, - { name = "deepagents", marker = "python_full_version >= '3.11'", specifier = ">=0.6.12,<0.7" }, + { name = "deepagents", marker = "python_full_version >= '3.11'", specifier = ">=0.7,<0.8" }, { name = "googleapis-common-protos", specifier = ">=1.75.0,<2" }, { name = "grpcio-tools", specifier = ">=1.48.2,<2" }, { name = "httpx", specifier = ">=0.28.1" }, - { name = "langchain", marker = "python_full_version >= '3.11'", specifier = ">=1.3.11,<2" }, - { name = "langchain-anthropic", marker = "python_full_version >= '3.11'", specifier = ">=1.4.7" }, - { name = "langchain-core", marker = "python_full_version >= '3.11'", specifier = ">=1.4.8,<2" }, + { name = "langchain", marker = "python_full_version >= '3.11'", specifier = ">=1.3.14,<2" }, + { name = "langchain-anthropic", marker = "python_full_version >= '3.11'", specifier = ">=1.5.3" }, + { name = "langchain-core", marker = "python_full_version >= '3.11'", specifier = ">=1.5.0,<2" }, { name = "langgraph", specifier = ">=1.1.0" }, - { name = "langsmith", specifier = ">=0.7.34,<0.9" }, + { name = "langsmith", specifier = ">=0.7.34,<0.13" }, { name = "litellm", specifier = ">=1.83.0" }, { name = "maturin", specifier = ">=1.8.2" }, { name = "mcp", specifier = ">=1.9.4,<2" }, @@ -5066,6 +5173,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/22/2a/5e5e750890ada51017d18d0d4c30da696e5b5bd3180947729927628fc3cb/tqdm-4.68.4-py3-none-any.whl", hash = "sha256:5168118b2368f48c561afda8020fd79195b1bdb0bdf8086b88442c267a315dc2", size = 676612, upload-time = "2026-07-07T09:58:16.256Z" }, ] +[[package]] +name = "truststore" +version = "0.10.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/a3/1585216310e344e8102c22482f6060c7a6ea0322b63e026372e6dcefcfd6/truststore-0.10.4.tar.gz", hash = "sha256:9d91bd436463ad5e4ee4aba766628dd6cd7010cf3e2461756b3303710eebc301", size = 26169, upload-time = "2025-08-12T18:49:02.73Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/97/56608b2249fe206a67cd573bc93cd9896e1efb9e98bce9c163bcdc704b88/truststore-0.10.4-py3-none-any.whl", hash = "sha256:adaeaecf1cbb5f4de3b1959b42d41f6fab57b2b1666adb59e89cb0b53361d981", size = 18660, upload-time = "2025-08-12T18:49:01.46Z" }, +] + [[package]] name = "twine" version = "4.0.2" @@ -5379,7 +5495,7 @@ name = "wcmatch" version = "11.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "bracex", marker = "python_full_version >= '3.11'" }, + { name = "bracex" }, ] sdist = { url = "https://files.pythonhosted.org/packages/16/25/1da725838132221e33568973da484ff43813662ccc06ebf7f6e3abddfcd5/wcmatch-11.0.tar.gz", hash = "sha256:55d95c2447789712774b198ceec72939e88b5618f1f8f0a9b605bf7740b63b96", size = 141360, upload-time = "2026-07-10T05:50:24.183Z" } wheels = [