Skip to content

fix: prevent googleSearch + functionDeclarations mixed tools regression#2245

Open
thebtf wants to merge 7 commits intolbjlaq:mainfrom
thebtf:fix/no-mixed-tools-regression
Open

fix: prevent googleSearch + functionDeclarations mixed tools regression#2245
thebtf wants to merge 7 commits intolbjlaq:mainfrom
thebtf:fix/no-mixed-tools-regression

Conversation

@thebtf
Copy link

@thebtf thebtf commented Mar 3, 2026

Summary

v4.1.28 introduced a supports_mixed_tools model-based allowlist that re-enabled mixing googleSearch with functionDeclarations for gemini-2.0/2.5/3.x models. This causes 400 errors because the Gemini generateContent API does not support mixed tool types — this is a model-level restriction, not an SDK limitation.

Evidence

Error reproduced

{
  "error": {
    "code": 400,
    "message": "Built-in tools ({google_search}) and Custom tools (Function Calling) cannot be combined in a single request for models/gemini-2.5-flash-preview-04-17"
  }
}

Changes

File Change
common_utils.rs Remove mapped_model param and supports_mixed_tools allowlist from inject_google_search_tool; unconditionally skip injection when functionDeclarations present
claude/request.rs Rewrite build_tools to make functionDeclarations and googleSearch mutually exclusive (functionDeclarations take priority)
gemini/wrapper.rs Update call site
openai/request.rs Update call site

Regression history

Version Behavior
v4.1.27 Correct: if has_functions { return } — never mixed
v4.1.28 Regression: added supports_mixed_tools allowlist — mixed tools on 2.0/2.5/3.x → 400
This PR Restores v4.1.27 behavior, cleans up dead code, fixes all code paths

Test plan

  • Verify inject_google_search_tool skips injection when functionDeclarations exist
  • Verify build_tools (Claude mapper) produces only functionDeclarations when both tools + web_search present
  • Updated test assertions to validate no mixed tools are produced
  • Manual test: Claude Code session with MCP tools through AGM → Gemini (no 400 error)

Kirill Turanskiy and others added 7 commits March 3, 2026 17:18
* feat: add CLI config export for web/Docker mode

In web mode (Docker), the One-click CLI Sync section now generates
drop-in config files for all 5 CLI tools (Claude Code, Codex, Gemini CLI,
OpenCode, Droid) and writes them to ~/.antigravity_tools/one-click-sync/
which is volume-mounted to the host.

Backend:
- Extract generate_file_content() helper from sync_config() in cli_sync.rs
- Add export_config() and get_export_status() for Claude/Codex/Gemini
- Add export functions to opencode_sync.rs and droid_sync.rs
- Add 6 HTTP routes and handlers in server.rs
- Register 6 new Tauri commands in lib.rs

Frontend:
- Detect web mode via isTauri() and adapt CliSyncCard UI
- Show "Export Mode" badge, "Exported/Not Exported" status
- Show export directory instead of base URL
- "Export" button replaces "Sync", hide Restore/View/Clear in web mode
- Non-destructive confirm dialog for export operations

* fix: address code review findings — safer JSON handling, atomic writes

- Replace unwrap() chains on nested JSON with safe if-let patterns
- Use atomic temp+rename for export_config() writes
- Replace unwrap() on serialization with map_err in opencode/droid export
- Add remove_file before rename for Windows compatibility
- Check all files exported (not just any) in get_export_status()

* feat: Claude Code 3-tier model support (opus/sonnet/haiku) + export UX

- Add ClaudeModelTiers struct for opus/sonnet/haiku model selection
- Set all Claude Code env vars: ANTHROPIC_MODEL, ANTHROPIC_DEFAULT_OPUS/SONNET/HAIKU_MODEL, CLAUDE_CODE_SUBAGENT_MODEL
- Clean stale tier vars on fallback to single-model mode
- Replace single model selector with 3 GroupedSelect for Claude
- Add export usage instructions banner in web mode
- Fix: Windows-only remove_file before rename with error propagation
- Fix: consistent field visibility in CliSyncRequest
- Bump version to 4.1.27

* feat: persist CLI sync model selections in localStorage

Model selections (including Claude 3-tier opus/sonnet/haiku) now
survive page reloads via localStorage persistence.

---------

Co-authored-by: Kirill Turanskiy <kt@novamedia.ru>
…mismatch

export_config skips config.json when settings.json exists, but
get_export_status counted all 3 files as expected. Now mirrors
the same skip logic so exported count matches expected count.
In Docker/web mode, CLI tools run on the host machine, not inside
the container. The exported proxy URL now uses window.location.hostname
(the address the user accessed the UI from) instead of 127.0.0.1.
…ression)

v4.1.28 introduced a `supports_mixed_tools` allowlist that enabled mixing
googleSearch with functionDeclarations for gemini-2.0/2.5/3.x models.
This causes 400 errors because the Gemini generateContent API does NOT
support mixed tool types — this is a model-level restriction confirmed by
Google documentation and staff (google/adk-python#969).

Only the Live API (WebSocket) supports combining built-in tools with
custom function declarations.

Changes:
- common_utils: remove mapped_model parameter and supports_mixed_tools
  allowlist from inject_google_search_tool; unconditionally skip injection
  when functionDeclarations are present
- claude/request: rewrite build_tools to make functionDeclarations and
  googleSearch mutually exclusive (functionDeclarations take priority)
- Update all call sites (gemini/wrapper, openai/request, claude/request)
- Fix tests to assert mixed tools are never produced
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant