Preserve Windows Pi dispatch arguments, serialize raw trace adoption, recover
unexpected core exits without overriding manual stop/start, and avoid unused
token estimation and repeated route script body copies. Preserve custom token
counts and select the configured protocol for bare runtime provider IDs.
Remove all gateway dependency patches and build directly from upstream commit
0a2c0abd48d2144ed0ac2ce4d954a661c51ffcb1. Include reproducing regressions and
update desktop/Docker release packaging and development records.
Validation: CCR targeted regressions 270 passed, 2 Windows skips; upstream
full suite 931 passed, 7 skips; bundled HTTP/SSE/SQLite/process tests 4 passed.
Type checks and both production builds passed.
The Codex backend routes prompt caching by the session_id request header;
prompt_cache_key in the body alone does not hit the cache. Codex upstreams
were skipped entirely, so Claude Code sessions routed to Codex got almost
no cache reads. Add the session_id header (unless already present) and
prompt_cache_key (unless caller-supplied) for Codex, still without metadata.
Fall back to the session id embedded in metadata.user_id and drop values
unsafe for HTTP headers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0199MDCTCCgDMRPaiKkrXEGA
raw-trace updates rewrote request_logs.response_headers with the upstream
header set (or "{}" when the set was empty), wiping the gateway-inserted
x-ccr-fallback-attempts header that powers the R{n} retry badge on the log
page. Since updateFromRawTrace only refines rows the gateway already
inserted, keep the incoming headers for usage/billing extraction below but
stop persisting them to the response_headers column.
Adds a regression test asserting x-ccr-fallback-attempts survives raw-trace
updates carrying both a non-empty header set and an empty {} set.
Fixes#1864
A bare model id registered under multiple providers with disjoint
protocol capabilities resolved to undefined, so hop 1 failed locally
and the request silently fell through to the global fallback chain on
a different model. ModelRegistry.resolve() now accepts the request
protocol and uses it to break ties between bare-id matches;
genuinely ambiguous ids (no protocol given, same protocol declared
on both providers, or providers without capability metadata) keep
the previous undefined behavior instead of guessing.
Fixes#1860.
Readable.fromWeb(upstream.body).pipe(transform) leaves the source with no
'error' listener, so an upstream ECONNRESET mid-stream ("TypeError:
terminated") became an unhandled 'error' event and killed the core gateway
process. Use stream.pipeline() in the live token rate transform and the
Codex apply-patch / multi-agent bridges so the error destroys the whole
chain and reaches the response consumer.
The main-process proxy already listens for errors on every stage, but
.pipe() never ended the client response, so the client hung until its own
timeout. Destroy the response once the stream error is logged.
Fixes#1846
Base URL normalization stripped any trailing /models, so a custom
provider URL like https://host/platform/models became
https://host/platform. Only treat /models as the model-list endpoint
when it sits at the root or directly under an API version segment.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds Serply to the hosted web search providers and the built-in Fusion
web_search MCP tool, alongside Brave, Bing, Google CSE, Serper, SerpAPI,
Tavily and Exa. Configured with SERPLY_API_KEY and an optional
SERPLY_SEARCH_ENDPOINT override, like the other providers.