Implement review suggestions: improved error handling, type validation, and edge case tests

Co-Authored-By: Joe Moura <joao@crewai.com>
This commit is contained in:
Devin AI
2025-05-14 00:31:04 +00:00
parent 8483d1c772
commit aa1b915209
2 changed files with 59 additions and 3 deletions

View File

@@ -173,11 +173,18 @@ class CrewStructuredTool:
def _parse_args(self, raw_args: Union[str, dict]) -> dict: def _parse_args(self, raw_args: Union[str, dict]) -> dict:
"""Parse and validate the input arguments against the schema. """Parse and validate the input arguments against the schema.
This method handles different input formats from various LLM providers,
including nested dictionaries with 'value' fields that some providers use.
Args: Args:
raw_args: The raw arguments to parse, either as a string or dict raw_args: The raw arguments to parse, either as a string or dict.
Supports nested dictionaries with 'value' field for LLM provider compatibility.
Returns: Returns:
The validated arguments as a dictionary The validated arguments as a dictionary
Raises:
ValueError: If argument parsing or validation fails
""" """
if isinstance(raw_args, str): if isinstance(raw_args, str):
try: try:
@@ -194,8 +201,23 @@ class CrewStructuredTool:
for field_name, field_value in list(raw_args.items()): for field_name, field_value in list(raw_args.items()):
# Check if this field exists in the schema # Check if this field exists in the schema
if field_name in schema_fields: if field_name in schema_fields:
if (isinstance(field_value, dict) and 'value' in field_value): # Handle nested dictionaries with 'value' field
raw_args[field_name] = field_value['value'] if isinstance(field_value, dict):
if 'value' in field_value:
# Extract the value from the nested dictionary
value = field_value['value']
self._logger.debug(f"Extracting value from nested dict for {field_name}")
expected_type = schema_fields[field_name].annotation
if expected_type in (str, int, float, bool) and not isinstance(value, expected_type):
self._logger.warning(
f"Type mismatch for {field_name}: expected {expected_type}, got {type(value)}"
)
raw_args[field_name] = value
else:
self._logger.debug(f"Nested dict for {field_name} has no 'value' key")
try: try:
validated_args = self.args_schema.model_validate(raw_args) validated_args = self.args_schema.model_validate(raw_args)

View File

@@ -137,3 +137,37 @@ def test_nested_dict_without_value_key():
invalid_input = {"query": {"description": "A string input parameter", "other_key": "test"}} invalid_input = {"query": {"description": "A string input parameter", "other_key": "test"}}
with pytest.raises(ValueError): with pytest.raises(ValueError):
tool._parse_args(invalid_input) tool._parse_args(invalid_input)
def test_empty_nested_dict():
"""Test handling of empty nested dictionaries."""
def test_func(query: str) -> str:
return f"Processed: {query}"
tool = CrewStructuredTool.from_function(
func=test_func,
name="StringTool",
description="A tool that processes string input"
)
# Test with empty nested dict
empty_dict_input = {"query": {}}
with pytest.raises(ValueError):
tool._parse_args(empty_dict_input)
def test_deeply_nested_structure():
"""Test handling of deeply nested structures."""
def test_func(query: str) -> str:
return f"Processed: {query}"
tool = CrewStructuredTool.from_function(
func=test_func,
name="StringTool",
description="A tool that processes string input"
)
# Test with deeply nested structure
deeply_nested = {"query": {"nested": {"deeper": {"value": "deep value"}}}}
with pytest.raises(ValueError):
tool._parse_args(deeply_nested)