Commit Graph

174 Commits

Author SHA1 Message Date
sususu
c0b76c2d09 refactor(devin): keep sensitive words strictly external in config.yaml without hardcoding 2026-09-13 23:34:43 +08:00
sususu
c0b86059c4 fix(devin): sanitize claude subagent identity and emoji directives to prevent content policy 403 2026-09-13 23:34:43 +08:00
sususu
f5247e496f fix(devin): restrict sensitive word obfuscation strictly to system prompt only 2026-09-13 23:34:43 +08:00
sususu
02fd1bde78 feat(devin): restrict glm-5-2 to free tier, remove static swe-1-7-lightning, and harden cloak 2026-09-13 23:34:43 +08:00
sususu
eed249072d feat(devin): prefix all Devin model IDs with devin/ namespace 2026-09-13 23:34:43 +08:00
sususu
cbe800aa28 feat(devin): bind upstream session_id and cascade_id to CPA canonical session 2026-09-13 23:34:43 +08:00
sususu
f94752762b feat(devin): add Devin/Cognition provider integration and CLI OAuth
Implement the full Devin/Cognition Connect-RPC provider support across all CPA endpoints (/v1/chat/completions, /v1/messages, /v1/responses), complete with binary protobuf wire framing, streaming tools/arguments delta handling, thinking/reasoning replay, and CLI OAuth authentication.

Key highlights:
- Wire Protocol & Streaming:
  * Implemented Connect-RPC uncompressed 5-byte framing (0x00 + 4-byte length + protobuf) for ApiServerService/GetChatMessage.
  * Implemented Devin protobuf encoder/decoder in internal/runtime/executor/helps/devin_wire.go, including ClientMetadata, prompts, tools, completion_config, and multimodal image handling (Prompt Field #10).
  * Stream frame consumption via interactions protocol, correctly mapping arguments_delta and tracking multiple sequential tool calls (currentToolCallActive).
  * Streaming thought summary and sealed.v1 signature deltas targeting the thinking step.

- Model Registration & Thinking Clamping:
  * Registered static fallback models in model_definitions.go (swe-2, claude-fable-5-1, gpt-6-astra, swe-1-7-lightning, glm-5-2, glm-5-3).
  * Configured ThinkingSupport with discrete levels per model family.
  * Implemented CPA-standard nearest-neighbor clamping for thinking levels (minimal/low -> medium, xhigh -> max for swe-2).
  * Mapped thinking effort to Devin upstream model UID (e.g. swe-2-medium, swe-2-high, swe-2-max).

- Sensitive Words & System Prompt Sanitization:
  * Added devin.sensitive-words configuration in internal/config/config_types.go and config.go, matching Antigravity conventions.
  * Supported zero-width space (\u200b) obfuscation in prompts, tools, and system instructions via SensitiveWordMatcher.
  * Stripped Claude Code billing headers (x-anthropic-billing-header:) and CLI identity signatures from system instructions and tool descriptions to avoid upstream content filter rejections.

- Signature Compatibility:
  * Added SignatureProviderSWE = "swe" recognizing sealed.v1.* reasoning signatures in internal/signature/provider_compatibility.go.
  * Propagated reasoning.encrypted_content on Responses API and thinking.signature on Messages API.

- Authentication:
  * Implemented Devin PKCE OAuth flow with loopback callback server and headless manual token/code paste (--no-browser).
  * Registered Devin authenticator in SDK and CLI (-devin-login flag).
  * Integrated with management OAuth session endpoints and credentials manager.
2026-09-13 23:34:43 +08:00
Luis Pater
94d6eb535e docs(config): document payload filter examples for codex tools
- Add example payload filter rules in `config.example.yaml` for stripping tools from both flat and nested `additional_tools` Codex request payloads.

Closes: #5792
2026-09-13 22:12:28 +08:00
Luis Pater
f702bc1ac2 feat(codex): preserve native fidelity for responses-lite requests
- Detect native responses-lite requests via headers and client metadata.
- Skip instructions normalization and synthetic session cloaking for native requests.
- Preserve upstream completion output during websocket response forwarding.

Closes: #5780
2026-09-13 15:05:03 +08:00
Luis Pater
377c315fd7 fix(claude): anchor billing fingerprint to initial turn for cloaked cache stability
- Derive billing fingerprint message text from the first user message to prevent prompt cache invalidation across turns.
- Centralize continuity tag resolution to maintain stable prompt IDs and request references across requests.

Closes: #5730
2026-09-11 16:59:57 +08:00
Luis Pater
4edf9d1dd6 fix(thinking): extract configuration_update reasoning effort in codex usage reporting
- Inspect `input` items for the latest `configuration_update` reasoning effort before falling back to top-level configuration.
- Route `codex`, `xai`, and `openai-response` providers through usage-specific thinking config extraction.
- Support `none`, `auto`, and explicit reasoning level modes from in-turn updates.

Closes: #5714
2026-09-11 12:15:57 +08:00
Luis Pater
c8f723e0fb feat(usage): propagate upstream base_url across usage records and plugin auth
- Add `BaseURL` field to usage records and host auth file entries.
- Extract `base_url` from auth attributes and metadata during usage reporting.
- Propagate `base_url` through plugin usage adapters and runtime auth callbacks.

Closes: #5693
2026-09-11 00:25:17 +08:00
Luis Pater
6a73f39627 fix(claude): preserve 1h cache ttl and beta header for subagent requests
- Retain `cache_control` blocks with 1h TTL and `extended-cache-ttl` beta header when explicitly requested by subagents.
- Detect 1h TTL configuration from request payloads and incoming Anthropic-Beta headers.
- Ensure `extended-cache-ttl` beta header is preserved or injected when 1h TTL is present.

Closes: #5629
2026-09-10 10:58:34 +08:00
Luis Pater
3bf787fc1d feat(auth): propagate canonical session id for custom header expansion
- Initialize `util.SessionIDResolver` to resolve session IDs from request contexts, metadata, and headers.
- Ensure canonical session metadata is injected into execution options across execution flows.
- Propagate session context in executors to support `$CPA-SESSION-ID` expansion in custom headers.
- Sync cleared or updated session identities back to execution contexts during conductor execution.

Closes: #5690
2026-09-10 01:43:37 +08:00
Luis Pater
db011593ca Merge pull request #5677 from sususu98/fix/codex-tool-schema-pattern
fix(translator): strip unsupported unicode property escape patterns from tool schemas
2026-09-09 18:22:16 +08:00
sususu
37ce368c50 fix(schema): inspect patternProperties keys and avoid Unicode escape fast-path bypass
- Check for \u in fast-path check to prevent JSON Unicode escapes from bypassing inspection.
- Inspect regex keys under patternProperties and drop keys with unsupported Unicode property escapes.
- Add tests covering Unicode escape representations (\u005c, \u0070, \u0050) and patternProperties keys.
2026-09-09 18:03:39 +08:00
sususu
e56abd56f1 fix(translator): strip unsupported unicode property escape patterns from tool schemas
- Add HasUnsupportedUnicodePropertyEscape in internal/util to detect \p{...} / \P{...} escapes that fail Python re compilation.
- Strip incompatible pattern attributes during tool parameter normalization in codex/claude and openai/claude translators.
- Provide schema-aware fallback stripping in codex executor helps to protect downstream Codex requests without mutating non-schema user data.
- Export unified schema keyword lists in internal/util to eliminate duplication.
- Add comprehensive unit tests covering Artifact fixtures, lookaheads, and user data preservation.

Closes: #5644
2026-09-09 17:49:13 +08:00
Luis Pater
a59b1764e7 fix(claude): emit trailing usage chunk and aggregate stream usage
- Emit an OpenAI-compatible trailing usage chunk with an empty choices array on `message_stop`.
- Include `cache_write_tokens` in prompt token details for OpenAI response translations.
- Parse usage from `message.usage` and buffer Claude stream usage across chunks to merge input and output token counts.
- Ensure observed streaming usage details are published on completion or stream failure.

Closes: #5617
2026-09-09 10:48:05 +08:00
sususu
390589159e feat(session): enhance harness hierarchy recognition and deduplicate selector extraction 2026-09-08 17:04:58 +08:00
Luis Pater
d4146bde12 feat(kimi): support openai responses api
- Route `openai-response` source format requests to dedicated streaming and non-streaming responses handlers.
- Add upstream URL resolution for Kimi Responses API endpoints based on auth attributes.
- Normalize `openai-response` provider format to codex during thinking parameter resolution.

Closes: #5400 #5571
2026-09-08 10:52:27 +08:00
이현민
280b96acea fix(claude): align beta assembly and Haiku helper transport with the measured 2.1.258
advanced-tool-use-2025-11-20 is sent only while tool search or another
advanced tool-use feature is on the wire, or when the caller asks for it;
2.1.258 no longer attaches it to plain tool declarations (measured: 158
inline tools, no beta). A caller-supplied afk-mode-2026-01-31 is forwarded
between fast-mode and extended-cache-ttl and is an insertion boundary for
the advisor beta.

2.1.258 Haiku helpers offer the same full compression set as the main
thread and never send X-Stainless-Async. x-client-request-id is attached
only when the client's base URL is api.anthropic.com, so the helper
transport check accepts an empty value or a valid UUID and rejects only a
malformed one.
2026-09-08 10:34:05 +08:00
Luis Pater
bf20b999de fix(codex): simplify complex tool schema unions and detect empty incomplete responses
- Normalize complex constant `oneOf` and `anyOf` tool parameter schemas into equivalent enums to prevent upstream aborts.
- Escape property keys containing dots and colons during schema updates to prevent invalid path splitting.
- Identify terminal `response.incomplete` events with zero output tokens and no content as upstream failures.

Closes: #5551
2026-09-07 20:09:29 +08:00
sususu
d5397905f0 fix(antigravity): default to short connections and harden connection pool lifecycle (fixes #5494)
- Configure upstream connection pool under antigravity.connection-pool with enabled: false by default.
- In short connection mode, set MaxIdleConnsPerHost = -1 with DisableKeepAlives = false, ensuring immediate TCP termination after response body completion without leaking Connection: close request headers.
- When pooling is explicitly enabled (enabled: true), cap idle-conn-timeout at 210s (leaving a 30s safety buffer below Google Frontend's 240s Keep-Alive cutoff) and default max-idle-conns-per-host to 2 (bounded at 100).
- Refactor TransportCache to execute CloseIdleConnections outside the mutex lock during LRU eviction and matching closes.
- Proactively evict and close idle connections on 429 quota exhaustion across Execute, ExecuteStream, and CountTokens.
- Wire hot-reload diff detection and server reload purge hooks for graceful transport pool updates.
2026-09-07 19:15:39 +08:00
Luis Pater
5dc428f392 fix(gemini): append trailing user turn for requests ending with model content
- Ensure Gemini, AI Studio, Vertex, and Antigravity requests end with a user turn to prevent upstream errors when trailing with model content.
- Preserve trailing turns that contain a function response and skip trailing adjustments for `countTokens` actions or Claude models.
- Introduce boundary normalization helpers to validate both leading and trailing turn roles.

Closes: #5358
2026-09-06 23:41:12 +08:00
Luis Pater
70f4560452 feat(antigravity): add conversation compaction support and capsule encryption
- Add payload detection and preparation helpers for compaction triggers and summary generation.
- Implement AES-GCM sealing and unsealing to store and restore opaque compaction capsules across turns.
- Support expanding compaction capsules into developer context for downstream turns.
- Provide summary text extraction across Gemini, Claude, and OpenAI response formats.
- Add builders for compaction non-stream JSON responses and SSE stream frames.

Closes: #5094
2026-09-06 21:51:47 +08:00
sususu
580df36423 feat(usage): propagate session and parent session hierarchy to usage reporting queue
- Reuse coresession.ExtractSessionInfo across HTTP headers and request payloads to unify canonical session prefix namespaces with the scheduler.
- Extract hierarchical session identities in two phases: initial extraction from request headers on entry, and authoritative deep extraction once request payloads and metadata are available.
- Support Claude Code multi-level subagents (X-Claude-Code-Agent-Id, metadata.agent_id) and Codex thread fork lineages.
- Propagate SessionID and ParentSessionID across ClientRequestMetadata, UsageReporter, and coreusage.Record without root_session_id.
- Include session_id and parent_session_id in queuedUsageDetail for Home LPushUsage forwarding and Redis consumption with self-loop guards.
- Add comprehensive test coverage for canonical headers, body extraction, ghost parent elimination, and self-referential loop guards.
2026-09-06 10:45:32 +08:00
sususu
de4aa60028 feat(claude): add Fable 5.1 reporting outcomes block and post-payload reconciliation
- Inject '# Reporting outcomes' system block for Fable 5.1 / Mythos 5.1 models matching Claude Code 2.1.258 tengu_dapper_lagoon behavior.
- Support both string-format and block-array system prompts for Fable reporting injection.
- Add reconcileClaudeCodeFableModelAfterPayload to reconcile model additions when payload rules override model or thinking.
- Reliably re-add reporting block if omitted after payload rules modify system blocks.
- Drop injected thinking.display on Fable models when payload changes thinking type from adaptive to disabled.
- Enhance payload rule path tracking with ancestor target matching in ApplyPayloadConfigWithTrackedPaths.
2026-09-04 15:23:31 +08:00
sususu
086ad91bd9 feat(claude): implement 2.1.258 billing header fingerprint chain and upstream request continuity
- Assemble x-anthropic-billing-header strictly following official 2.1.258 binary sequence: cc_version -> cc_entrypoint -> cch -> cc_workload -> cc_is_subagent -> cc_prev_req -> cc_prompt_id.
- Track upstream request-id in thread-safe bounded session continuity state and inject into subsequent turns as cc_prev_req.
- Generate and enforce RFC 4122 UUIDv4 cc_prompt_id per user prompt turn, preserving it across tool continuations while suppressing it on probes and title helpers.
- Detect subagents via agent headers and session metadata to emit cc_is_subagent=true.
- Harmonize diagnostics and continuity lifecycles to prevent uncommitted or truncated streams from corrupting state.
- Exclude x-anthropic-billing-header system blocks from sensitive-word zero-width space injection.
2026-09-04 15:23:31 +08:00
Luis Pater
291cfb87ef feat(codex): support orphan delegation compatibility via orphan-delegation-compatibility
- Add `codex.orphan-delegation-compatibility` configuration option and mirror it to SDK configuration.
- Convert orphan Codex delegation outputs into standard user messages for requests with `X-Openai-Subagent: collab_spawn`.
- Integrate orphan delegation rewriting into OpenAI responses request handling pipeline.

Closes: #5401
2026-09-03 20:21:24 +08:00
Luis Pater
63fdd77f80 Merge pull request #5436 from router-for-me/models
fix(models): apply Home-provided model capabilities during execution
2026-09-03 16:32:54 +08:00
hkfires
6ff680e90a feat(auth): use home model capabilities for thinking 2026-09-03 13:10:30 +08:00
sususu
df7e04ea28 fix(claude): upgrade default Claude Code baseline and fingerprint to 2.1.258
- Bump default Claude Code version baseline from 2.1.220 to 2.1.258 to resolve upstream 400 version gate error
- Update Stainless SDK package version to 0.112.1 and runtime version to v26.3.0
- Refresh default device profile, billing header build hashes, and cloaking signatures
- Decouple unconfirmed client OS/Arch test assertions from host runner platform
- Update config.example.yaml and test suites across executor and helps packages
2026-09-03 10:21:13 +08:00
Luis Pater
9721d9939e feat(usage): track streaming execution state in usage records
- Add `Stream` field to usage records, context helpers, and Redis queue payloads.
- Propagate streaming mode across execution handlers, conductors, and usage reporters.

Closes: #5361
2026-08-31 20:29:19 +08:00
hkfires
b908ed5d86 fix(store): close git repos during recovery
Close go-git repository handles across store operations and tests to avoid
leaked handles blocking recovery cleanup. Abort recovery before mutating the
worktree when close failures occur and retain backups when rollback fails.
2026-08-31 08:41:08 +08:00
Luis Pater
d31b15916d feat(executor): support token usage parsing for plugin executors
- Add `ParsePluginExecutorResponseUsage` to extract token usage from non-streaming plugin responses across Claude, Gemini, Interactions, Antigravity, and OpenAI/Codex protocols.
- Add `ObservePluginExecutorStreamUsage` to observe and aggregate token usage across streaming chunks.

Closes: #5340
2026-08-30 14:51:08 +08:00
hkfires
6a489fa84d fix(auth): prefer errors from upstream attempts
Track when executor calls cross an upstream transport boundary and use that
signal to keep model/provider errors from being replaced by later local
preparation, selection, or internal failures.

Mark HTTP, websocket, relay, and usage-tracked transports as upstream
attempts, while avoiding marks for local validation, logging, missing
sessions, and successful websocket handshakes before request send.

Parse relative auth expiry metadata and adjust Antigravity refresh timing.
2026-08-29 12:50:46 +08:00
hkfires
bc918ab276 fix(runtime): log safe home refresh error types 2026-08-29 12:50:45 +08:00
hkfires
e4a8f98913 fix(logging): enhance error diagnostics and logging for home refresh operations 2026-08-29 12:50:45 +08:00
hkfires
9a2201c36a fix(auth): forward Home unauthorized upstream errors
Stop refreshing Home-owned OAuth credentials after upstream 401s.
Preserve marked upstream response bodies for direct responses, usage
records, request logs, and websocket handshake failures.
2026-08-29 12:50:44 +08:00
sususu98
4b2beb3da1 feat(executor): measure effective TTFT with protocol-aware token classification (#5313)
* feat(executor): measure effective TTFT with protocol-aware token classification

- Introduce protocol-aware streaming token classification under internal/runtime/executor/helps
- Implement responses_ttft_helpers.go for OpenAI Responses / Codex WebSocket & SSE streaming
- Filter out container metadata, rate limits, handshake headers, and tool execution outputs
- Implement dual-track firstPacketDuration fallback for abnormal / zero-token stream terminations
- Add TrackHTTPClientRoundTripOnly to bypass false TTFT triggers on first response body reads
- Optimize UsageReporter.ObserveTokenEvent hot path with fast-path RLock short-circuiting (0 B/op)
- Align terminal event completions across SSE, WebSocket streaming, and non-streaming executions
- Add EnsurePublished metric recording fallback for successful terminal turns lacking usage blocks
- Add stub helpers with comprehensive specifications for Chat, Claude, and Gemini protocols

* fix(executor): normalize SSE response.done and terminate incomplete WS streams

* fix(usage): capture first-packet fallback on initial body reads with TrackHTTPClientRoundTripOnly
2026-08-29 01:22:21 +08:00
Luis Pater
95f83a8d96 fix(claude): treat allowed_warning as allowed in unified rate limit checks
- Treat `allowed_warning` status as allowed for shared 5h and 7d rate limit windows.
- Ensure Fable-only rejections with warning-level shared windows remain model-scoped instead of credential-scoped.

Closes: #5275
2026-08-27 17:32:07 +08:00
Luis Pater
4b5f1eab25 feat(plugin): support observing upstream websocket response events
- Introduce `WebSocketResponseObserver` capability and bump plugin ABI schema version to 4.
- Forward upstream WebSocket response frames from Codex and xAI executors to configured observers.
- Wire `WebSocketResponseObserver` across API handlers and plugin host dispatchers.

Closes: #5248
2026-08-27 05:30:19 +08:00
sususu98
ca601db05d feat: observe upstream provider quota signals (#5211)
Codex and Claude already emit credential-level quota watermarks on ordinary
responses. CPA used to drop them. Keep the latest watermark in memory and
return it from the management auth-file API.

Hard rule: this is observation only. It must not change scheduling, cooldown
selection, or auth-file persistence.

Snapshot, not accumulation
- QuotaState now has ObservedAt and a bounded Signals map. MarkResult fills
  them from the response headers already recorded on the request.
- Signals is the current response, not a union of earlier ones. Retry-After
  and "limit reached" only appear on the response that produced them; merging
  across responses would keep an expired value forever.
- A response with no quota header (transport failure, 5xx, unrelated endpoint)
  leaves the previous snapshot in place.
- ObservedAt is the time of the current snapshot. It advances even when the
  values did not change, so a consumer can tell a fresh reading from a stale
  one.
- When two model states merge, keep the newer snapshot. Do not union keys
  captured at different times.

What is observed, and what is not
- One predicate, ProviderSupportsQuotaObservation, decides the provider set.
- Keep Codex and Claude. Drop Kimi, xAI/Grok, Antigravity, and the Gemini
  family (gemini/vertex/aistudio): their ordinary headers are not a reliable
  credential-level remaining quota.
- Count-tokens reuses the credential but is not generation traffic.
  ExecuteCount sets SkipQuotaObservation so those headers cannot replace the
  last generation snapshot. Cooldown and success/failure accounting still run.

Cooldown must not overwrite the last snapshot
- Observation writes only ObservedAt and Signals.
- Cooldown writes only Exceeded, Reason, NextRecoverAt, and BackoffLevel,
  through applyCooldownFields. Never assign a fresh QuotaState{...} over a
  live value: that would zero the snapshot on 429, Cloudflare, credential-
  scope sibling updates, and cooldown clears.
- If a credential-quota cooldown is still active, MarkResult still observes
  an already-present model state. It does not create scheduler state just to
  record a watermark.
- .cds files persist cooldownFieldsOf(Quota) only. Restore keeps the newer
  ObservedAt, so reloading cooldown cannot clobber a newer in-memory snapshot.
- cooldownQuotaEqual still ignores observation fields, so a watermark change
  cannot by itself persist cooldown or move the scheduler.
- The management payload omits every cooldown field, so it cannot be mistaken
  for scheduler state or wired back into scheduling.
- Manual ResetQuota still clears the full QuotaState.

Codex websocket events
- Codex WS reports quota as codex.rate_limits frames, not HTTP headers.
  ParseCodexQuotaEventHeaders turns one event into the same bounded header
  shape, and MergeResponseHeaders folds it into the request-scoped holder.
  additional_rate_limits is accepted as an object (websocket) or an array
  (/wham/usage).
- Parse only through AppendCodexAPIWebsocketResponse. The shared
  AppendAPIWebsocketResponse is also used by xAI, and xAI error frames really
  do carry x-ratelimit-* headers. Parsing every frame as Codex quota would
  forge Codex headers into another provider's request log.
- Also capture code_review_rate_limits.
- A malformed active-limit name drops only that one header, not the window
  watermarks parsed from the same event.
- The type discriminator scans a bounded frame prefix, not every byte of
  every frame.
- HTTP namespaces an extra limit by short name (x-codex-bengalfox-*); WS
  namespaces it by limit name (GPT-5.3-Codex-Spark). The two paths cannot
  emit the same header names. The X-Codex-Additional- prefix marks the WS
  origin, and snapshot replacement keeps the two spellings from piling up.

Hardening
- Reject observed values with control characters. These strings reach the
  plain-text request log, and Limit-Name is upstream-controlled, so CR/LF
  could forge a header line.
- When the header cap is hit, keep plan/credits/primary ahead of
  additional-limit namespaces, then sort names so truncation is deterministic.
- QuotaState.Clone deep-copies Signals and is used by Auth.Clone and
  ModelState.Clone.
- Token stores still serialize credential metadata only, so observation adds
  no auth-file writes.
2026-08-24 17:15:37 +08:00
Luis Pater
42d8e746e5 fix(claude): avoid long global cooldowns for Fable-only 7d_oi rate limits
Closes: #5101
2026-08-21 02:02:46 +08:00
sususu98
85d2faddd1 fix(claude): preserve native subagent and environment headers (#4982) (#5084) 2026-08-20 00:30:41 +08:00
sususu98
8aa6868d0d fix(claude): support setup-tokens and gracefully handle 403 OAuth profile errors (#4983) (#5083) 2026-08-20 00:15:31 +08:00
sususu98
788e9b7928 fix(claude): restore tool_search_tool_result references and recognize advisor/agent server tools (#5044) (#5082)
- Add bidirectional remapping for nested tool_references inside tool_search_tool_result across non-stream, SSE stream, and multi-turn message history.
- Add advisor_ and agent_toolset_ to IsClaudeServerToolType to prevent schema stripping and MCP aliasing on native Anthropic server tools.
- Wrap MCP alias restoration errors in claudeMCPAliasRestoreError with IsRequestScoped() bool to avoid cooling down healthy OAuth credentials.
- Add unit tests for tool_search_tool_result remapping, error variants, server tool recognition, and error scoping.
2026-08-19 22:29:51 +08:00
sususu
0f69f09a70 fix(logging): exclude HTTP 499 and client cancellations from forced error logs 2026-08-19 18:58:47 +08:00
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
sususu98
f1b0431c77 feat(claude): add fingerprint-profile=claude-code-cli for API keys and delegated providers (#5047)
* feat(config): add fingerprint-profile to Claude keys and auth JSON

- Add FingerprintProfile to ClaudeKey configuration struct and normalizer
- Track fingerprint-profile in config diff
- Map fingerprint-profile / fingerprint_profile to auth attributes in file and config synthesizers
- Support fingerprint-profile in Management API PatchClaudeKey and normalization
- Add Claude billing attribution string manipulation utilities in internal/util
- Document fingerprint-profile options in config.example.yaml

* feat(claude): add fingerprint policy and request-local CLI identity

- Centralize Claude fingerprint policy resolution in claude_fingerprint_policy.go
- Support stable Claude CLI identity synthesis (UUIDv5 account_uuid and SHA-256 device_id)
  seeded from API keys or stable OAuth IDs, keeping access tokens isolated
- Warn on unrecognized fingerprint-profile values

* feat(claude): apply CLI fingerprint to Messages and keep API keys caller-owned

- Wire centralized fingerprint policy into Claude and Kimi executors
- Keep first-party Anthropic API keys and delegated providers caller-owned by default
- Apply Claude Code CLI wire profile (betas, metadata, diagnostics, MCP aliases)
  when fingerprint-profile=claude-code-cli is configured
- Strictly align CCH signing with native Claude Code 2.1.220: only first-party
  api.anthropic.com and Vertex sign dynamic CCH; third-party gateways and Kimi
  receive billing header without cch= to avoid prompt cache busting
- Respect caller-owned count_tokens bodies by default while aligning CLI shape on opt-in
- Fall back to CLIProxyAPI/<version> User-Agent when caller sends no UA in caller-owned mode
- Scope custom operator header overrides accurately in caller-owned mode
- Add comprehensive test coverage for policy resolution, gateway opt-in, Kimi, and token counting
2026-08-18 17:29:26 +08:00