* fix(executor): prepend empty user turn for model-first requests targeting Gemini/Antigravity (#4959)
When forwarding sliced conversation histories or tool calls across OpenAI Responses,
OpenAI Chat Completions, Claude Messages, and native Gemini, native Gemini and Antigravity
Gemini endpoints require that conversation contents begin with a user turn.
Normalize leading turns at the executor boundary rather than the translator layer:
- Prepend an empty user turn ({"role":"user","parts":[{"text":""}]}) for Gemini, Gemini Vertex,
AI Studio, and Antigravity Gemini generation and CountTokens requests if the first turn is 'model'.
- Keep Antigravity Claude requests untouched to avoid adapter 400 errors.
- Ensure normalization runs after payload rules so payload index overrides target the original turns.
- Use no-copy GJSON inspection to keep overhead zero on valid user-first requests.
* fix(executor): inject Antigravity leading user after reasoning replay (#4959)
Replay can insert a model functionCall at contents[0] for sliced
tool-result history. Run the empty-user prepend on the final
requestPayload, after sanitize and prepareAntigravityGeminiReasoningReplayPayload.
- add shared `EnsureResponsesUsageDetails` helper to patch `usage` objects with:
- `output_tokens_details.reasoning_tokens = 0`
- `input_tokens_details.cached_tokens = 0`
- for both plain JSON and SSE `data:` frames, including multi-line frames
- apply the helper to OpenAI Response format outputs in non-stream and stream paths across executors/plugins so translated payloads consistently include required usage details
- update websocket/completion payload builders to emit default `usage` detail fields for prewarm/finish responses
Closes: #4985
Execute, executeClaudeNonStream and ExecuteStream all assign the validated
original payload to the request and then translate both values. Since both
translations saw the same bytes, every Antigravity request paid for a second
full scan of the client payload. On a captured 24MB tool-history request that
second pass cost roughly 0.9s of CPU and 651MB of allocations.
Translate once when both inputs share a backing array and hand the caller an
independent duplicate, because later stages edit the working copy in place.
Payloads that genuinely differ still get two translations.
Client.KVCompareAndSwap sent Redis EVAL with a Lua script, but the Home RESP
subset does not implement EVAL, so Home replied "ERR unknown command 'eval'".
That broke the Antigravity and Codex reasoning replay caches in Home mode.
Switch the transport to Home's dedicated CAS command:
CAS <key> <expected-exists 0|1> <expected-value> <new-value> [PX <ttl-ms>]
The semantics match the old script argument for argument, so KVCompareAndSwap's
signature and all its callers are unchanged. Omitting PX when ttl <= 0 mirrors
the script's SET-without-PX branch, which clears the TTL.
Deployments that predate CAS reject the command. Detect that by matching the
unsupported-command error, latch ErrCompareAndSwapUnsupported for the client
lifetime so later calls skip the round trip, and warn exactly once. The latch is
deliberately not carried across NewLifetime, so a Home upgrade takes effect on
the next reconnect rather than requiring a CPA restart.
Also stop replay-state failures from failing the request. A bare replay error has
no HTTP status, so resultErrorFromError does not classify it as request-scoped and
MarkResult marks the credential unavailable for that model, walking every
candidate credential until alias resolution has nothing left and returns 503. A
ledger miss is already a tolerated outcome, so degrade to "no replay this turn"
instead. The pairing failure still returns its 400.
Verified end to end against a real Home over RESP/mTLS on PostgreSQL with
Antigravity OAuth credentials: patched Home recreates the replay row through CAS
with its TTL, while a pre-CAS Home latches once, keeps returning 200 instead of
503, and records no credential error attributable to the replay path.
Refs router-for-me/CLIProxyAPIHome#79
- Removed deprecated interceptor and executor-related methods, including `callRequestInterceptor`, `callResponseInterceptor`, and `callStreamChunkInterceptor`.
- Consolidated unused logic and pruned redundant imports to streamline `adapters.go`.
- No functional changes.