diff --git a/src/google/adk/tools/_function_parameter_parse_util.py b/src/google/adk/tools/_function_parameter_parse_util.py index a8e98980d5..6da14619e7 100644 --- a/src/google/adk/tools/_function_parameter_parse_util.py +++ b/src/google/adk/tools/_function_parameter_parse_util.py @@ -294,6 +294,17 @@ def _parse_schema_from_parameter( args = get_args(param.annotation) if origin is dict: schema.type = types.Type.OBJECT + if len(args) == 2: + value_type = args[1] + schema.additional_properties = _parse_schema_from_parameter( + variant, + inspect.Parameter( + 'value', + inspect.Parameter.POSITIONAL_OR_KEYWORD, + annotation=value_type, + ), + func_name, + ) if param.default is not inspect.Parameter.empty: if not _is_default_value_compatible(param.default, param.annotation): raise ValueError(default_value_error_msg) diff --git a/tests/unittests/tools/test_build_function_declaration.py b/tests/unittests/tools/test_build_function_declaration.py index 608f06cb13..cfaeaa765d 100644 --- a/tests/unittests/tools/test_build_function_declaration.py +++ b/tests/unittests/tools/test_build_function_declaration.py @@ -102,6 +102,53 @@ def simple_function(input_str: dict[str, str]) -> str: assert function_decl.name == 'simple_function' assert function_decl.parameters.type == 'OBJECT' assert function_decl.parameters.properties['input_str'].type == 'OBJECT' + assert ( + function_decl.parameters.properties[ + 'input_str' + ].additional_properties.type + == 'STRING' + ) + + +def test_dict_input_with_int_values(): + def simple_function(input_str: dict[str, int]) -> str: + return {'result': input_str} + + function_decl = _automatic_function_calling_util.build_function_declaration( + func=simple_function + ) + + assert function_decl.name == 'simple_function' + assert function_decl.parameters.type == 'OBJECT' + assert function_decl.parameters.properties['input_str'].type == 'OBJECT' + assert ( + function_decl.parameters.properties[ + 'input_str' + ].additional_properties.type + == 'INTEGER' + ) + + +def test_list_of_dict_input(): + """Test list[dict[str, str]] emits proper schema with additional_properties.""" + + def simple_function(fruits: list[dict[str, str]]) -> str: + return str(fruits) + + function_decl = _automatic_function_calling_util.build_function_declaration( + func=simple_function + ) + + assert function_decl.name == 'simple_function' + assert function_decl.parameters.type == 'OBJECT' + assert function_decl.parameters.properties['fruits'].type == 'ARRAY' + assert function_decl.parameters.properties['fruits'].items.type == 'OBJECT' + assert ( + function_decl.parameters.properties[ + 'fruits' + ].items.additional_properties.type + == 'STRING' + ) def test_basemodel_input(): @@ -279,6 +326,12 @@ def simple_function( assert function_decl.parameters.properties['input_str'].items.type == 'STRING' assert function_decl.parameters.properties['input_dir'].type == 'ARRAY' assert function_decl.parameters.properties['input_dir'].items.type == 'OBJECT' + assert ( + function_decl.parameters.properties[ + 'input_dir' + ].items.additional_properties.type + == 'STRING' + ) def test_enums():