Skip to content

Commit 25745b7

Browse files
authored
test: add tool_arg_validator edge case test, fix typo (#826) (#831)
* test: add tool_arg_validator edge case test, fix typo (#826) Add test documenting that tool_arg_validator with tool_name=None silently returns True when no tool call contains the target arg_name. Fix "Valiudation" typo in error reason strings. * fix: error reason interpolates tool_name=None, add issue ref Use loop variable `tool` instead of `tool_name` in the no-tool-name branch error message. Add assertion verifying actual tool name appears in the reason string. Reference #826 in test docstring. * fix: tidy up tool_arg_validator error messages and guards - Use `is not None` instead of truthiness check for tool_name - Fix "Expected None to be called" message when tool_name is None - Complete truncated docstring for tool_name parameter * fix: use identity check for tool_label fallback Consistent with the other is-not-None guards in the function.
1 parent f1d5cf4 commit 25745b7

2 files changed

Lines changed: 25 additions & 7 deletions

File tree

mellea/stdlib/requirements/tool_reqs.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ def tool_arg_validator(
6060
) -> Requirement:
6161
"""A requirement that passes only if `validation_fn` returns a True value for the *value* of the `arg_name` argument to `tool_name`.
6262
63-
If `tool_name` is not specified, then this requirement is enforced for *every* tool that
63+
If `tool_name` is not specified, then this requirement is enforced for *every* tool that was called.
6464
6565
Args:
6666
description: The Requirement description.
67-
tool_name: The (optional) tool name for .
67+
tool_name: The (optional) tool name to validate. When None, all tools are checked.
6868
arg_name: The argument to check.
6969
validation_fn: A validation function for validating the value of the `arg_name` argument.
7070
check_only: propagates the `check_only` flag to the requirement.
@@ -76,20 +76,21 @@ def tool_arg_validator(
7676
Returns:
7777
A ``Requirement`` that validates the specified tool argument.
7878
"""
79-
if tool_name:
79+
if tool_name is not None:
8080
tool_name = _name2str(tool_name)
8181

8282
def _validate(ctx: Context) -> ValidationResult:
8383
output = ctx.last_output()
8484
assert output is not None
8585

8686
if output.tool_calls is None:
87+
tool_label = tool_name if tool_name is not None else "a tool"
8788
return ValidationResult(
8889
result=False,
89-
reason=f"Expected {tool_name} to be called but no tools were called.",
90+
reason=f"Expected {tool_label} to be called but no tools were called.",
9091
)
9192

92-
if tool_name:
93+
if tool_name is not None:
9394
if tool_name not in output.tool_calls:
9495
return ValidationResult(
9596
result=False, reason=f"Tool {tool_name} was not called."
@@ -106,7 +107,7 @@ def _validate(ctx: Context) -> ValidationResult:
106107
else:
107108
return ValidationResult(
108109
result=False,
109-
reason=f"Valiudation did not pass for {tool_name}.{arg_name}. Arg value: {arg_value}. Argument validation result: {validate_result}",
110+
reason=f"Validation did not pass for {tool_name}.{arg_name}. Arg value: {arg_value}. Argument validation result: {validate_result}",
110111
)
111112
else:
112113
for tool in output.tool_calls.keys():
@@ -116,7 +117,7 @@ def _validate(ctx: Context) -> ValidationResult:
116117
if not validate_result:
117118
return ValidationResult(
118119
result=False,
119-
reason=f"Valiudation did not pass for {tool_name}.{arg_name}. Arg value: {arg_value}. Argument validation result: {validate_result}",
120+
reason=f"Validation did not pass for {tool}.{arg_name}. Arg value: {arg_value}. Argument validation result: {validate_result}",
120121
)
121122
return ValidationResult(result=True)
122123

test/stdlib/requirements/test_reqlib_tools.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,20 @@ def test_tool_arg_validator_no_tool_name_one_fails():
185185
)
186186
result = req.validation_fn(ctx)
187187
assert result.as_bool() is False
188+
assert "tool_b" in result.reason
189+
assert "None" not in result.reason
190+
191+
192+
def test_tool_arg_validator_no_tool_name_arg_missing_everywhere():
193+
"""Documents current behavior (see #826): when tool_name=None and no tool call
194+
contains the target arg_name, validation silently passes (the for-loop completes
195+
without failing). This is arguably a latent bug — the validator never runs."""
196+
ctx = _ctx_with_tool_calls({"tool_a": _make_tool_call("tool_a", {"y": 5})})
197+
req = tool_arg_validator(
198+
description="x must be positive",
199+
tool_name=None,
200+
arg_name="x",
201+
validation_fn=lambda v: v > 0,
202+
)
203+
result = req.validation_fn(ctx)
204+
assert result.as_bool() is True

0 commit comments

Comments
 (0)