Spaces:
Running
Running
Jeremiah Lowin commited on
Commit ·
da5987c
1
Parent(s): aa46c09
Update for 'result' kwarg instead of 'value'
Browse files- tests/tools/test_tool_manager.py +15 -15
- tests/tools/test_tool_transform.py +14 -14
tests/tools/test_tool_manager.py
CHANGED
|
@@ -355,7 +355,7 @@ class TestCallTools:
|
|
| 355 |
result = await manager.call_tool("add", {"a": 1, "b": 2})
|
| 356 |
|
| 357 |
assert result.content[0].text == "3" # type: ignore[attr-defined]
|
| 358 |
-
assert result.structured_content == {"
|
| 359 |
|
| 360 |
async def test_call_async_tool(self):
|
| 361 |
async def double(n: int) -> int:
|
|
@@ -367,7 +367,7 @@ class TestCallTools:
|
|
| 367 |
manager.add_tool(tool)
|
| 368 |
result = await manager.call_tool("double", {"n": 5})
|
| 369 |
assert result.content[0].text == "10" # type: ignore[attr-defined]
|
| 370 |
-
assert result.structured_content == {"
|
| 371 |
|
| 372 |
async def test_call_tool_callable_object(self):
|
| 373 |
class Adder:
|
|
@@ -382,7 +382,7 @@ class TestCallTools:
|
|
| 382 |
manager.add_tool(tool)
|
| 383 |
result = await manager.call_tool("Adder", {"x": 1, "y": 2})
|
| 384 |
assert result.content[0].text == "3" # type: ignore[attr-defined]
|
| 385 |
-
assert result.structured_content == {"
|
| 386 |
|
| 387 |
async def test_call_tool_callable_object_async(self):
|
| 388 |
class Adder:
|
|
@@ -397,7 +397,7 @@ class TestCallTools:
|
|
| 397 |
manager.add_tool(tool)
|
| 398 |
result = await manager.call_tool("Adder", {"x": 1, "y": 2})
|
| 399 |
assert result.content[0].text == "3" # type: ignore[attr-defined]
|
| 400 |
-
assert result.structured_content == {"
|
| 401 |
|
| 402 |
async def test_call_tool_with_default_args(self):
|
| 403 |
def add(a: int, b: int = 1) -> int:
|
|
@@ -410,7 +410,7 @@ class TestCallTools:
|
|
| 410 |
result = await manager.call_tool("add", {"a": 1})
|
| 411 |
|
| 412 |
assert result.content[0].text == "2" # type: ignore[attr-defined]
|
| 413 |
-
assert result.structured_content == {"
|
| 414 |
|
| 415 |
async def test_call_tool_with_missing_args(self):
|
| 416 |
def add(a: int, b: int) -> int:
|
|
@@ -438,7 +438,7 @@ class TestCallTools:
|
|
| 438 |
|
| 439 |
result = await manager.call_tool("sum_vals", {"vals": [1, 2, 3]})
|
| 440 |
assert result.content[0].text == "6" # type: ignore[attr-defined]
|
| 441 |
-
assert result.structured_content == {"
|
| 442 |
|
| 443 |
async def test_call_tool_with_list_str_or_str_input(self):
|
| 444 |
def concat_strs(vals: list[str] | str) -> str:
|
|
@@ -451,11 +451,11 @@ class TestCallTools:
|
|
| 451 |
# Try both with plain python object and with JSON list
|
| 452 |
result = await manager.call_tool("concat_strs", {"vals": ["a", "b", "c"]})
|
| 453 |
assert result.content[0].text == "abc" # type: ignore[attr-defined]
|
| 454 |
-
assert result.structured_content == {"
|
| 455 |
|
| 456 |
result = await manager.call_tool("concat_strs", {"vals": "a"})
|
| 457 |
assert result.content[0].text == "a" # type: ignore[attr-defined]
|
| 458 |
-
assert result.structured_content == {"
|
| 459 |
|
| 460 |
async def test_call_tool_with_complex_model(self):
|
| 461 |
class MyShrimpTank(BaseModel):
|
|
@@ -487,7 +487,7 @@ class TestCallTools:
|
|
| 487 |
)
|
| 488 |
|
| 489 |
assert result.content[0].text == '[\n "rex",\n "gertrude"\n]' # type: ignore[attr-defined]
|
| 490 |
-
assert result.structured_content == {"
|
| 491 |
|
| 492 |
async def test_call_tool_with_custom_serializer(self):
|
| 493 |
"""Test that a custom serializer provided to FastMCP is used by tools."""
|
|
@@ -533,7 +533,7 @@ class TestCallTools:
|
|
| 533 |
== 'CUSTOM:[{"key": "value", "number": 123}, {"key": "value2", "number": 456}]' # type: ignore[attr-defined]
|
| 534 |
)
|
| 535 |
assert result.structured_content == {
|
| 536 |
-
"
|
| 537 |
{"key": "value", "number": 123},
|
| 538 |
{"key": "value2", "number": 456},
|
| 539 |
]
|
|
@@ -559,7 +559,7 @@ class TestCallTools:
|
|
| 559 |
result.content[0].text # type: ignore[attr-defined]
|
| 560 |
== pydantic_core.to_json(uuid_result).decode()
|
| 561 |
)
|
| 562 |
-
assert result.structured_content == {"
|
| 563 |
|
| 564 |
|
| 565 |
class TestToolSchema:
|
|
@@ -630,7 +630,7 @@ class TestContextHandling:
|
|
| 630 |
async with context:
|
| 631 |
result = await manager.call_tool("tool_with_context", {"x": 42})
|
| 632 |
assert result.content[0].text == "42" # type: ignore[attr-defined]
|
| 633 |
-
assert result.structured_content == {"
|
| 634 |
|
| 635 |
async def test_context_injection_async(self):
|
| 636 |
"""Test that context is properly injected in async tools."""
|
|
@@ -649,7 +649,7 @@ class TestContextHandling:
|
|
| 649 |
async with context:
|
| 650 |
result = await manager.call_tool("async_tool", {"x": 42})
|
| 651 |
assert result.content[0].text == "42" # type: ignore[attr-defined]
|
| 652 |
-
assert result.structured_content == {"
|
| 653 |
|
| 654 |
async def test_context_optional(self):
|
| 655 |
"""Test that context is optional when calling tools."""
|
|
@@ -668,7 +668,7 @@ class TestContextHandling:
|
|
| 668 |
async with context:
|
| 669 |
result = await manager.call_tool("tool_with_context", {"x": 42})
|
| 670 |
assert result.content[0].text == "42" # type: ignore[attr-defined]
|
| 671 |
-
assert result.structured_content == {"
|
| 672 |
|
| 673 |
def test_parameterized_context_parameter_detection(self):
|
| 674 |
"""Test that context parameters are properly detected in
|
|
@@ -777,7 +777,7 @@ class TestCustomToolNames:
|
|
| 777 |
# Tool should be callable by its custom name
|
| 778 |
result = await manager.call_tool("custom_multiply", {"a": 5, "b": 3})
|
| 779 |
assert result.content[0].text == "15" # type: ignore[attr-defined]
|
| 780 |
-
assert result.structured_content == {"
|
| 781 |
|
| 782 |
# Original name should not be registered
|
| 783 |
with pytest.raises(NotFoundError, match="Tool 'multiply' not found"):
|
|
|
|
| 355 |
result = await manager.call_tool("add", {"a": 1, "b": 2})
|
| 356 |
|
| 357 |
assert result.content[0].text == "3" # type: ignore[attr-defined]
|
| 358 |
+
assert result.structured_content == {"result": 3}
|
| 359 |
|
| 360 |
async def test_call_async_tool(self):
|
| 361 |
async def double(n: int) -> int:
|
|
|
|
| 367 |
manager.add_tool(tool)
|
| 368 |
result = await manager.call_tool("double", {"n": 5})
|
| 369 |
assert result.content[0].text == "10" # type: ignore[attr-defined]
|
| 370 |
+
assert result.structured_content == {"result": 10}
|
| 371 |
|
| 372 |
async def test_call_tool_callable_object(self):
|
| 373 |
class Adder:
|
|
|
|
| 382 |
manager.add_tool(tool)
|
| 383 |
result = await manager.call_tool("Adder", {"x": 1, "y": 2})
|
| 384 |
assert result.content[0].text == "3" # type: ignore[attr-defined]
|
| 385 |
+
assert result.structured_content == {"result": 3}
|
| 386 |
|
| 387 |
async def test_call_tool_callable_object_async(self):
|
| 388 |
class Adder:
|
|
|
|
| 397 |
manager.add_tool(tool)
|
| 398 |
result = await manager.call_tool("Adder", {"x": 1, "y": 2})
|
| 399 |
assert result.content[0].text == "3" # type: ignore[attr-defined]
|
| 400 |
+
assert result.structured_content == {"result": 3}
|
| 401 |
|
| 402 |
async def test_call_tool_with_default_args(self):
|
| 403 |
def add(a: int, b: int = 1) -> int:
|
|
|
|
| 410 |
result = await manager.call_tool("add", {"a": 1})
|
| 411 |
|
| 412 |
assert result.content[0].text == "2" # type: ignore[attr-defined]
|
| 413 |
+
assert result.structured_content == {"result": 2}
|
| 414 |
|
| 415 |
async def test_call_tool_with_missing_args(self):
|
| 416 |
def add(a: int, b: int) -> int:
|
|
|
|
| 438 |
|
| 439 |
result = await manager.call_tool("sum_vals", {"vals": [1, 2, 3]})
|
| 440 |
assert result.content[0].text == "6" # type: ignore[attr-defined]
|
| 441 |
+
assert result.structured_content == {"result": 6}
|
| 442 |
|
| 443 |
async def test_call_tool_with_list_str_or_str_input(self):
|
| 444 |
def concat_strs(vals: list[str] | str) -> str:
|
|
|
|
| 451 |
# Try both with plain python object and with JSON list
|
| 452 |
result = await manager.call_tool("concat_strs", {"vals": ["a", "b", "c"]})
|
| 453 |
assert result.content[0].text == "abc" # type: ignore[attr-defined]
|
| 454 |
+
assert result.structured_content == {"result": "abc"}
|
| 455 |
|
| 456 |
result = await manager.call_tool("concat_strs", {"vals": "a"})
|
| 457 |
assert result.content[0].text == "a" # type: ignore[attr-defined]
|
| 458 |
+
assert result.structured_content == {"result": "a"}
|
| 459 |
|
| 460 |
async def test_call_tool_with_complex_model(self):
|
| 461 |
class MyShrimpTank(BaseModel):
|
|
|
|
| 487 |
)
|
| 488 |
|
| 489 |
assert result.content[0].text == '[\n "rex",\n "gertrude"\n]' # type: ignore[attr-defined]
|
| 490 |
+
assert result.structured_content == {"result": ["rex", "gertrude"]}
|
| 491 |
|
| 492 |
async def test_call_tool_with_custom_serializer(self):
|
| 493 |
"""Test that a custom serializer provided to FastMCP is used by tools."""
|
|
|
|
| 533 |
== 'CUSTOM:[{"key": "value", "number": 123}, {"key": "value2", "number": 456}]' # type: ignore[attr-defined]
|
| 534 |
)
|
| 535 |
assert result.structured_content == {
|
| 536 |
+
"result": [
|
| 537 |
{"key": "value", "number": 123},
|
| 538 |
{"key": "value2", "number": 456},
|
| 539 |
]
|
|
|
|
| 559 |
result.content[0].text # type: ignore[attr-defined]
|
| 560 |
== pydantic_core.to_json(uuid_result).decode()
|
| 561 |
)
|
| 562 |
+
assert result.structured_content == {"result": str(uuid_result)}
|
| 563 |
|
| 564 |
|
| 565 |
class TestToolSchema:
|
|
|
|
| 630 |
async with context:
|
| 631 |
result = await manager.call_tool("tool_with_context", {"x": 42})
|
| 632 |
assert result.content[0].text == "42" # type: ignore[attr-defined]
|
| 633 |
+
assert result.structured_content == {"result": "42"}
|
| 634 |
|
| 635 |
async def test_context_injection_async(self):
|
| 636 |
"""Test that context is properly injected in async tools."""
|
|
|
|
| 649 |
async with context:
|
| 650 |
result = await manager.call_tool("async_tool", {"x": 42})
|
| 651 |
assert result.content[0].text == "42" # type: ignore[attr-defined]
|
| 652 |
+
assert result.structured_content == {"result": "42"}
|
| 653 |
|
| 654 |
async def test_context_optional(self):
|
| 655 |
"""Test that context is optional when calling tools."""
|
|
|
|
| 668 |
async with context:
|
| 669 |
result = await manager.call_tool("tool_with_context", {"x": 42})
|
| 670 |
assert result.content[0].text == "42" # type: ignore[attr-defined]
|
| 671 |
+
assert result.structured_content == {"result": 42}
|
| 672 |
|
| 673 |
def test_parameterized_context_parameter_detection(self):
|
| 674 |
"""Test that context parameters are properly detected in
|
|
|
|
| 777 |
# Tool should be callable by its custom name
|
| 778 |
result = await manager.call_tool("custom_multiply", {"a": 5, "b": 3})
|
| 779 |
assert result.content[0].text == "15" # type: ignore[attr-defined]
|
| 780 |
+
assert result.structured_content == {"result": 15}
|
| 781 |
|
| 782 |
# Original name should not be registered
|
| 783 |
with pytest.raises(NotFoundError, match="Tool 'multiply' not found"):
|
tests/tools/test_tool_transform.py
CHANGED
|
@@ -53,7 +53,7 @@ async def test_tool_defaults_are_maintained_on_unmapped_args(add_tool):
|
|
| 53 |
)
|
| 54 |
result = await new_tool.run(arguments={"new_x": 1})
|
| 55 |
# The parent tool returns int which gets wrapped as structured output
|
| 56 |
-
assert result.structured_content == {"
|
| 57 |
|
| 58 |
|
| 59 |
async def test_tool_defaults_are_maintained_on_mapped_args(add_tool):
|
|
@@ -62,7 +62,7 @@ async def test_tool_defaults_are_maintained_on_mapped_args(add_tool):
|
|
| 62 |
)
|
| 63 |
result = await new_tool.run(arguments={"old_x": 1})
|
| 64 |
# The parent tool returns int which gets wrapped as structured output
|
| 65 |
-
assert result.structured_content == {"
|
| 66 |
|
| 67 |
|
| 68 |
def test_tool_change_arg_name(add_tool):
|
|
@@ -89,7 +89,7 @@ async def test_tool_drop_arg(add_tool):
|
|
| 89 |
)
|
| 90 |
assert sorted(new_tool.parameters["properties"]) == ["old_x"]
|
| 91 |
result = await new_tool.run(arguments={"old_x": 1})
|
| 92 |
-
assert result.structured_content == {"
|
| 93 |
|
| 94 |
|
| 95 |
async def test_dropped_args_error_if_provided(add_tool):
|
|
@@ -111,7 +111,7 @@ async def test_hidden_arg_with_constant_default(add_tool):
|
|
| 111 |
assert sorted(new_tool.parameters["properties"]) == ["old_x"]
|
| 112 |
# Should pass old_x=5 and old_y=20 to parent
|
| 113 |
result = await new_tool.run(arguments={"old_x": 5})
|
| 114 |
-
assert result.structured_content == {"
|
| 115 |
|
| 116 |
|
| 117 |
async def test_hidden_arg_without_default_uses_parent_default(add_tool):
|
|
@@ -124,7 +124,7 @@ async def test_hidden_arg_without_default_uses_parent_default(add_tool):
|
|
| 124 |
# Should pass old_x=3 and let parent use its default old_y=10
|
| 125 |
result = await new_tool.run(arguments={"old_x": 3})
|
| 126 |
assert result.content[0].text == "13" # type: ignore[attr-defined]
|
| 127 |
-
assert result.structured_content == {"
|
| 128 |
|
| 129 |
|
| 130 |
async def test_mixed_hidden_args_with_custom_function(add_tool):
|
|
@@ -150,7 +150,7 @@ async def test_mixed_hidden_args_with_custom_function(add_tool):
|
|
| 150 |
# Should pass visible_x=7 as old_x=7 and old_y=25 to parent
|
| 151 |
result = await new_tool.run(arguments={"visible_x": 7})
|
| 152 |
assert result.content[0].text == "32" # type: ignore[attr-defined]
|
| 153 |
-
assert result.structured_content == {"
|
| 154 |
|
| 155 |
|
| 156 |
async def test_hide_required_param_without_default_raises_error():
|
|
@@ -188,7 +188,7 @@ async def test_hide_required_param_with_user_default_works():
|
|
| 188 |
assert sorted(new_tool.parameters["properties"]) == ["optional_param"]
|
| 189 |
# Should pass required_param=5 and optional_param=20 to parent
|
| 190 |
result = await new_tool.run(arguments={"optional_param": 20})
|
| 191 |
-
assert result.structured_content == {"
|
| 192 |
|
| 193 |
|
| 194 |
async def test_forward_with_argument_mapping(add_tool):
|
|
@@ -208,7 +208,7 @@ async def test_forward_with_argument_mapping(add_tool):
|
|
| 208 |
|
| 209 |
result = await new_tool.run(arguments={"new_x": 2, "new_y": 3})
|
| 210 |
assert result.content[0].text == "5" # type: ignore[attr-defined]
|
| 211 |
-
assert result.structured_content == {"
|
| 212 |
|
| 213 |
|
| 214 |
async def test_forward_with_incorrect_args_raises_error(add_tool):
|
|
@@ -249,7 +249,7 @@ async def test_forward_raw_without_argument_mapping(add_tool):
|
|
| 249 |
|
| 250 |
result = await new_tool.run(arguments={"new_x": 2, "new_y": 3})
|
| 251 |
assert result.content[0].text == "5" # type: ignore[attr-defined]
|
| 252 |
-
assert result.structured_content == {"
|
| 253 |
|
| 254 |
|
| 255 |
async def test_custom_fn_with_kwargs_and_no_transform_args(add_tool):
|
|
@@ -260,7 +260,7 @@ async def test_custom_fn_with_kwargs_and_no_transform_args(add_tool):
|
|
| 260 |
new_tool = Tool.from_tool(add_tool, transform_fn=custom_fn)
|
| 261 |
result = await new_tool.run(arguments={"extra": 1, "old_x": 2, "old_y": 3})
|
| 262 |
assert result.content[0].text == "6" # type: ignore[attr-defined]
|
| 263 |
-
assert result.structured_content == {"
|
| 264 |
assert new_tool.parameters["required"] == IsList(
|
| 265 |
"extra", "old_x", check_order=False
|
| 266 |
)
|
|
@@ -278,7 +278,7 @@ async def test_fn_with_kwargs_passes_through_original_args(add_tool):
|
|
| 278 |
new_tool = Tool.from_tool(add_tool, transform_fn=custom_fn)
|
| 279 |
result = await new_tool.run(arguments={"new_y": 2, "old_y": 3})
|
| 280 |
assert result.content[0].text == "5" # type: ignore[attr-defined]
|
| 281 |
-
assert result.structured_content == {"
|
| 282 |
|
| 283 |
|
| 284 |
async def test_fn_with_kwargs_receives_transformed_arg_names(add_tool):
|
|
@@ -297,7 +297,7 @@ async def test_fn_with_kwargs_receives_transformed_arg_names(add_tool):
|
|
| 297 |
)
|
| 298 |
result = await new_tool.run(arguments={"new_x": 2, "old_y": 3})
|
| 299 |
assert result.content[0].text == "5" # type: ignore[attr-defined]
|
| 300 |
-
assert result.structured_content == {"
|
| 301 |
|
| 302 |
|
| 303 |
async def test_fn_with_kwargs_handles_partial_explicit_args(add_tool):
|
|
@@ -318,7 +318,7 @@ async def test_fn_with_kwargs_handles_partial_explicit_args(add_tool):
|
|
| 318 |
arguments={"new_x": 3, "old_y": 7, "some_other_param": "test"}
|
| 319 |
)
|
| 320 |
assert result.content[0].text == "10" # type: ignore[attr-defined]
|
| 321 |
-
assert result.structured_content == {"
|
| 322 |
|
| 323 |
|
| 324 |
async def test_fn_with_kwargs_mixed_mapped_and_unmapped_args(add_tool):
|
|
@@ -337,7 +337,7 @@ async def test_fn_with_kwargs_mixed_mapped_and_unmapped_args(add_tool):
|
|
| 337 |
) # only map 'a'
|
| 338 |
result = await new_tool.run(arguments={"new_x": 1, "old_y": 5})
|
| 339 |
assert result.content[0].text == "6" # type: ignore[attr-defined]
|
| 340 |
-
assert result.structured_content == {"
|
| 341 |
|
| 342 |
|
| 343 |
async def test_fn_with_kwargs_dropped_args_not_in_kwargs(add_tool):
|
|
|
|
| 53 |
)
|
| 54 |
result = await new_tool.run(arguments={"new_x": 1})
|
| 55 |
# The parent tool returns int which gets wrapped as structured output
|
| 56 |
+
assert result.structured_content == {"result": 11}
|
| 57 |
|
| 58 |
|
| 59 |
async def test_tool_defaults_are_maintained_on_mapped_args(add_tool):
|
|
|
|
| 62 |
)
|
| 63 |
result = await new_tool.run(arguments={"old_x": 1})
|
| 64 |
# The parent tool returns int which gets wrapped as structured output
|
| 65 |
+
assert result.structured_content == {"result": 11}
|
| 66 |
|
| 67 |
|
| 68 |
def test_tool_change_arg_name(add_tool):
|
|
|
|
| 89 |
)
|
| 90 |
assert sorted(new_tool.parameters["properties"]) == ["old_x"]
|
| 91 |
result = await new_tool.run(arguments={"old_x": 1})
|
| 92 |
+
assert result.structured_content == {"result": 11}
|
| 93 |
|
| 94 |
|
| 95 |
async def test_dropped_args_error_if_provided(add_tool):
|
|
|
|
| 111 |
assert sorted(new_tool.parameters["properties"]) == ["old_x"]
|
| 112 |
# Should pass old_x=5 and old_y=20 to parent
|
| 113 |
result = await new_tool.run(arguments={"old_x": 5})
|
| 114 |
+
assert result.structured_content == {"result": 25}
|
| 115 |
|
| 116 |
|
| 117 |
async def test_hidden_arg_without_default_uses_parent_default(add_tool):
|
|
|
|
| 124 |
# Should pass old_x=3 and let parent use its default old_y=10
|
| 125 |
result = await new_tool.run(arguments={"old_x": 3})
|
| 126 |
assert result.content[0].text == "13" # type: ignore[attr-defined]
|
| 127 |
+
assert result.structured_content == {"result": 13}
|
| 128 |
|
| 129 |
|
| 130 |
async def test_mixed_hidden_args_with_custom_function(add_tool):
|
|
|
|
| 150 |
# Should pass visible_x=7 as old_x=7 and old_y=25 to parent
|
| 151 |
result = await new_tool.run(arguments={"visible_x": 7})
|
| 152 |
assert result.content[0].text == "32" # type: ignore[attr-defined]
|
| 153 |
+
assert result.structured_content == {"result": 32}
|
| 154 |
|
| 155 |
|
| 156 |
async def test_hide_required_param_without_default_raises_error():
|
|
|
|
| 188 |
assert sorted(new_tool.parameters["properties"]) == ["optional_param"]
|
| 189 |
# Should pass required_param=5 and optional_param=20 to parent
|
| 190 |
result = await new_tool.run(arguments={"optional_param": 20})
|
| 191 |
+
assert result.structured_content == {"result": 25}
|
| 192 |
|
| 193 |
|
| 194 |
async def test_forward_with_argument_mapping(add_tool):
|
|
|
|
| 208 |
|
| 209 |
result = await new_tool.run(arguments={"new_x": 2, "new_y": 3})
|
| 210 |
assert result.content[0].text == "5" # type: ignore[attr-defined]
|
| 211 |
+
assert result.structured_content == {"result": 5}
|
| 212 |
|
| 213 |
|
| 214 |
async def test_forward_with_incorrect_args_raises_error(add_tool):
|
|
|
|
| 249 |
|
| 250 |
result = await new_tool.run(arguments={"new_x": 2, "new_y": 3})
|
| 251 |
assert result.content[0].text == "5" # type: ignore[attr-defined]
|
| 252 |
+
assert result.structured_content == {"result": 5}
|
| 253 |
|
| 254 |
|
| 255 |
async def test_custom_fn_with_kwargs_and_no_transform_args(add_tool):
|
|
|
|
| 260 |
new_tool = Tool.from_tool(add_tool, transform_fn=custom_fn)
|
| 261 |
result = await new_tool.run(arguments={"extra": 1, "old_x": 2, "old_y": 3})
|
| 262 |
assert result.content[0].text == "6" # type: ignore[attr-defined]
|
| 263 |
+
assert result.structured_content == {"result": 6}
|
| 264 |
assert new_tool.parameters["required"] == IsList(
|
| 265 |
"extra", "old_x", check_order=False
|
| 266 |
)
|
|
|
|
| 278 |
new_tool = Tool.from_tool(add_tool, transform_fn=custom_fn)
|
| 279 |
result = await new_tool.run(arguments={"new_y": 2, "old_y": 3})
|
| 280 |
assert result.content[0].text == "5" # type: ignore[attr-defined]
|
| 281 |
+
assert result.structured_content == {"result": 5}
|
| 282 |
|
| 283 |
|
| 284 |
async def test_fn_with_kwargs_receives_transformed_arg_names(add_tool):
|
|
|
|
| 297 |
)
|
| 298 |
result = await new_tool.run(arguments={"new_x": 2, "old_y": 3})
|
| 299 |
assert result.content[0].text == "5" # type: ignore[attr-defined]
|
| 300 |
+
assert result.structured_content == {"result": 5}
|
| 301 |
|
| 302 |
|
| 303 |
async def test_fn_with_kwargs_handles_partial_explicit_args(add_tool):
|
|
|
|
| 318 |
arguments={"new_x": 3, "old_y": 7, "some_other_param": "test"}
|
| 319 |
)
|
| 320 |
assert result.content[0].text == "10" # type: ignore[attr-defined]
|
| 321 |
+
assert result.structured_content == {"result": 10}
|
| 322 |
|
| 323 |
|
| 324 |
async def test_fn_with_kwargs_mixed_mapped_and_unmapped_args(add_tool):
|
|
|
|
| 337 |
) # only map 'a'
|
| 338 |
result = await new_tool.run(arguments={"new_x": 1, "old_y": 5})
|
| 339 |
assert result.content[0].text == "6" # type: ignore[attr-defined]
|
| 340 |
+
assert result.structured_content == {"result": 6}
|
| 341 |
|
| 342 |
|
| 343 |
async def test_fn_with_kwargs_dropped_args_not_in_kwargs(add_tool):
|