Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/google/adk/tools/_function_parameter_parse_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ def _parse_schema_from_parameter(

def _get_required_fields(schema: types.Schema) -> list[str]:
if not schema.properties:
return
return []
return [
field_name
for field_name, field_schema in schema.properties.items()
Expand Down
41 changes: 41 additions & 0 deletions tests/unittests/tools/test_build_function_declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from google.adk.features import FeatureName
from google.adk.features._feature_registry import temporary_feature_override
from google.adk.tools import _automatic_function_calling_util
from google.adk.tools import _function_parameter_parse_util
from google.adk.tools.tool_context import ToolContext
from google.adk.utils.variant_utils import GoogleLLMVariant
from google.genai import types
Expand Down Expand Up @@ -198,6 +199,46 @@ def simple_function(input_str: str, tool_context: ToolContext) -> str:
assert function_decl.parameters.properties['input_str'].type == 'STRING'
assert 'tool_context' not in function_decl.parameters.properties

def test_get_required_fields_no_properties_returns_empty_list(self):
# Regression for https://github.com/google/adk-python/issues/5920: the
# declared return type is list[str], so a schema without properties must
# yield [] rather than None for any caller that relies on the declared
# list[str] return.
assert (
_function_parameter_parse_util._get_required_fields(
types.Schema(type='OBJECT')
)
== []
)
assert (
_function_parameter_parse_util._get_required_fields(
types.Schema(type='OBJECT', properties={})
)
== []
)

def test_declaration_required_fields_is_list_not_none(self):
def simple_function(input_str: str) -> str:
return {'result': input_str}

function_decl = _automatic_function_calling_util.build_function_declaration(
func=simple_function
)

assert function_decl.parameters.required == ['input_str']

def test_toolcontext_only_builds_without_none_required(self):
def only_context(tool_context: ToolContext) -> str:
return ''

function_decl = _automatic_function_calling_util.build_function_declaration(
func=only_context, ignore_params=['tool_context']
)

# No parameters remain after ignoring tool_context, so the declaration
# carries no parameter schema instead of one with required=None.
assert function_decl.parameters is None

def test_basemodel(self):
class SimpleFunction(BaseModel):
input_str: str
Expand Down