Integrate #13: what a current Gemini model refuses - #19
Merged
Merged
Conversation
Three faults between the provider and Gemini 3, found by pointing a duck at gemini-3.5-flash. The schema cleaner did not strip exclusiveMinimum/exclusiveMaximum. pydantic writes gt=0 that way, so every verb with a timeout_s or a duration_s carried one, and google-genai 2.x validates the declaration and refuses the keyword. The executor still enforces the bound on the way in. The default model, gemini-2.5-pro, answers 'no longer available to new users'. The default is now the gemini-pro-latest alias, on purpose: a default that 404s is worse than one that moves. Gemini 3 signs each function call with a thought_signature that the next turn must hand back on that same call, or the request is refused with a 400. ToolCall carries it as base64 text (signature, empty for every other provider) and render_contents puts the bytes back on the function_call part. Verified with a two-step run to success on gemini-3.5-flash with thought summaries on; ruff, mypy and the full suite are green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…fuses Bayway's three fixes, merged whole. Conflicts were resolved to his side so his diff lands as written; what main solved differently since is corrected in the commit after this one, not in his lines. Conflicts: gemini.py (main replaced DEFAULT_MODEL with the model catalogue), tests/test_providers.py (the same assertion), CHANGELOG.md (both sides added entries under Unreleased; both are kept). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bayway's third fix pointed the default at the `gemini-pro-latest` alias because
`gemini-2.5-pro` had started answering "no longer available to new users". Main
solved the same problem differently while the PR was open: ADR-0031 replaced the
per-provider constant with the model catalogue, and `default_model_for("gemini")`
now returns its first entry.
So the constant this branch reintroduced was dead on arrival -- nothing read it,
because the constructor takes the catalogue's answer. Removed, with the test
assertion put back on `default_model_for("gemini")` rather than a literal, which
is what keeps it honest when the catalogue's first entry moves again.
The CHANGELOG entry loses that third item and says two. It gains the thing that
matters more now: the catalogue's first Gemini entry is a Gemini 3 model, so both
remaining fixes are on the default path rather than an opt-in one. The schema bug
is every robot, not some -- `move` and `go_to` are core verbs and both carry a
`gt=0` bound.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CONTRIBUTING says anything the review found by reading, the next review should find by failing. This one was found by reading: `move` and `go_to` are core verbs, both bound `gt=0`, so pydantic gave both an exclusiveMinimum and Gemini refused the declaration on every robot. The existing test proves `clean_schema` handles a schema written in the test. This one runs `default_registry().tool_schemas()` -- the real fifteen -- and asserts no key in UNSUPPORTED_SCHEMA_KEYS survives. It also asserts that some verb still carries a bound before cleaning, because the day none does this test would pass for the wrong reason and quietly stop guarding the agreement between quackd/verbs/core.py and that set. Checked it fails without the fix: drop the two keys and exclusiveMinimum leaks. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Integration branch for #13 (@Bayway), handled the way CONTRIBUTING describes: merged with
git merge, never squashed or rebased, his commit verbatim, corrections on top in named commits.Commits
e570573fix(gemini): a current Gemini model as the pilot7d92378fb19360fix(gemini): the catalogue already chose the modelf3cdd94test(gemini): the verbs quackd actually sends, not a schema written hereWhat of his was kept
Two of his three fixes, and both are live on the default path — the catalogue's first Gemini entry is
gemini-3.8-flash, a Gemini 3 model:exclusiveMinimum/exclusiveMaximumnot stripped. pydantic writesgt=0that way and google-genai 2.x refuses the declaration.moveandgo_toare core verbs and both carry a bound, so this was every robot, not some.function_callis signed and the next turn is refused with a 400 unless the signature comes back on that same call.What was corrected, and why
His third fix pointed
DEFAULT_MODELat thegemini-pro-latestalias becausegemini-2.5-prohad started answering "no longer available to new users". Real problem — but ADR-0031 solved it differently while the PR was open, replacing the per-provider constant with the model catalogue. The constant this branch reintroduced was dead on arrival: the constructor takesdefault_model_for("gemini"). Removed, and the test assertion put back on the catalogue rather than a literal.The CHANGELOG entry said "Three things"; it says two, and now records that both remaining fixes are on the default path.
Test added
Rule 4 — anything the review found by reading, the next review should find by failing. His schema test uses a hand-written dict; the new one runs
default_registry().tool_schemas()(the real fifteen) and asserts nothing inUNSUPPORTED_SCHEMA_KEYSsurvives. It also asserts some verb still carries a bound, so it cannot pass for the wrong reason later. Mutation-checked: drop the two keys andexclusiveMinimumleaks.Gate, on the merged result
ruff check·ruff format --check(againstgit archivebytes, not the CRLF tree) ·mypyon 3.11 and 3.12 · fullpytest— all green locally on Windows. This PR exists to get macOS, Linux and the physics job too.Older breakage this surfaced
Rule 5. The Gemini path has been broken on
mainsince google-genai 2.x — every robot, every Gemini run, not only Gemini 3. Worth saying in the release note.🤖 Generated with Claude Code