mirror of
https://github.com/hwchase17/langchain.git
synced 2026-06-09 18:50:33 +00:00
Moving all `ToolNode` related improvements back to LangGraph and importing them in LC! pairing w/ https://github.com/langchain-ai/langgraph/pull/6321 this fixes a couple of things: 1. `InjectedState`, store etc will continue to work as expected no matter where the import is from 2. `ToolRuntime` is now usable w/in langgraph, woohoo!
70 lines
2.0 KiB
Python
70 lines
2.0 KiB
Python
from __future__ import annotations
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
from langchain_core.messages.tool import ToolCall
|
|
|
|
pytest.importorskip(
|
|
"anthropic", reason="Anthropic SDK is required for Claude middleware tests"
|
|
)
|
|
|
|
from langchain.agents.middleware.types import ToolCallRequest
|
|
from langchain_core.messages import ToolMessage
|
|
|
|
from langchain_anthropic.middleware.bash import ClaudeBashToolMiddleware
|
|
|
|
|
|
def test_wrap_tool_call_handles_claude_bash(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
middleware = ClaudeBashToolMiddleware()
|
|
sentinel = ToolMessage(content="ok", tool_call_id="call-1", name="bash")
|
|
|
|
monkeypatch.setattr(middleware, "_run_shell_tool", MagicMock(return_value=sentinel))
|
|
monkeypatch.setattr(
|
|
middleware, "_ensure_resources", MagicMock(return_value=MagicMock())
|
|
)
|
|
|
|
tool_call: ToolCall = {
|
|
"name": "bash",
|
|
"args": {"command": "echo hi"},
|
|
"id": "call-1",
|
|
}
|
|
request = ToolCallRequest(
|
|
tool_call=tool_call,
|
|
tool=MagicMock(),
|
|
state={},
|
|
runtime=None, # type: ignore[arg-type]
|
|
)
|
|
|
|
handler_called = False
|
|
|
|
def handler(_: ToolCallRequest) -> ToolMessage:
|
|
nonlocal handler_called
|
|
handler_called = True
|
|
return ToolMessage(content="should not be used", tool_call_id="call-1")
|
|
|
|
result = middleware.wrap_tool_call(request, handler)
|
|
assert result is sentinel
|
|
assert handler_called is False
|
|
|
|
|
|
def test_wrap_tool_call_passes_through_other_tools(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
middleware = ClaudeBashToolMiddleware()
|
|
tool_call: ToolCall = {"name": "other", "args": {}, "id": "call-2"}
|
|
request = ToolCallRequest(
|
|
tool_call=tool_call,
|
|
tool=MagicMock(),
|
|
state={},
|
|
runtime=None, # type: ignore[arg-type]
|
|
)
|
|
|
|
sentinel = ToolMessage(content="handled", tool_call_id="call-2", name="other")
|
|
|
|
def handler(_: ToolCallRequest) -> ToolMessage:
|
|
return sentinel
|
|
|
|
result = middleware.wrap_tool_call(request, handler)
|
|
assert result is sentinel
|