- Propagate request headers into custom-header resolution for OpenAI/Gemini/XAI/Codex execution and websocket flows.
- Resolve auth `header:` values like `$ABC` from incoming request headers at request time and omit headers when no value is available.
- Add documentation for the dynamic custom-header behavior in `config.example.yaml`.
Closes: #5053
- Extract the credential-identity block shared by the streaming and
non-streaming Claude paths into applyClaudeCLIIdentity, so the identity
seed choice (API key versus stable Kimi auth identity) cannot drift
between the two paths
- Move stripDefaultKimiClaudeCodeAttribution next to the other attribution
and CCH helpers in claude_signing.go; it is only called from the Claude
executor paths and never from the Kimi executor itself
- Reattach the addConfigHeadersToAttrs doc comment to its function in the
watcher synthesizer helpers
Claude Code 2.1.220 through 2.1.234 emit the cch attribution only for
firstParty on api.anthropic.com and for vertex; every other backend sends
the billing header unsigned. CPA had dropped its endpoint check, so an
opted-in API key signed a per-request hash on any gateway and could bust
that gateway's prompt cache.
- Restore the endpoint gate in claudeCCHSigningEnabled: a real Claude OAuth
credential still signs on every upstream, because a downstream Claude Code
pointed at CPA cannot produce that value itself, while a claude-code-cli
API key signs only on api.anthropic.com or Vertex
- Drop the unused origin parameter from Claude fingerprint policy resolution
and restore the original resolveClaudeWirePolicy signature; the wire profile
follows the credential and only CCH follows the origin
- Add config.NormalizeClaudeFingerprintProfile / ValidateClaudeFingerprintProfile
as the single source of truth for fingerprint-profile values
- Reject unknown fingerprint-profile values in the Management API, and warn
once per distinct value at request time instead of on every resolution,
which previously logged about four warnings per request for one typo
- Preserve unrecognized values through config sanitization so rewriting a
config file never discards operator input
- Update config.example.yaml and tests for the origin-scoped CCH behavior
* 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
- Prefer `max_tokens` when both `max_tokens` and `max_completion_tokens` are present, otherwise use whichever exists.
- Default to existing template `max_tokens` limit when neither field is provided.
- Add regression coverage for all token-limit source/preference paths.
Closes: #5040
- Raise GPT 5.6 Sol/Terra/Luna `context_length` values to `921000` in `internal/registry/models/models.json`.
- Update matching Codex client model settings to `context_window: 272000` and `max_context_window: 921000` in `internal/registry/models/codex_client_models.json`.
- Changed `DisableCooling` from a boolean to a pointer in various config types to allow explicit inheritance.
- Updated tests to reflect the new pointer usage for `DisableCooling`.
- Enhanced the `BuildConfigChangeDetails` function to handle optional boolean changes for `DisableCooling`.
- Added new tests to ensure proper handling of cooling overrides in configurations.
- Refactored the `SetQuotaCooldownDisabled` function and related logic to clarify the purpose of cooldown management.
- Introduced new tests for cooling override precedence in the auth manager.
- Ensured that all relevant handlers and synthesizers correctly manage the `DisableCooling` setting.
- Add request-scoped error rule extraction from auth metadata or runtime provider config (including OpenAI compatibility fallback)
- Match rules by HTTP/status-code plus error body substring or regex patterns
- Support `stop`, `stop-and-cooldown`, `continue`, `continue-and-cooldown` actions with normalized validation
- Apply matched actions to execution results via request-scoped vs force-cooldown error codes and stop/continue flow control
- Introduce request-stop error wrappers/helpers for matching and unwrapping scoped stop state
Closes: #5006
- Use original `call_id` / `tool_call_id` values as keys for tool-result/message caches and emitted-id tracking in Claude OpenAI request translators.
- Avoid mixed sanitized-vs-raw ID lookups that could cause duplicate or missed deduplication of repeated tool outputs.
- Refactor Gemini/OpenAI/Codex/Claude/Antigravity interaction and response translators to collect `parts`, `content`, `steps`, `tool_calls`, and `output` items in slices, then set each array once via `translatorcommon` helpers.
- Replace repeated incremental `sjson.SetRawBytes(..., ".-1", ...)` mutations with single-shot raw-array updates to avoid repeated rewrites.
- Keep existing step/content semantics while reducing ordering/overwrite risks when merging multi-fragment data (including thought/signature and web-search/function-call blocks).
- Emit plain text directly for Gemini→OpenAI chat responses when the message contains only one text part and no reasoning/tool/image content.
- Replace `choices` assignment via `JoinRawArray` with `translatorcommon.SetRawArrayItems` for direct raw-array insertion.
- Refactor multiple OpenAI/Gemini/Codex/Claude/Antigravity/Interactions response translators to collect output elements in slices and set arrays once via `translatorcommon.JoinRawArray`.
- Fix non-stream OpenAI→Gemini part handling so fields (`reasoning`, `content`, `functionCall`) from multiple choices overlay correctly on shared parts instead of being overwritten.
- Preserve explicit empty message fields in Gemini→OpenAI chat-completion conversion (`content`/`reasoning_content`) and add tests covering empty-text and cross-choice overlay cases.
- Add shared `GenerateClaudeToolCallID` in `common` and replace duplicated local `toolu_` generators across Claude request translators for consistent, uniform ID generation.
- Replace `bufio.Scanner`-based SSE line handling with manual newline parsing and use `JoinRawArray` for array assembly to avoid scanner buffer limits and extra wrapping allocations.
- Improve carrier/thought signature scrubbing to safely strip internal metadata only when present and detect spoofed/duplicate `thoughtSignature` keys (including raw/unicode-escaped forms) during sanitized JSON traversal.
- Precompute the last tool message/output per `tool_call_id` in chat-completions and responses requests, then emit only one `tool_result` per call ID at its first position.
- Use the final payload for each duplicate tool call/output and preserve attachment of cache-control metadata from the final tool item.
Closes: #4997
- Normalize conversation-context fields across OpenAI↔Interactions request/response translation by mapping both `previous_response_id`/`previous_interaction_id` and resolving `environment_id` (including nested `environment.id`) in both directions.
- Forward `agent_config` through translation and, for antigravity models, route output-token limits to `agent_config.max_total_tokens` while removing antigravity-incompatible `generation_config` knobs from emitted requests.
- Preserve `environment_id` through stream state so chat-completions and responses (stream/non-stream) outputs consistently carry it in final payloads.
Closes: #4995
- Add a cleanup pass to hoist `then`/`else` properties into the containing schema path (including nested and `allOf` cases).
- Remove `if`/`then`/`else` from the unsupported keyword list so sanitized schemas no longer retain conditional keywords.
Closes: #4984
- 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
injectClaudeCodeCurrentDate inserted the reminder at index 0 of the first user message. Anthropic requires the message after an assistant tool_use turn to lead with its tool_result blocks, so the request was rejected with 400. Advance the insert index past leading tool_result blocks, matching the existing guard in prependClaudeSystemRemindersToFirstUserMessage. Every other content shape keeps the current index-0 placement.
- Add a sanitizer option to keep `additionalProperties: false` in response paths instead of converting it to description hints.
- Skip dropping `additionalProperties: false` in `removeUnsupportedKeywords` when response mode is enabled, while still removing non-false `additionalProperties`.
- Keep tool-schema behavior unchanged by continuing to remove `additionalProperties` and emit compatibility hints for non-response conversions.
Closes: #4961
- Update OpenAI Responses conversion to map finish reasons (`length`/`max_tokens`/`content_filter`) to `response.incomplete` with proper `incomplete_details`.
- Propagate `incomplete` status to response, message, and function/custom tool items in both streaming and non-stream paths.
- Prevent premature completion of tool-call items when a stream ends without a terminal finish reason or with incomplete/partial tool arguments.
Closes: #4873
- Add registry generation tracking and a Codex catalog revision accessor to provide stable cache keys.
- Cache parsed model templates and rendered spawn-agent markdown, and reuse them across requests when revision/generation are unchanged.
- Invalidate/recompute caches when model registrations or catalog content change, and separate rewrite handling for spawn tool descriptions vs. message encryption stripping.
Closes: #4967
- Remove `prompt_cache_breakpoint` from `input[].content[]` items during OpenAI Responses → Codex request conversion to avoid unsupported-field rejection.
- Keep message contents and existing `system`→`developer` role conversion behavior unchanged while applying the cleanup.
Closes: #4951
- Added metadata merge helpers in `sdk/cliproxy/auth` to retain existing auth-file settings while excluding token lifecycle fields.
- Applied merge before saving in management handler and `sdk/auth.Manager.Login` so re-login overwrites credentials without discarding user-configured fields.
- Updated token save paths for Claude, Codex, Kimi, XAI, and Vertex to persist merged metadata payloads when writing auth files.
Closes: #4945
- Replaced random tool-call ID generation with deterministic `call_<sha256>` IDs for stable, repeatable Gemini→OpenAI conversion.
- Switched response matching from global ordering to per-function-name queues, so same-name and interleaved tool calls are paired correctly, while honoring explicit IDs (`id`/`call_id`/`callId`) when provided.
- Added deterministic fallback IDs for orphan tool responses when no matching pending call exists.
Closes: #4939
The word-based virtual server spans only ~2048^2 names, and plausible
real MCP server names such as file_system or web_search are valid BIP-39
word pairs. When a caller's own server matched the derived one, its tools
stopped passing through and entered alias recovery instead: they were
silently restored to an unrelated proxied tool, or failed the request
with a 500 when no semantic suffix matched.
Record untouched caller MCP tool names as identity entries in the reverse
map, skip those entries when collecting virtual servers and recovery
candidates, and forward them unchanged on an exact hit. Recording is
skipped when nothing was aliased, so an untouched request still keeps an
empty reverse map and a no-op restore path.
Also warn instead of silently forwarding an original name when the alias
space is exhausted, report an empty embedded wordlist, trace the
semantic-suffix fallback because it guesses rather than fails, and build
both alias entry points through one shared constructor so the exhaustion
tests cannot drift away from the production path.
Refs #4916
Replace high-entropy Base32 alias IDs with request-local BIP-39 English
words so weaker models are less likely to drift tool names. Keep a
two-word virtual server plus one-word tool ID, linearly probe wordlist
space on collision without self-overlap, and fall through to unambiguous
longest semantic-suffix recovery after a successful but wrong parse.
Fixes#4916
- Add `defer reporter.EnsurePublished(ctx)` to Gemini, Gemini Vertex, and AI Studio streaming goroutines so stream reporting is always finalized on exit.
- Update Gemini usage parsing to reject all-zero `usageMetadata` frames, preventing placeholder usage events from being accepted.
Closes: #4964
- Normalize repeated `mcp__<server>__` alias prefixes during reverse remapping to resolve stacked aliases.
- Add a semantic-suffix fallback when parsing fails, allowing unambiguous recovery from malformed tool IDs.
Closes: #4916
- Added `gemini-3.7-flash-high` to `internal/registry/models/models.json` with completion/context limits, multimodal input/output metadata, and supported thinking levels.
- Added `supportedInputModalities` and `supportedOutputModalities` across model entries in `internal/registry/models/models.json`.
- Filled capability metadata for text/image/audio/video-aware models (mainly Claude/Gemini-family and related provider routes), including Gemini image variants and image-generation models.
- Standardized modality descriptors for multimodal compatibility checks in model routing/validation without changing existing token or generation settings.
- Added `grok-imagine-image-2.0` as a first-class xAI image base model across validation, canonicalization, and routing checks.
- Registered the model in built-in model definitions so it appears in model metadata.
- Updated image model allowlists and request validation error messaging to include the new model.
- Marked the new model as hidden in client visibility override handling.