4a9b22719b
* fix(antigravity): translate JSON Schema unions to Gemini nullable Tool parameter schemas using JSON Schema 2020-12 unions like "type": ["string", "null"] crash Gemini's function_declarations parser with HTTP 400. Two existing tools trip this: - core/framework/tasks/tools/colony_tools.py:52 (owner in _update_schema) - core/framework/tasks/tools/session_tools.py:84-87 (same shape) Add an adapter-level sanitizer that walks the schema tree and converts union-with-null to OpenAPI 3.0 "nullable": true (which Gemini accepts). Recurses into properties, items, additionalProperties, and the anyOf/oneOf/allOf combinators. Source schemas remain valid JSON Schema so OpenAI/Anthropic backends are unaffected. * fix(antigravity): bump spoofed UA past Google's deprecation cutoff Google has deprecated client version "Antigravity/1.18.3" — chats now return "This version of Antigravity is no longer supported" instead of a real model response. Bump the spoofed User-Agent to "Antigravity/1.23.2" + "Electron/39.2.3" (current desktop release) and add a comment that this needs periodic re-bumping. A more durable fix (auto-detect from the installed app's Info.plist) is a follow-up. * fix(antigravity): fail loud on multi-type non-null Gemini schema unions Per review on PR #7170: silently picking the first type from a union like ["string", "integer", "null"] changes the contract for callers that rely on the other types, and the failure is hard to diagnose at the Gemini side. Replace the silent narrowing with a ValueError that points the schema author at anyOf or a single type. A repo scan finds no current Gemini-bound schemas using multi-type non-null unions, so this branch is preventative for future authors. * chore(antigravity): drop em dash from test docstring
74 lines
2.3 KiB
Python
74 lines
2.3 KiB
Python
"""Tests for the Antigravity Gemini schema sanitizer.
|
|
|
|
Run with:
|
|
cd core
|
|
pytest tests/test_antigravity_schema.py -v
|
|
"""
|
|
|
|
import pytest
|
|
|
|
from framework.llm.antigravity import _sanitize_schema_for_gemini
|
|
|
|
|
|
def test_union_with_null_becomes_nullable():
|
|
assert _sanitize_schema_for_gemini({"type": ["string", "null"]}) == {
|
|
"type": "string",
|
|
"nullable": True,
|
|
}
|
|
|
|
|
|
def test_plain_schema_passthrough():
|
|
assert _sanitize_schema_for_gemini({"type": "string"}) == {"type": "string"}
|
|
|
|
|
|
def test_recurses_into_properties():
|
|
out = _sanitize_schema_for_gemini(
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {"type": "integer"},
|
|
"owner": {"type": ["string", "null"]},
|
|
},
|
|
"required": ["id"],
|
|
}
|
|
)
|
|
assert out["properties"]["id"] == {"type": "integer"}
|
|
assert out["properties"]["owner"] == {"type": "string", "nullable": True}
|
|
assert out["required"] == ["id"]
|
|
|
|
|
|
def test_recurses_into_items():
|
|
assert _sanitize_schema_for_gemini({"type": "array", "items": {"type": ["integer", "null"]}}) == {
|
|
"type": "array",
|
|
"items": {"type": "integer", "nullable": True},
|
|
}
|
|
|
|
|
|
def test_recurses_into_combinators():
|
|
assert _sanitize_schema_for_gemini({"anyOf": [{"type": ["string", "null"]}, {"type": "integer"}]}) == {
|
|
"anyOf": [{"type": "string", "nullable": True}, {"type": "integer"}]
|
|
}
|
|
|
|
|
|
def test_does_not_mutate_input():
|
|
schema = {"type": "object", "properties": {"x": {"type": ["string", "null"]}}}
|
|
snapshot = {"type": "object", "properties": {"x": {"type": ["string", "null"]}}}
|
|
_sanitize_schema_for_gemini(schema)
|
|
assert schema == snapshot
|
|
|
|
|
|
def test_pure_null_type_falls_back_to_string():
|
|
assert _sanitize_schema_for_gemini({"type": ["null"]}) == {
|
|
"type": "string",
|
|
"nullable": True,
|
|
}
|
|
|
|
|
|
def test_multi_type_non_null_union_raises():
|
|
"""Silently picking one type would change the contract; fail loud instead."""
|
|
with pytest.raises(ValueError, match="Unsupported Gemini schema union"):
|
|
_sanitize_schema_for_gemini({"type": ["string", "integer", "null"]})
|
|
|
|
with pytest.raises(ValueError, match="Unsupported Gemini schema union"):
|
|
_sanitize_schema_for_gemini({"type": ["string", "integer"]})
|