Commit Graph

9 Commits

Author SHA1 Message Date
sususu98
62f5a2798c fix(executor): prepend empty user turn for model-first Gemini/Antigravity requests (#4959) (#5048)
* 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.
2026-08-19 18:56:43 +08:00
Luis Pater
e0b4956242 fix(openai): ensure Responses usage includes token detail fields
- 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
2026-08-15 15:00:19 +08:00
sususu
cf8c27fe90 perf(antigravity): translate each upstream request once
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.
2026-08-11 16:07:42 +08:00
Luis Pater
42eef103d6 feat(antigravity): obfuscate sensitive words in system instructions
Closes: #4696 #4723 #4732
2026-08-05 00:27:32 +08:00
Supra4E8C
1df21b14bf fix(usage): update token fingerprint after refresh 2026-08-03 21:39:48 +08:00
sususu
0c2ec7da23 fix(thinking): honor normalized summary payloads 2026-07-31 12:45:13 +08:00
sususu
b3046d29b9 feat(thinking): preserve cross-protocol summary visibility 2026-07-30 21:53:30 +08:00
sususu
20784c67ff fix(home): use Home's CAS command instead of EVAL for replay compare-and-swap
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
2026-07-29 09:44:05 +08:00
Luis Pater
fe4ae4989c chore(pluginhost): refactor and remove unused interceptors and executor methods
- 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.
2026-07-26 14:31:45 +08:00