Apply patch [skip ci]

This commit is contained in:
open-swe[bot]
2025-08-22 12:42:37 +00:00
parent a5b61361af
commit cc54df296e
+116
View File
@@ -0,0 +1,116 @@
#!/usr/bin/env python3
"""Test script to verify reserved keyword injection works correctly."""
from typing import Any
from langchain_core.tools import tool
from langgraph.prebuilt import ToolNode
from langgraph.runtime import Runtime
from langgraph.store.memory import InMemoryStore
from langchain_core.messages import AIMessage, ToolCall
# Test tool with reserved keyword 'state'
@tool
def tool_with_state(x: int, state) -> str:
"""Tool that uses reserved keyword 'state'."""
return f"x={x}, state_keys={list(state.keys()) if isinstance(state, dict) else 'not_dict'}"
# Test tool with reserved keyword 'runtime'
@tool
def tool_with_runtime(x: int, runtime) -> str:
"""Tool that uses reserved keyword 'runtime'."""
has_store = runtime.store is not None if hasattr(runtime, 'store') else False
return f"x={x}, has_store={has_store}"
# Test tool with both reserved keywords
@tool
def tool_with_both(x: int, state, runtime) -> str:
"""Tool that uses both reserved keywords."""
has_store = runtime.store is not None if hasattr(runtime, 'store') else False
return f"x={x}, state_keys={list(state.keys()) if isinstance(state, dict) else 'not_dict'}, has_store={has_store}"
# Test regular tool without injection
@tool
def regular_tool(x: int, y: str) -> str:
"""Regular tool without injection."""
return f"x={x}, y={y}"
def test_reserved_keywords():
"""Test that reserved keywords work correctly."""
# Create ToolNode with all test tools
tools = [tool_with_state, tool_with_runtime, tool_with_both, regular_tool]
node = ToolNode(tools)
# Check that reserved keywords are detected
print("Tool to state args:", node.tool_to_state_args)
print("Tool to runtime args:", node.tool_to_runtime_arg)
# Check tool schemas - reserved keywords should be excluded
for tool_name, tool_obj in node.tools_by_name.items():
schema = tool_obj.get_input_schema()
print(f"\n{tool_name} schema fields:", list(schema.__fields__.keys()))
# Verify reserved keywords are not in the schema
if tool_name == "tool_with_state":
assert "state" not in schema.__fields__, f"'state' should be excluded from {tool_name} schema"
elif tool_name == "tool_with_runtime":
assert "runtime" not in schema.__fields__, f"'runtime' should be excluded from {tool_name} schema"
elif tool_name == "tool_with_both":
assert "state" not in schema.__fields__, f"'state' should be excluded from {tool_name} schema"
assert "runtime" not in schema.__fields__, f"'runtime' should be excluded from {tool_name} schema"
print("\nAll schema checks passed!")
# Test actual injection
store = InMemoryStore()
state = {"messages": [], "foo": "bar"}
# Create tool calls
tool_call1: ToolCall = {
"name": "tool_with_state",
"args": {"x": 1},
"id": "1",
"type": "tool_call"
}
tool_call2: ToolCall = {
"name": "tool_with_runtime",
"args": {"x": 2},
"id": "2",
"type": "tool_call"
}
tool_call3: ToolCall = {
"name": "regular_tool",
"args": {"x": 3, "y": "test"},
"id": "3",
"type": "tool_call"
}
# Test injection
from langchain_core.runnables import RunnableConfig
config = RunnableConfig()
injected1 = node.inject_tool_args(tool_call1, state, store, config)
print(f"\nInjected args for tool_with_state: {injected1['args']}")
assert "state" in injected1["args"], "State should be injected"
injected2 = node.inject_tool_args(tool_call2, state, store, config)
print(f"Injected args for tool_with_runtime: {injected2['args']}")
assert "runtime" in injected2["args"], "Runtime should be injected"
injected3 = node.inject_tool_args(tool_call3, state, store, config)
print(f"Injected args for regular_tool: {injected3['args']}")
assert "state" not in injected3["args"], "State should not be injected"
assert "runtime" not in injected3["args"], "Runtime should not be injected"
print("\nAll injection tests passed!")
if __name__ == "__main__":
test_reserved_keywords()