diff --git a/src/google/adk/tools/_gemini_schema_util.py b/src/google/adk/tools/_gemini_schema_util.py index 08e8d4e6c1..6ec4f889b5 100644 --- a/src/google/adk/tools/_gemini_schema_util.py +++ b/src/google/adk/tools/_gemini_schema_util.py @@ -106,7 +106,11 @@ def _sanitize_schema_type( def _dereference_schema(schema: dict[str, Any]) -> dict[str, Any]: """Resolves $ref pointers in a JSON schema.""" - defs = schema.get("$defs", {}) + defs = {} + if isinstance(schema.get("definitions"), dict): + defs.update(schema["definitions"]) + if isinstance(schema.get("$defs"), dict): + defs.update(schema["$defs"]) def _resolve_refs(sub_schema: Any, path_refs: frozenset[str]) -> Any: if isinstance(sub_schema, dict): @@ -151,6 +155,8 @@ def _resolve_refs(sub_schema: Any, path_refs: frozenset[str]) -> Any: # Remove the definitions block after resolving. if "$defs" in dereferenced_schema: del dereferenced_schema["$defs"] + if "definitions" in dereferenced_schema: + del dereferenced_schema["definitions"] return dereferenced_schema diff --git a/tests/unittests/tools/test_gemini_schema_util.py b/tests/unittests/tools/test_gemini_schema_util.py index d919172527..92c6e3c8f9 100644 --- a/tests/unittests/tools/test_gemini_schema_util.py +++ b/tests/unittests/tools/test_gemini_schema_util.py @@ -337,6 +337,55 @@ def test_to_gemini_schema_nested_dict_with_defs_and_ref(self): ] assert gemini_schema.properties["payload"].required == ["adDomain"] + def test_to_gemini_schema_nested_dict_with_draft07_definitions_and_ref(self): + openapi_schema = { + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "DeviceEnum": { + "enum": ["GLOBAL", "desktop", "mobile"], + "type": "string", + }, + "DomainPayload": { + "properties": { + "adDomain": { + "items": {"type": "string"}, + "type": "array", + }, + "device": { + "$ref": "#/definitions/DeviceEnum", + "default": "GLOBAL", + }, + }, + "required": ["adDomain"], + "type": "object", + }, + }, + "properties": {"payload": {"$ref": "#/definitions/DomainPayload"}}, + "required": ["payload"], + "type": "object", + } + gemini_schema = _to_gemini_schema(openapi_schema) + assert gemini_schema.type == Type.OBJECT + assert gemini_schema.properties["payload"].type == Type.OBJECT + assert ( + gemini_schema.properties["payload"].properties["adDomain"].type + == Type.ARRAY + ) + assert ( + gemini_schema.properties["payload"].properties["adDomain"].items.type + == Type.STRING + ) + assert ( + gemini_schema.properties["payload"].properties["device"].type + == Type.STRING + ) + assert gemini_schema.properties["payload"].properties["device"].enum == [ + "GLOBAL", + "desktop", + "mobile", + ] + assert gemini_schema.properties["payload"].required == ["adDomain"] + def test_sanitize_integer_formats(self): """Test that int32 and int64 formats are preserved for integer types""" openapi_schema = {