Commit Graph

3472 Commits

Author SHA1 Message Date
Luis Pater
e424bfad00 feat(executor): support $-based custom headers from downstream request headers
- 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
2026-08-18 19:33:50 +08:00
sususu
f3e836ce6c refactor(claude): deduplicate CLI identity application and tidy helpers
- 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
2026-08-18 18:21:33 +08:00
sususu
aec70dfec4 fix(claude): gate CCH signing by upstream origin and validate fingerprint-profile
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
2026-08-18 18:06:40 +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
Luis Pater
f985a5cfe2 Merge pull request #5033 from DEAN-Cherry/fix/claude-fable-model-scoped-cooldown
fix(claude): keep Fable-only rate limits model scoped
2026-08-18 14:52:57 +08:00
Supra4E8C
ee2c494788 fix: update LMU registration links in README files 2026-08-18 14:30:15 +08:00
Supra4E8C
9826bd7da9 Merge pull request #5050 from router-for-me/sponsor/add-bestproxy
Sponsor/add bestproxy
2026-08-18 14:03:23 +08:00
Luis Pater
d388a4bef9 Merge pull request #5043 from DragonFSKY/fix/consumed-compaction-trigger
fix(websocket): drop consumed compaction triggers
2026-08-18 13:56:54 +08:00
Luis Pater
3230e37023 fix(claude): accept both max_tokens and max_completion_tokens in OpenAI→Claude request conversion
- 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
2026-08-18 13:46:27 +08:00
Luis Pater
20f84e78c1 fix(gemini): support mixed and structured function_call_output handling in OpenAI→Gemini responses translation
Closes: #5039
2026-08-18 13:37:37 +08:00
Supra4E8C
628f535aac docs(readme): link Bestproxy free trial 2026-08-18 12:50:37 +08:00
DragonFSKY
45c90e8d0e fix(websocket): drop consumed compaction triggers
After remote compaction succeeds, the normalized previous request still contains the consumed compaction_trigger. The next WebSocket-to-HTTP merge replays that trigger before the compaction output and current input, causing the upstream 400 error.

Remove compaction_trigger only from previous request items when the previous response contains compaction or compaction_summary. Add a two-step regression test covering trigger normalization followed by compact replay.

Fixes #5041
2026-08-18 04:33:00 +08:00
Supra4E8C
d3a5988fc0 docs: temporarily hide Qiniu Cloud and FennoAI sponsors 2026-08-18 04:05:59 +08:00
Supra4E8C
781544961d add bestproxy sponser 2026-08-18 03:26:35 +08:00
Bryan
a8f9814a69 fix(claude): keep Fable-only rate limits model scoped
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
2026-08-17 21:29:51 +08:00
Luis Pater
856ddd8df7 Merge pull request #5026 from router-for-me/cooling
Refactor cooling management across configuration and handlers
v7.2.135
2026-08-17 12:51:04 +08:00
Luis Pater
745fb38dbb chore(models): update GPT-5.6 context limits in registry metadata
- 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`.
2026-08-17 12:48:09 +08:00
hkfires
5bffd1514f Refactor cooling management across configuration and handlers
- 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.
2026-08-17 10:54:07 +08:00
Luis Pater
b8fbe70b37 fix(auth): stop old selectors when replacing manager selector and harden cache stop concurrency
- Add `isSameSelector` using type-aware comparable checks to avoid unnecessary selector replacement.
- Update `Manager.SetSelector` to:
  - serialize swaps with a dedicated selector mutex,
  - no-op when replacing with the same selector instance/type,
  - stop the previous selector when it implements `StoppableSelector`.
- Protect `SessionCache.Stop()` with `sync.Once` and nil-check to make repeated/concurrent stops safe and idempotent.

Closes: #5018
v7.2.134
2026-08-16 22:28:45 +08:00
Luis Pater
75e2454e72 docs(readme): remove obsolete ecosystem links for PPAP and Alex
- Remove the **Playful Proxy API Panel (PPAP)** and **Alex** entries from `README.md`, `README_CN.md`, and `README_JA.md`.
- Keep the remaining project list and note section unchanged.
2026-08-16 22:03:00 +08:00
Luis Pater
00c4377a21 fix(auth): share session affinity across model variant suffixes
- Canonicalize model IDs when building session-affinity cache/fallback keys so variant suffixes (for example thinking modes) map to the same binding.
- Normalize model values from result metadata/on-result release paths to release and rebind bindings consistently across canonical model keys.

Closes: #5016
2026-08-16 21:55:50 +08:00
Luis Pater
aa10847e12 feat(auth): add request-scoped error action handling in conductor
- 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
2026-08-16 21:39:38 +08:00
Luis Pater
361fe95799 Merge pull request #5008 from shengyy/fix/antigravity-schema-semantics
fix(antigravity): preserve response and tool schema semantics
2026-08-16 14:45:15 +08:00
shengyy
7d55d0da0d fix(antigravity): preserve schema semantics 2026-08-16 13:00:59 +08:00
shengyy
e23395a92b test(antigravity): cover schema sanitizer semantics 2026-08-16 13:00:50 +08:00
Luis Pater
7eefab98b8 feat(claude): map OpenAI service_tier to Claude speed in responses requests
- Translate `service_tier: "priority"` to `speed: "fast"` in `ConvertOpenAIResponsesRequestToClaude`.
- Leave `speed` unset for default/absent/standard/unsupported `service_tier` values.

Closes: #5003
2026-08-16 05:36:42 +08:00
Luis Pater
92f03e68e3 fix(claude,gemini,openai): preserve upstream stream errors when no data payload is emitted
- Return buffered pending stream errors from `errChan` when the data channel closes in streaming handlers.
- Emit error response instead of silently falling back to normal SSE completion paths.
- Replace Claude’s local `pendingClaudeStreamError` usage with shared `handlers.PendingStreamError`.

Closes: #4710
2026-08-16 04:29:51 +08:00
Luis Pater
7efe0a7c11 pref(claude): keep raw Claude tool IDs for deduplication in request translation
- 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.
v7.2.133
2026-08-16 03:06:44 +08:00
Luis Pater
8b3b304952 perf(translator): switch response translators to batched raw-array insertion via SetRawArrayItems 2026-08-16 01:53:27 +08:00
Luis Pater
0c58c3c83d perf(translator): batch assemble translation arrays before writing JSON
- 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).
2026-08-16 01:25:28 +08:00
Luis Pater
a581838082 fix(gemini): simplify OpenAI chat response content and choices serialization
- 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.
2026-08-16 00:23:47 +08:00
Luis Pater
124dab6cc1 perf(translator): batch assemble response arrays and merge multi-choice parts
- 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.
2026-08-15 23:15:50 +08:00
Luis Pater
616d1b11e5 fix(claude,gemini,antigravity): centralize tool-call ID generation and harden signature sanitization
- 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.
2026-08-15 21:21:02 +08:00
Luis Pater
1ecb7df228 fix(claude): deduplicate duplicate tool outputs in OpenAI-to-Claude request conversion
- 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
2026-08-15 19:34:03 +08:00
Luis Pater
c1ff55fc2f chore(models): remove GPT-5.6 Sol Work Mode registrations from model registry config 2026-08-15 19:13:39 +08:00
Luis Pater
10afcc8c77 fix(openai): propagate environment context and sanitize antigravity generation config in interaction adapters
- 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
2026-08-15 19:09:58 +08:00
Luis Pater
f53a2b6e80 fix(gemini): merge conditional schema branches during JSON schema cleanup
- 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
2026-08-15 17:24:48 +08:00
Chén Mù
48d021813b Merge pull request #4994 from router-for-me/models
feat(models): add max_completion_tokens to model definitions and responses
2026-08-15 16:39:30 +08:00
Luis Pater
9169ad56e1 fix(auth): make session-affinity updates safe for rebound sessions
- Propagate session-affinity provider/model metadata through selection and execution results so affinity cleanup uses the same namespace/model keys as selection.
- Forward execution `Options` in `Result` across normal, home, and stream paths, then hook manager cooldown handling to notify the affinity selector.
- Add `Touch`/`CompareAndDelete` to session cache and switch affinity release logic to compare-and-delete semantics, preventing stale failures from deleting a session already rebound to another auth.

Closes: #4989
2026-08-15 16:37:49 +08:00
hkfires
046b59ecc5 feat(models): add max_completion_tokens to model definitions and responses 2026-08-15 16:27:57 +08:00
Luis Pater
dd214445ef feat(models): add GPT-5.6 Sol Work Mode model registrations and Codex client config updates 2026-08-15 15:34:11 +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
Luis Pater
ac82bedfaf fix(claude): add Anthropic unified rate-limit parsing helpers
- Add new Claude rate-limit helper utilities to detect unified header-based quota rejections (5h/7d), handling case-insensitive headers and missing canonical forms.
- Compute deterministic retry duration from `Retry-After` and header reset timestamps, preferring the longest applicable unified window so cooldowns can be applied consistently.
- Introduce reusable rate-limit classification logic to distinguish header-authoritative rejections from request-scoped errors (e.g. fast-mode entitlement failures) for correct credential/model cooldown behavior.

Closes: #4874
2026-08-15 14:08:16 +08:00
mardausdennis
297139cc8d fix(claude): keep tool_result blocks first when injecting currentDate
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.
2026-08-15 11:45:49 +08:00
Luis Pater
203f5b1a1d fix(auth): avoid cooldown for request-scoped 401 request-faults
- Treat request-invalid/invalid-parameter 401 faults as request-scoped so auth/model cooldown is skipped.
- Export request-scoped/connection-lifecycle error codes and add helpers to explicitly create or mark request-scoped `Error`s.
- Improve request-fault detection by checking the raw message body when `Error.Code` formatting hides JSON payloads.

Closes: #4976
2026-08-15 05:46:10 +08:00
Luis Pater
810d4dddb3 Merge pull request #4360 from router-for-me/perf/skip-inactive-request-interceptors 2026-08-15 05:12:18 +08:00
Luis Pater
8b02fedec2 Merge pull request #4928 from ramapitecusment/codex/websocket-transcript-allocations-v2
perf(openai): reduce websocket transcript merge allocations
2026-08-15 04:58:38 +08:00
Luis Pater
61c4fd87f5 fix(gemini): preserve additionalProperties:false for Antigravity response schemas
- 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
2026-08-15 04:48:42 +08:00
Luis Pater
78f0c4079e fix(openai): mark truncated/filtered responses as incomplete and avoid finalizing partial tool calls
- 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
v7.2.132
2026-08-15 04:28:55 +08:00
Luis Pater
98c98d66be fix(codex): cache multi-agent spawn-agent model data and invalidate on updates
- 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
2026-08-15 03:49:56 +08:00