Commit Graph

250 Commits

Author SHA1 Message Date
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
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
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
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
db35b91e2a feat(openai): add xAI Grok Imagine Image 2.0 image model support
- 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.
2026-08-13 14:37:29 +08:00
Luis Pater
75d2c4a4b4 fix(openai): avoid JSON copies in websocket responses tool-call repair path
Closes: #4925
2026-08-12 20:32:10 +08:00
Ramapitecus
baa11ed6dd fix(openai): match websocket item metadata case-insensitively 2026-08-12 16:52:16 +05:00
Ramapitecus
49b2f891ac fix(openai): preserve duplicate websocket input semantics 2026-08-12 16:43:56 +05:00
Ramapitecus
f8bcd1cc5f test(openai): harden websocket transcript allocation coverage 2026-08-12 16:23:35 +05:00
Ramapitecus
e7c3fb1983 test: make race detector suite deterministic 2026-08-12 16:17:14 +05:00
Ramapitecus
f9bd9def2b perf(openai): reduce websocket transcript merge allocations 2026-08-12 16:09:14 +05:00
Luis Pater
c845ce15c9 fix(openai): refactor websocket responses request merge/repair path
- Consolidate Responses websocket transcript merging by introducing typed input-item parsing for previous request input, previous response output, and appended input, replacing ad-hoc raw JSON-array string merges.
- Keep deduplication behavior in a single shared pipeline with metadata parsed once (type/id/call_id), then dedupe function-calls and item IDs before reserializing.
- Refactor fallback-turn tool-call repair into a unified prepare path that returns repaired payload + turn context, and only commits request state after successful forwarding to avoid stale per-turn history.

Closes: #4913
2026-08-12 17:06:27 +08:00
Luis Pater
522b4de54a fix(openai): handle premature SSE stream termination with terminal error emission
- Propagate pending terminal errors when image/response data streams close, emitting `error`/`failed` SSE events (or HTTP error responses when no stream started) instead of dropping them.
- Sanitize and normalize streamed terminal errors before writing, and reuse normalized errors for cancellation.
- Improve SSE parsing/frame handling for multiline and cross-chunk payloads, prioritize payload/event-level failures, and avoid mutating emitted frame buffers by cloning chunks before queueing.

Closes: #4904
2026-08-12 13:05:06 +08:00
Luis Pater
ba5ab795a2 feat(plugin): add schema-v3 stream chunk contract to omit payload request bodies
- Bump plugin schema to version 3 and introduce `SchemaVersionStreamChunkOmitRequestBody`.
- Treat missing plugin schema versions as legacy during RPC registration (`0 -> 1`) and expose schema on plugin descriptors.
- In stream interception, keep request headers/bodies on header-init chunk and stop re-sending them on payload chunks for schema-v3+ plugins, with per-chunk cloning for legacy plugins.

Closes: #4876
2026-08-11 04:32:20 +08:00
Luis Pater
3522e481aa fix(openai): emit response.failed stream errors for Codex requests
Closes: #4854
2026-08-09 03:47:14 +08:00
Luis Pater
9829bd9d3e fix(cliproxy): stop non-streaming keep-alive after OpenAI handler execution
Closes: #4782
2026-08-08 06:32:09 +08:00
Luis Pater
4b3cc55cdc fix(cliproxy): centralize client error status mapping and apply context cancellation/deadline HTTP codes
Closes: #4601
2026-08-08 04:53:34 +08:00
sususu
b148af80bd fix(api): escape the model name in the unroutable model error
Build the error body with sjson instead of formatting the requested model name into a JSON literal. The name is client supplied and is echoed back verbatim, so a quote in it produced a malformed body and a crafted name could append fields that overwrote the error code clients branch on, for example turning model_not_found into insufficient_quota.

Reported by the Codex reviewer on #4820.
2026-08-06 20:49:23 +08:00
sususu
579f5e30fb fix(auth): rotate credentials for unknown upstream failures
Stop treating an upstream 500 carrying "status":"UNKNOWN" as a request fault. It is an internal upstream failure, so the request now falls through to the next credential instead of failing immediately, and the resulting cooldown lands on the failing credential and model pair only, leaving sibling models on that credential selectable.

Move the store=false item-miss detection into the shared client-error package. The upstream sends that 404 as plain text rather than a JSON error body, so the structured identifiers could never match it and only the conductor recognized it. The proxy now reports it to the client, which is the only party able to rebuild the request without the stale item reference; a reconnect resends the full input and the conversation continues unchanged.
2026-08-06 20:49:23 +08:00
sususu
c1d69e7b47 fix(auth): avoid penalizing credentials for client faults 2026-08-06 20:49:23 +08:00
sususu
fe28d582f4 fix(openai): expose only client-fault streaming errors
Forward an upstream failure to Responses websocket and SSE clients only when the request itself is at fault. Credential, quota and transport failures now close the stream silently so the client reconnects and retries; a fresh websocket carries no server-side transcript, so reconnecting already implies a full context resend and needs no extra close-code signal.

Classify the failure from the upstream error body instead of the attached status. Codex reports the same cyber_policy rejection as 400 on the stream error path and as 502 through the websocket disconnect channel, so a status-only whitelist hid most of them. Treat cyber_policy as a request error so it stops credential failover without suspending the credential, and treat 413 as request-scoped because a payload that exceeds the upstream frame limit fails identically on every credential and would otherwise burn the whole pool.

Report an unroutable model as 400 invalid_request_error instead of 502 so streaming clients receive an actionable message instead of retrying forever. Keep the upstream reason in the request-log websocket timeline when the client only observes a closed connection, and stop logging expected connection-teardown races as warnings.
2026-08-06 20:49:23 +08:00
Luis Pater
32f1069a18 Merge pull request #4668 from oscarbrey/fix/grok-imagine-video-1.5-ga
fix(xai): support Grok Imagine Video 1.5 GA
2026-08-04 23:12:15 +08:00
Luis Pater
f27be0006d Merge pull request #4771 from FlameMida/fix/prepared-route-skip-recursion
fix: 嵌套流式执行遵守路由插件跳过标记
2026-08-04 23:05:42 +08:00
Luis Pater
9b8d97441e fix(responses): preserve original request model on response.created/response.in_progress payloads 2026-08-04 18:37:01 +08:00
flame
7ea5e3ae66 fix: honor router skips for prepared stream routes 2026-08-04 03:42:00 +08:00
Luis Pater
7fe8473766 feat(codex): prepare multi-agent v2 tool definitions at the Responses boundary for Codex clients 2026-08-03 22:22:15 +08:00
oscarbrey
84232747e2 fix(xai): register video preview alias 2026-07-29 23:28:53 +02:00
oscarbrey
61d9a30d12 fix(xai): preserve preview alias auth routing 2026-07-29 23:19:16 +02:00
oscarbrey
abaeb55bb2 fix(xai): support Grok Imagine Video 1.5 GA 2026-07-29 23:06:30 +02:00
Luis Pater
c9417c8ae9 feat(logging): add client request metadata extraction and propagation
- Added `ClientRequestMetadata` struct to capture client IP, `X-Forwarded-For` headers, and user agent.
- Implemented metadata extraction in HTTP handlers and propagation through context.
- Updated Redis queue plugin to include client request metadata in payloads.
- Added tests to validate metadata extraction and inclusion in request contexts.
2026-07-28 16:34:15 +08:00
Luis Pater
5dcca50fd9 feat(auth): introduce weighted round-robin scheduler and credential weight validation
- Added support for weighted round-robin authentication scheduling strategy.
- Implemented credential weight validation for attributes and metadata, with strict error handling for invalid weights.
- Enhanced scheduler with smooth weighted state handling and proportional selection logic.
- Introduced tests for credential weight parsing, validation, and weighted round-robin behavior.
- Updated configuration to include `weight` field for credentials with range validation.

Closes: #4470
2026-07-28 14:23:23 +08:00
Luis Pater
30efd7c4fd feat(plugin): add request lifecycle plugin with interception and termination capabilities
- Implemented a Go-based dynamic library plugin for request lifecycle management.
- Added concurrency controls, keyword-based request termination, and response handling.
- Supported optional capabilities for request interception and active lifecycle termination.
- Included tests for schema compatibility, concurrency limits, and policy-based termination.
- Added build instructions and configuration details in README.
- Updated host support for lifecycle plugin RPC methods.

Closes: #4568
2026-07-28 03:22:18 +08:00
Luis Pater
6914478562 feat(config): add support for disabling model list cloaking in Claude Code
- Introduced `DisableCloakingModelList` in `ClaudeCodeConfig` to control model ID cloaking in Anthropic model list responses.
- Updated relevant APIs and handlers to respect the new configuration.
- Added comprehensive tests for enabling/disabling cloaking behavior and config-driven hot reload scenarios.
- Extended example configuration and documentation to include the new setting.

Closes: #4473
2026-07-27 18:16:41 +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
Luis Pater
f6c32ec3ff feat(runtime): implement derived session identity features and tests
- Added utilities for generating stable session identities, including `DerivedSessionID`, `DerivedSessionUUID`, and `ProviderSessionUUID`.
- Introduced support for Antigravity's negative decimal `DerivedAntigravitySessionID` mapping.
- Enhanced metadata handling for provider-scoped UUID stabilization and consistent session identity inference.
- Added comprehensive tests for stability, namespace isolation, and preferred execution session prioritization.
2026-07-26 03:07:21 +08:00
Luis Pater
0296600be6 feat(models): add Claude client model catalog and response builder
- Introduced a new `models` package for organizing Claude client model templates and building responses.
- Migrated Claude response handling to `claudemodels.BuildResponse`.
- Added comprehensive tests for model ID transformation, sorting, and metadata validation.
- Removed redundant utility functions and simplified integration with the API server.
2026-07-25 01:41:07 +08:00
Luis Pater
71d591296b feat(models): add Codex client model catalog and response builder
- Introduced a new `models` package for organizing Codex client model templates and building responses.
- Migrated Codex response handling to `codexmodels.BuildResponse`.
- Added comprehensive tests for model metadata, reasoning levels, and input modalities handling.
2026-07-25 01:24:22 +08:00
Luis Pater
84bf9376e5 feat(executor): replace sdktranslator.TranslateRequest with helps.TranslateRequestWithCodexMultiAgentV2
- Updated Kimi and Gemini executors to use `TranslateRequestWithCodexMultiAgentV2` for improved multi-agent v2 optimization.
- Enhanced configuration and API server to support `CodexOptimizeMultiAgentV2`.
- Added codex multi-agent V2 optimizations in `config`, `executor`, and `watcher` modules.
2026-07-25 00:32:37 +08:00
Luis Pater
e5729872fa Merge pull request #4522 from sususu98/fix/responses-ws-continuity 2026-07-23 14:31:41 +08:00
Luis Pater
3ecd4afe80 feat: add Home credential concurrency support 2026-07-23 13:42:08 +08:00
sususu
a661172b1f fix(responses): commit websocket tool cache atomically 2026-07-23 13:07:57 +08:00
sususu
e05ae09425 fix(responses): preserve context across websocket transport changes 2026-07-23 13:07:23 +08:00
Luis Pater
a007ad69f2 test(websocket): add robust unit tests for tool call handling and reconciliation
- Implemented tests for scenarios involving incomplete, conflicting, and reconciled tool calls in response payloads.
- Enhanced coverage for `restoreResponsesWebsocketCompletionOutput` and `responseCompletedOutputFromPayload` logic.
- Refactored `isCompleteResponsesWebsocketToolCall` to validate string fields in tool calls.
- Improved caching behavior to skip incomplete tool calls and ensure reconciliation logic aligns with expected outputs.

Closes: #4447
2026-07-20 16:47:22 +08:00
sususu98
7329437297 fix(websocket): propagate upstream 1009 without credential fallback (#4444)
Preserve Codex and XAI upstream message-too-big closes across the Responses WebSocket boundary while treating them as request-scoped errors. Prevent CPA reconnect and credential cooldown/fallback, scope close state to the active connection, retain terminal errors under backpressure, and ensure downstream disconnect cleanup cannot wait behind a blocked writer.
2026-07-20 16:18:13 +08:00
Luis Pater
fbe116071a feat(websockets): implement active connection tracking for websocket sessions
- Introduced per-connection active channel management for Codex and XAI websocket sessions.
- Enhanced session behavior to support clearing and reassigning active channels tied to specific connections.
- Added support for detecting and detaching stale connections upon session target changes.
- Refactored websocket message handling logic to ensure connection-specific channel consistency.
- Extended test coverage for websocket session behaviors, including reconnections, target switching, and pinned auth transitions.
2026-07-18 00:40:56 +08:00
Luis Pater
366271969a feat(logging): add CPA trace ID middleware and enhance metadata handling
- Introduced CPA trace ID middleware to inject trace IDs in response headers.
- Added support for CPA trace ID generation and validation.
- Updated metadata handling to include stable auth indices and trace ID callbacks for enhanced request tracking.
- Enhanced tests to verify CPA trace ID propagation and reserved header handling across middleware, metadata, and handlers.

Closes: #4370
2026-07-17 22:58:28 +08:00
Shawn G
970529b6ee perf(api): skip inactive request interceptors
Why:
- The plugin host can exist without active request interceptors.
- The before-auth path still cloned large request bodies four times in that case.

What:
- Reuse the existing request interceptor capability detector before dispatch.
- Add pointer-reuse regression coverage and allocation benchmarks.

Validation:
- go test ./... -count=1
- go build -o /tmp/test-output ./cmd/server
- focused race test passed; the full handler race run still hits an existing stream-header race reproduced on origin/dev
2026-07-16 15:04:41 +08:00
Luis Pater
768b4c49fd feat(usage): track generate flag with backward-compatible defaults
Propagate client generate metadata through usage records while keeping
legacy callers that omit the field enabled by default. Preserve an
existing context generate=false when metadata does not set the value,
and normalize omission to true only at publishing boundaries.
2026-07-15 21:30:09 +08:00
sususu98
03d58c4402 fix(usage): collapse OpenAI service tier metadata (#4275)
* fix(usage): preserve request service tier metadata

* fix(usage): collapse request tier metadata

* fix(usage): emit only service_tier and response_service_tier

Collapse request tier to service_tier for usage records and queue payloads. Keep RequestServiceTier as a deprecated input-only alias for older plugin callers.
2026-07-14 14:19:13 +08:00