When enabled, the server uses only the embedded models.json loaded at
init() and skips registry.StartModelsUpdater(), disabling the initial
remote fetch and 3-hour periodic refresh. The management panel
auto-updater (managementasset.StartAutoUpdater) is unaffected.
gjson.Parse() marks any string starting with { or [ as gjson.JSON type,
even when the content is not valid JSON (e.g. macOS plist format, truncated
tool results). This caused sjson.SetRaw to embed non-JSON content directly
into the Gemini API request payload, producing 400 errors.
Add json.Valid() check before using SetRaw to ensure only actually valid
JSON is embedded raw. Non-JSON content now falls through to sjson.Set
which properly escapes it as a JSON string.
Fixes#2161
The Claude-to-Gemini translator derived function names by splitting
tool_use_id on "-", which produced empty strings for IDs with exactly
2 segments (e.g. toolu_tool-<uuid>). Replace the string-splitting
heuristic with a lookup map built from tool_use blocks during the
main processing loop, with fallback to the raw ID on miss.
Only emit note in listAuthFilesFromDisk when the JSON value is actually
a string (gjson.String), matching the synthesizer/buildAuthFileEntry
behavior. Non-string values like numbers or booleans are now ignored
instead of being coerced via gjson.String().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
buildAuthFileEntry now falls back to reading priority/note from
auth.Metadata when Attributes lacks them. This covers auths registered
via UploadAuthFile which bypass the synthesizer and only populate
Metadata from the raw JSON.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Read note from Attributes (consistent with priority) in buildAuthFileEntry,
fixing missing note on Gemini multi-project virtual auth cards.
- Propagate note from primary to virtual auths in SynthesizeGeminiVirtualAuths,
mirroring existing priority propagation.
- Sync note/priority writes to both Metadata and Attributes in PatchAuthFileFields,
with refactored nil-check to reduce duplication (review feedback).
- Validate priority type in fallback disk-read path instead of coercing all values
to 0 via gjson.Int(), aligning with the auth-manager code path.
- Add regression tests for note synthesis, virtual-auth note propagation, and
end-to-end multi-project Gemini note inheritance.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gemini API rejects uniqueItems in tool schemas with 400. Add it to
unsupportedConstraints alongside minItems/maxItems where it belongs.
Same class of fix as #1424 and #1531.
When assistant has tool_calls but no text content, the translator
emitted an empty message into the Responses API input array before
function_call items. The API then couldn't match function_call_output
to its function_call by call_id, returning:
No tool output found for function call ...
Only emit assistant messages that have content parts. Tool-call-only
messages now produce function_call items directly.
Added 9 tests for tool calling translation covering single/parallel
calls, multi-turn conversations, name shortening, empty content
edge cases, and call_id integrity.
The list endpoint previously omitted priority and note, which are stored
inside each auth file's JSON content. This adds them to both the normal
(auth-manager) and fallback (disk-read) code paths, and extends
PATCH /auth-files/fields to support writing the note field.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. Claude translator: add CleanJSONSchemaForGemini() to sanitize tool
input schemas (removes $schema, anyOf, const, format, etc.) and
delete eager_input_streaming from tool declarations. Remove fragile
bytes.Replace for format:"uri" now covered by schema cleaner.
2. Gemini native translator: filter out content entries with empty or
missing parts arrays to prevent Gemini API 400 error "required
oneof field 'data' must have one initialized field".
Both fixes align gemini-cli with protections already present in the
antigravity translator.
when Amp or Claude Code sends functionResponse with an empty name in Gemini
conversation history, the Gemini API rejects the request with 400
"Name cannot be empty". this fix backfills empty names from the
corresponding preceding functionCall parts using positional matching.
covers all three Gemini translator paths:
- gemini/gemini (direct API key)
- antigravity/gemini (OAuth)
- gemini-cli/gemini (Gemini CLI)
also switches fixCLIToolResponse pending group matching from LIFO to
FIFO to correctly handle multiple sequential tool call groups.
fixes#1903