Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
390 commits
Select commit Hold shift + click to select a range
fdbc610
feat(auth): enhance plugin auth handling with multi-auth support and …
luispater Oct 12, 2026
a27799e
Merge pull request #6548 from gracjankubicki/fix/tool-search-golden-date
luispater Oct 12, 2026
519d590
feat(streaming): support send-keepalive-before-ft option
luispater Oct 12, 2026
67870b6
docs: add sub2api to "Who is with us?"
devbymak Oct 12, 2026
bf93416
Merge pull request #6557 from devbymak/docs/add-sub2api
luispater Oct 12, 2026
fb87727
Merge pull request #6543 from RoySRose/pr/claude-oauth-wrapped-full-m…
luispater Oct 12, 2026
333f62b
docs(readme): note Meta Muse Wonder availability
kdcokenny Oct 12, 2026
50bfc50
docs(readme): list Muse Wonder models first
kdcokenny Oct 12, 2026
4c15906
feat(registry): add muse-wonder-1.0 models
luispater Oct 12, 2026
4f9630d
feat(registry): add web_search native capability
luispater Oct 12, 2026
97ba1e8
fix(claude): keep prompt cache when tool_search discovers the first d…
gracjankubicki Oct 12, 2026
1fbb06d
Merge pull request #6560 from gracjankubicki/fix/tool-search-deferred…
luispater Oct 12, 2026
e235fb3
fix(server): prevent data races during concurrent config access and r…
luispater Oct 12, 2026
a0fd844
fix(schema): preserve multi-branch anyOf/oneOf unions during schema s…
luispater Oct 13, 2026
77fd91e
feat(gemini): support client-executed tool_search in OpenAI Responses…
luispater Oct 13, 2026
f62d4d2
feat(registry): add claude-haiku-5-5 and remove legacy gemini models
luispater Oct 13, 2026
51952a7
feat(httptransport): add request-scoped HTTP transport decorator
luispater Oct 13, 2026
39ace7e
docs(readme): note Gemini 4 Argon availability
kdcokenny Oct 13, 2026
c96d9c9
docs(readme): keep Gemini model list consistent
kdcokenny Oct 13, 2026
f88b6b2
Merge pull request #6327 from kdcokenny/docs/antigravity-claude-55-av…
sususu98 Oct 13, 2026
866d84d
feat(registry): add gemini-4-argon-high model
sususu98 Oct 13, 2026
7795de1
feat(sse): implement CodexSSEScanner for improved event data handling
luispater Oct 13, 2026
6143cc1
feat(registry): add gemini-4-argon model
luispater Oct 13, 2026
40ce0e0
feat(kimi): support schema normalization for namespaced tools and inp…
luispater Oct 13, 2026
57d005f
fix(codex): strip out-of-range int64 numeric bounds from tool schemas
luispater Oct 13, 2026
56eee6a
fix(cliproxy): treat HTTP/2 closed connection errors as transient lif…
luispater Oct 13, 2026
e230a04
fix(server): prevent data races during concurrent config access and r…
luispater Oct 13, 2026
b0db544
feat(translator): use unique prefixes for fallback item IDs in OpenAI…
luispater Oct 13, 2026
81573f0
fix(server): prevent data races during concurrent config access and r…
luispater Oct 13, 2026
0d18d3b
feat(claude): support model-specific default max tokens from registry…
luispater Oct 14, 2026
a19a8ec
feat(registry): add gemini-3.8 model variants and update test cases
luispater Oct 14, 2026
5825700
feat(claude): ensure unique tool use IDs across turns in Gemini respo…
luispater Oct 14, 2026
7f2f17d
feat(gemini): treat MALFORMED_FUNCTION_CALL as retryable API error in…
luispater Oct 14, 2026
912a038
fix(antigravity): correct token usage calculations for cached tokens …
luispater Oct 14, 2026
f9ac397
feat(registry): add muse-wonder-full-1.0 model variants and update co…
luispater Oct 14, 2026
8fb633c
fix(antigravity): raise fallback client version to 2.23.0
sususu98 Oct 14, 2026
50eaed0
feat(pluginapi): expose config field defaults
Rat0323 Oct 12, 2026
345cc9d
feat(claude): add timeout and retry logic for silent TLS handshakes
luispater Oct 14, 2026
b3dc6c3
refactor(config): move tls-handshake-timeout-seconds to root request …
luispater Oct 14, 2026
5efe975
feat(antigravity): flatten multi-branch tool unions for Claude model …
luispater Oct 14, 2026
08e5762
fix(cliproxy): add model registration fencings and epoch-checked publ…
luispater Oct 14, 2026
5fc580b
feat(watcher): add file removal tracking and single-file auth snapsho…
luispater Oct 14, 2026
9db0729
feat(config): add operator overrides for Claude header defaults and c…
luispater Oct 14, 2026
4e8a412
feat(config): add operator overrides for Claude header defaults and c…
luispater Oct 14, 2026
f943770
feat(config): add PreapareConfigFileForUpload and seed remote storage…
luispater Oct 14, 2026
ceb4397
feat(executor): drop trailing thought-only model turns in Gemini Vert…
luispater Oct 15, 2026
1631875
fix(watcher): guard management saves against stale config reloads and…
luispater Oct 15, 2026
e9ba5c5
feat(util): strip unsupported discriminator keyword from JSON schemas…
luispater Oct 15, 2026
bbfd788
fix(xai): drop web_search options the Responses API rejects
trukhinyuri Oct 15, 2026
59930ba
feat(claude): map incomplete OpenAI Responses tool status to tool_res…
luispater Oct 15, 2026
207d119
Merge pull request #6642 from trukhinyuri/fix/xai-web-search-unsuppor…
luispater Oct 15, 2026
35af74f
fix(auth): protect active model and credential cooldowns from being c…
luispater Oct 15, 2026
7459255
feat(registry): add gemini-4-argon model definition
luispater Oct 15, 2026
2d7f537
feat(vertex): honor full /publishers/ prefix in API-key base-url
xyonium Oct 15, 2026
5be2cda
Merge pull request #6658 from xyonium/feat/vertex-api-key-full-baseurl
luispater Oct 15, 2026
7a511e4
feat(claude): pin validated request body per-stream in OpenAI Respons…
luispater Oct 15, 2026
fa68946
feat(management): add optimistic concurrency control with ETag and If…
luispater Oct 15, 2026
355fd10
feat(pluginhost): add content-addressed shadow copies for dynamic lib…
luispater Oct 16, 2026
e7003d2
feat(docs): add kedaya.ai as a new AI model API relay service provide…
LTbinglingfeng Oct 16, 2026
202b8b8
feat(claude): clean and normalize Claude tool arguments against origi…
luispater Oct 16, 2026
8071ef5
docs(readme): add Hermes CLIProxyAPI Provider to "Who is with us?"
duu261 Oct 16, 2026
7604d3d
feat(claude): add session date pin retention to preserve continuity a…
luispater Oct 16, 2026
088e445
test(meta): handle client disconnect gracefully after terminal stream…
luispater Oct 16, 2026
b946d54
feat(devin): add account-wide quota exhaustion tracking and credentia…
luispater Oct 16, 2026
911f49c
feat(claude): add automatic thinking block binding and beta policy fo…
luispater Oct 16, 2026
cba68c2
Merge pull request #6684 from duu261/docs/readme-hermes-cliproxyapi-p…
luispater Oct 16, 2026
e13bc9a
feat(claude): synthesize adaptive thinking block binding for preserve…
luispater Oct 17, 2026
ad9e456
feat(claude): support `between_tools` thinking disable type and adapt…
luispater Oct 17, 2026
a43026d
feat(gemini): strip unsupported contentMediaType and contentEncoding …
luispater Oct 17, 2026
4f2e527
feat(runtime): detect upstream stream truncation across executors and…
luispater Oct 17, 2026
c4c1d43
feat(auth): prevent stale file snapshots from overwriting later persi…
luispater Oct 17, 2026
16b5354
test(cliproxy): stabilize antigravity dynamic registration lifecycle …
luispater Oct 17, 2026
b8d4e14
feat(runtime): optimize antigravity schema sanitization to scale line…
luispater Oct 17, 2026
3a07229
feat(meta): filter subscription usage telemetry from SSE streams and …
luispater Oct 17, 2026
f75ea07
feat(cliproxy): reconcile latest auth state when model registration i…
luispater Oct 18, 2026
db1bab0
feat(runtime): narrow Claude per-minute rate-limit cooldown when shor…
luispater Oct 18, 2026
b015f20
fix(oauth): restore credential exclusion priority
LTbinglingfeng Oct 16, 2026
94d1a9a
Refactor authentication exclusion handling and improve model registra…
hkfires Oct 17, 2026
1a28c61
fix(auth): tolerate invalid excluded models on load
hkfires Oct 18, 2026
bb42824
docs(config): clarify oauth excluded-models priority
hkfires Oct 18, 2026
3e309fb
fix(auth): preserve plugin excluded models on synthesis
hkfires Oct 18, 2026
69d0ff8
Merge pull request #6691 from router-for-me/fix/oauth-credential-excl…
hkfires Oct 18, 2026
d7005b6
fix(cliproxy): apply excluded models to plugin models
hkfires Oct 18, 2026
7a0b756
feat(signature): recognize Meta Muse reasoning envelopes and gate rep…
sususu98 Oct 15, 2026
88ac14f
fix(translator): carry reasoning thought signatures through Gemini pr…
sususu98 Oct 16, 2026
a466026
fix(signature): make Gemini thought-signature carriage SDK-safe and o…
sususu98 Oct 16, 2026
cc5682c
fix(signature): replay OpenRouter router-suffixed Meta Muse signatures
sususu98 Oct 16, 2026
772df04
feat(translator): relay reasoning signatures through the Interactions…
sususu98 Oct 16, 2026
674dbe8
fix(signature): support Meta Muse signatures across third-party Respo…
sususu98 Oct 16, 2026
be9fbd9
feat(signature): support router-suffixed GPT/Grok envelopes and multi…
sususu98 Oct 16, 2026
adc436f
fix(pluginhost): bind catalog-only plugin models to credentials
hkfires Oct 18, 2026
a7608a8
feat(pluginhost): preserve auth identity and model registration for r…
luispater Oct 18, 2026
66c2758
feat(pluginhost): remove max line buffer size limit in stream executo…
luispater Oct 18, 2026
acaab59
feat(sdk): expose antigravity user agent helpers
hkfires Oct 18, 2026
a68c7d8
fix(signature): strip OpenRouter private RouterSuffix on official and…
sususu98 Oct 16, 2026
294ed09
feat(discovery): add robust mDNS host conflict resolution and IP bind…
luispater Oct 18, 2026
2422c6b
Merge pull request #6737 from router-for-me/plugins
luispater Oct 18, 2026
4337f1f
fix(logging): escape request path in access log to prevent log injection
luispater Oct 18, 2026
29076c9
Merge pull request #6738 from sususu98/feat/meta-muse-signature-replay
sususu98 Oct 18, 2026
c558d32
feat(util): inline local schema references in Gemini cleaners and pre…
luispater Oct 18, 2026
d69962e
feat(management): add safe Modify method for auth records with epoch …
luispater Oct 18, 2026
7484a52
feat(watcher): protect credentials from unindexed deletion during inc…
luispater Oct 18, 2026
50cfd23
feat(management): add support for static and plugin model definitions…
luispater Oct 18, 2026
5de9de9
perf(gemini): pin request payload and resolved tool maps per stream i…
luispater Oct 18, 2026
feb6398
feat(auth): increase Codex proactive refresh lead to 96 hours and imp…
luispater Oct 18, 2026
1ad175b
feat(auth): snapshot plugin scheduler and release host lock during ex…
luispater Oct 18, 2026
904ec71
feat(auth): enable expired antigravity AI credits negative hint recov…
luispater Oct 18, 2026
030d17e
perf(openai): cache stream preferences and tool maps per stream in Cl…
luispater Oct 19, 2026
9d453bc
feat(cache): add Claude web search result caching and restoration for…
luispater Oct 19, 2026
07feedf
fix(api): allow empty home model catalog
hkfires Oct 19, 2026
4d34502
fix(api): reject home models error envelopes
hkfires Oct 19, 2026
3bbd165
Merge pull request #6765 from router-for-me/models
luispater Oct 19, 2026
d9451cb
feat(vertex): support partner and open models via endpoints/openapi r…
luispater Oct 19, 2026
084b9ca
feat(claude): strip Claude Code identity on API keys with cloak mode …
luispater Oct 19, 2026
45ccd9c
fix(openai): preserve model prefix when routing xAI image requests
luispater Oct 19, 2026
8df4e42
fix(codex): advertise direct tool mode and disable responses lite for…
luispater Oct 19, 2026
e7d4c73
fix(codex): reconcile replayed web_search_call history with tool decl…
luispater Oct 19, 2026
154d514
fix(util): strip readOnly and writeOnly keywords in Gemini schema cle…
luispater Oct 19, 2026
ab9c06b
feat(cache): add Home KV support to Claude web search result cache
luispater Oct 19, 2026
344e0ef
feat(executor): support Codex remote-compaction v2 on Kimi and Meta R…
luispater Oct 19, 2026
d50a199
feat(management): add v8 SIWC credential binding
LTbinglingfeng Oct 19, 2026
c95c3e7
Merge pull request #6786 from router-for-me/feat/siwc-management-bind
luispater Oct 19, 2026
ae3ee3b
fix(management): reject legacy SIWC callbacks and symlink targets
LTbinglingfeng Oct 19, 2026
c449529
fix(openai): preserve tool_use stop reason and omitted-index parallel…
luispater Oct 20, 2026
7db0935
fix(translator): map completion_tokens_details.reasoning_tokens in no…
luispater Oct 20, 2026
3f0cef0
docs(readme): add Xcode sponsor and kedaya.ai to Japanese README
LTbinglingfeng Oct 20, 2026
e198f3c
fix(usage): parse flat reasoning_tokens dialect in OpenAI-compat usag…
sususu98 Oct 20, 2026
9d463e3
fix(meta): measure streaming TTFT on effective token frames
GavinKung Oct 20, 2026
5026f36
feat(executor): pass through downstream User-Agent and set default xA…
luispater Oct 20, 2026
f434192
fix(executor): count completed reasoning items toward TTFT
GavinKung Oct 20, 2026
c644755
Merge pull request #6794 from router-for-me/fix/meta-stream-ttft
GavinKung Oct 20, 2026
02e9e85
fix(antigravity): align Hub requests and invalidate versioned model c…
GavinKung Oct 20, 2026
9cd0de3
Merge pull request #6798 from router-for-me/fix/issue-6619-antigravit…
GavinKung Oct 20, 2026
aadb34f
fix(claude): map refusal, context window and pause_turn stop reasons;…
luispater Oct 20, 2026
77af379
perf(codex): resolve replay target model once per request in Claude t…
luispater Oct 20, 2026
bb2d8f8
fix(auth): resolve relative SIWC binding paths against working directory
luispater Oct 20, 2026
5fe203d
fix(watcher): preserve credentials when auth files return read errors…
luispater Oct 20, 2026
cddc9bb
fix(claude): scope web search result cache by upstream credential
luispater Oct 20, 2026
6bbd2cb
fix(auth): fence SIWC bind commits against replaced credential accounts
luispater Oct 20, 2026
8a3e762
fix(openai): allow xAI image vendor aliases to fall back under force-…
luispater Oct 20, 2026
3870639
fix(translator): preserve gemini thought signatures across openai cha…
luispater Oct 20, 2026
88041f0
fix(auth): serialize legacy auth-file uploads with SIWC bind commits
luispater Oct 20, 2026
20c9095
fix(claude): treat sdk-ts as native Claude Code and preserve caller h…
luispater Oct 20, 2026
d44f868
feat(vertex): support per-model and per-credential openapi routing se…
luispater Oct 20, 2026
4846a28
feat(pluginhost): add host.auth.models callback for per-credential mo…
luispater Oct 20, 2026
06fd5b8
feat(management): add read-only SIWC credential status endpoint
luispater Oct 21, 2026
df07b1e
fix(claude): drop empty text blocks and skip them during cache_contro…
luispater Oct 21, 2026
b12db8c
fix(gemini): preserve usage after terminal stream cancellation
luispater Oct 21, 2026
80d04e1
perf(util): precompute Claude tool-name collision policy
sususu98 Oct 21, 2026
83189e5
perf(gemini/claude): map tool names without rescanning the request
sususu98 Oct 21, 2026
c0e619d
perf(antigravity/claude): resolve request metadata once per stream
sususu98 Oct 21, 2026
33da6ec
Merge pull request #6828 from router-for-me/perf/translator-stream-me…
sususu98 Oct 21, 2026
95e1577
perf(codex/claude): cache short-to-original tool name map per stream
sususu98 Oct 21, 2026
b2e1ab2
Merge pull request #6829 from router-for-me/perf/codex-claude-tool-names
sususu98 Oct 21, 2026
befcba2
feat(home): add planned cluster rebalance handoff
hkfires Oct 21, 2026
3b15314
perf(openai/responses): extract request echo in one pass and drop req…
sususu98 Oct 21, 2026
3fa7639
Merge pull request #6831 from router-for-me/perf/responses-echo-openai
sususu98 Oct 21, 2026
ce07d18
docs: remove FluxA and Baidu AI Cloud sponsor sections and assets
luispater Oct 21, 2026
99d1698
fix(codex): preserve explicit parallel_tool_calls false in OpenAI tra…
luispater Oct 21, 2026
f4a2d04
perf(claude/responses): resolve namespaces from cached state and extr…
sususu98 Oct 21, 2026
7347882
Merge pull request #6832 from router-for-me/home
luispater Oct 21, 2026
9ec96fe
Merge pull request #6834 from router-for-me/perf/responses-echo-claude
sususu98 Oct 21, 2026
74e7ff6
perf(codex/chat): cache tool metadata per stream instead of rescannin…
sususu98 Oct 21, 2026
2957d10
Merge pull request #6836 from router-for-me/perf/codex-chat-tool-cache
sususu98 Oct 21, 2026
80aa2b1
fix(antigravity): preserve tool call replay continuity and caller iso…
luispater Oct 21, 2026
2f6f292
fix(auth): inherit parent credentials for guardian reviews
luispater Oct 21, 2026
009f8d7
fix(thinking): preserve standalone Claude effort on Codex requests
luispater Oct 21, 2026
d232ee1
docs(readme): add Chenju sponsor to README files
sususu98 Oct 21, 2026
0db1902
fix(codex): use original oauth credentials for alpha search
luispater Oct 21, 2026
b9bb031
fix(openai): reauthorize responses websocket turns and support denied…
luispater Oct 21, 2026
633a294
chore(deps): bump Go version to 1.26.10 and update dependencies
luispater Oct 22, 2026
d5816d5
fix(auth,watcher): preserve runtime cooldowns on file snapshots and r…
luispater Oct 22, 2026
ac3cd66
perf(util): skip Gemini schema cleanup when building Responses tool r…
luispater Oct 22, 2026
9e79552
fix(codex): hold response.metadata during stream bootstrap buffering
luispater Oct 22, 2026
c2dfec2
fix(claude): map model_context_window_exceeded to length in chat comp…
luispater Oct 22, 2026
d495e24
fix(claude): map model_context_window_exceeded to incomplete max_outp…
luispater Oct 22, 2026
d2e61d1
fix(claude): validate cloak_mode never headers against configured def…
luispater Oct 22, 2026
4138edb
fix(auth): skip token rejection and refresh for request-scoped 401 rules
luispater Oct 22, 2026
88732ad
fix(vertex): use regional endpoint hosts for multi-region us and eu l…
luispater Oct 22, 2026
df860eb
fix(translator): keep tool_use-deferred Claude web search open across…
luispater Oct 22, 2026
43f27e3
fix(responses): add context_length_exceeded code to Claude prompt ove…
luispater Oct 22, 2026
ad09c77
test(translator): skip replay target model allocation budget test und…
luispater Oct 22, 2026
57a1299
fix(watcher): preserve file credentials when auth directory is unread…
luispater Oct 22, 2026
8bd1795
fix(management): read Handler.cfg under h.mu in OAuth login flows and…
luispater Oct 22, 2026
07b5a7a
feat(usage): report effective outbound service tier after payload rules
luispater Oct 22, 2026
ceb045a
ci(workflow): bump Go version to 1.26.10 in release pipeline
luispater Oct 22, 2026
b90190d
fix(usage): propagate claude usage.speed into response service tier
luispater Oct 22, 2026
a014ba0
test(pluginhost,handlers): fix flaky races in plugin load and stream …
luispater Oct 22, 2026
13874f1
fix(pluginhost): pass decoded request body to frontend auth plugins
luispater Oct 22, 2026
4550161
fix(gemini): enable server-side tool invocations when mixing built-in…
luispater Oct 22, 2026
d946c4f
feat(codex): ignore use_siwc and enforce non-SIWC credentials for Cod…
luispater Oct 23, 2026
e45f942
feat(home): add cluster latency telemetry and probing
hkfires Oct 23, 2026
41a4b9f
Merge pull request #6903 from router-for-me/home
hkfires Oct 23, 2026
376015c
fix(codex): map commentary phase messages to thinking blocks in Claud…
luispater Oct 23, 2026
e1fb252
fix(claude): preserve tool arguments for implicitly open empty object…
luispater Oct 23, 2026
e5434f6
fix(signature): sign the first Gemini function call after a text part
luispater Oct 23, 2026
83cb1b9
fix(gemini): populate token limits in Gemini model catalog responses
luispater Oct 23, 2026
3f5d3a1
fix(gemini/vertex): preserve non-content finish reasons and surface p…
luispater Oct 23, 2026
29150a2
fix(schema): preserve Gemini $ref sibling constraints
luispater Oct 23, 2026
888f238
fix(api): add RESP protocol bounds validation and connection panic re…
luispater Oct 23, 2026
8289ec4
fix(usage): preserve interactions token semantics when merging stream…
luispater Oct 23, 2026
0d3ca1d
fix(store,home): handle repository index and packfile corruption and …
luispater Oct 24, 2026
ab139b4
fix(kimi): share thinking replay across K3.1 Pro variants
sususu98 Oct 24, 2026
da21f1e
fix(antigravity): restore non-stream tool signatures and preserve str…
luispater Oct 24, 2026
9d08f0d
fix(pluginhost): strip credential headers across cross-origin redirects
luispater Oct 24, 2026
44d1ddf
fix(pluginhost): translate plugin count_tokens replies as token counts
luispater Oct 24, 2026
35e834d
feat(pluginabi): carry retry-after metadata from plugin executor errors
luispater Oct 24, 2026
50147ae
fix(home): close underlying transport synchronously when canceling re…
luispater Oct 24, 2026
e42eee6
fix(pluginhost): apply user payload rules to plugin executor requests
luispater Oct 24, 2026
c9af529
fix(pluginhost): run canonical thinking pipeline before plugin execution
luispater Oct 24, 2026
179d43d
fix(logging): prevent path traversal vulnerabilities in request log f…
luispater Oct 24, 2026
bc06434
docs: remove outdated third-party extensions and apps from readmes
luispater Oct 24, 2026
2bb6ac6
fix(lint): resolve go vet lostcancel and static analysis warnings fro…
luispater Oct 24, 2026
6340fe4
fix(codex): bind duplex websocket turns to requested client model aft…
luispater Oct 24, 2026
3e7a21e
fix(openai): isolate duplex turn reauthorization from gin context and…
luispater Oct 24, 2026
32dd2c8
fix(watcher): preserve file snapshot binding on persisted auth updates
luispater Oct 24, 2026
2155350
fix(auth): restore re-logged credentials to rotation after refresh fa…
luispater Oct 24, 2026
b2fda98
fix(util): defer Gemini array placeholder items until after ref and a…
luispater Oct 24, 2026
e48d780
fix(plugin): preserve caller scope for replayed Claude OAuth MCP tool…
luispater Oct 25, 2026
0c61b12
fix(xai): deduplicate tools when promoting historical additional_tools
luispater Oct 25, 2026
ce433b3
fix(cliproxy): back off home subscriber retries
hkfires Oct 25, 2026
cf4fc4e
Merge pull request #6969 from router-for-me/home
sususu98 Oct 25, 2026
ba06ec5
fix(vertex): default credential location to global
LTbinglingfeng Oct 25, 2026
bdde391
fix(translator): preserve finishReason in Codex and OpenAI to Gemini …
luispater Oct 25, 2026
3dae075
feat(devin): aggregate swe-2 lightning UIDs into swe-2-lightning model
luispater Oct 25, 2026
27f3abf
feat(management): support session-scoped OAuth proxy with per-account…
luispater Oct 25, 2026
0fe4cc2
fix(openai): report buffered stream error when responses websocket da…
luispater Oct 25, 2026
90fe5b2
fix(handlers): report stream cancellation when channel closes with ca…
luispater Oct 25, 2026
84e8344
test(executor): fix race conditions in flaky websocket executor tests
luispater Oct 25, 2026
3078035
fix(aistudio): translate every SSE frame of a relay stream chunk
luispater Oct 25, 2026
712e497
fix(handlers): report cancellation when stream closes before first chunk
luispater Oct 25, 2026
e5321f5
fix(auth,pluginapi,usage): share per-selection ID between Scheduler.P…
luispater Oct 25, 2026
064e008
feat(codex): add full-chain compression for Codex upstream and downst…
luispater Oct 26, 2026
43f5386
fix(translator): map Claude thinking_tokens to reasoning_tokens in Op…
luispater Oct 26, 2026
531721b
fix(codex): restore Codex commentary history via internal thinking si…
luispater Oct 26, 2026
058b803
fix(api): explicitly allow Authorization in CORS preflight responses
luispater Oct 26, 2026
6fe654b
perf(pluginhost): gate request interceptor body delivery behind schem…
luispater Oct 26, 2026
ede07ca
fix(interactions): emit [DONE] sentinel after terminal usage frame in…
luispater Oct 26, 2026
8a982a5
feat(discovery): align TXT schema with draft-su-ai-gateway-discovery-00
sususu98 Oct 26, 2026
b214385
chore(config): deprecate discovery advertise-management
sususu98 Oct 26, 2026
1d45a5f
fix(claude): handle forced tool restrictions in claude 5.5
luispater Oct 26, 2026
37bd18b
fix(antigravity): accept bare content-block lists in interactions input
luispater Oct 26, 2026
11e5f67
fix(discovery): resolve split mDNS responses with scoped bounded caches
sususu98 Oct 26, 2026
999526c
docs(discovery): describe LAN resolution limits and trust boundaries
sususu98 Oct 26, 2026
aa4130e
fix(gemini): keep truncated HTTP 200 streams out of credential cooldo…
luispater Oct 26, 2026
ec81e70
Merge pull request #7010 from sususu98/feat/discovery-ietf-draft
sususu98 Oct 26, 2026
1f917e7
docs(readme): remove APIMart sponsor sections and assets
luispater Oct 26, 2026
7f7d7a6
Merge upstream v8.0.44 into the fork (HOUSE-79)
ericlitman Oct 27, 2026
2753090
fix(auth): keep reserve windows when restoring quota state (HOUSE-79)
ericlitman Oct 27, 2026
c88d701
docs: record the merge-based upstream sync on v8.0.44 (HOUSE-79)
ericlitman Oct 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ go build -o test-output ./cmd/server && rm test-output # Verify compile (REQUIRE
- As a rule, do not make standalone changes to `internal/translator/`. You may modify it only as part of broader changes elsewhere.
- If a task requires changing only `internal/translator/`, run `gh repo view --json viewerPermission -q .viewerPermission` to confirm you have `WRITE`, `MAINTAIN`, or `ADMIN`. If you do, you may proceed; otherwise, file a GitHub issue including the goal, rationale, and the intended implementation code, then stop further work.
- `internal/runtime/executor/` should contain executors and their unit tests only. Place any helper/supporting files under `internal/runtime/executor/helps/`.
- Payload configuration MUST be the final semantic barrier before sending requests in every executor, including streaming, WebSocket, continuation, retry/fallback, image, and token-count paths where applicable. Complete all built-in payload translation, normalization, injection, and cleanup first, then evaluate and apply user payload rules exactly once to the final business payload. No subsequent logic may overwrite configured values or restore filtered fields. Only necessary transport framing, serialization, signature calculation, and read-only validation may follow without changing business payload semantics. Add regression tests when introducing or changing request-building paths to enforce this ordering.
- Follow `gofmt`; keep imports goimports-style; wrap errors with context where helpful
- Do not use `log.Fatal`/`log.Fatalf` (terminates the process); prefer returning errors and logging via logrus
- Shadowed variables: use method suffix (`errStart := server.Start()`)
Expand Down
9 changes: 6 additions & 3 deletions MOBILYZE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

A fork of [router-for-me/CLIProxyAPI](https://github.com/router-for-me/CLIProxyAPI) that adds the `soonest-reset` credential selector (MASTRA-765). The selector sends each new session to the account whose weekly window resets soonest, among accounts that still have quota.

- Base: upstream tag `v8.0.13` (d7914afd). Our commits sit on top of it on `main`.
- To move to a new upstream tag: `git fetch upstream --tags`, then rebase our commits onto the tag.
- Base: upstream tag `v8.0.44` (1f917e77), merged into `main` by merge commit `7f7d7a61`.
- To move to a new upstream tag: `git fetch upstream --tags`, create a branch from `main`, and
merge the tag into it. Keep `.github/workflows/` to our own workflows. Land the branch through
a normal pull request, which Mergify merges with a merge commit. Do not rebase: a rebase needs a
force-push past the `non_fast_forward` rule on `main`.
- Never push upstream tags to this repo. Upstream's release and Docker workflows were removed, but a pushed upstream tag still carries them in its own tree.
- Our releases use tags of the form `v8.0.13-mob.N`.
- Our releases use tags of the form `v8.0.44-mob.N`.
- Selector source: zsprackett/CLIProxyAPI commits `faa4ccff`, `01ad0021` and `67f5749d` (MIT), with authorship kept. `4d7b2e84` (model-scoped weekly windows) was left out.

## Subscription reserves
Expand Down
69 changes: 41 additions & 28 deletions README.md

Large diffs are not rendered by default.

70 changes: 41 additions & 29 deletions README_CN.md

Large diffs are not rendered by default.

68 changes: 40 additions & 28 deletions README_JA.md

Large diffs are not rendered by default.

Binary file removed assets/aiberm.png
Binary file not shown.
Binary file removed assets/apimart-en.png
Binary file not shown.
Binary file removed assets/apimart-zh.png
Binary file not shown.
Binary file added assets/chenju.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed assets/fluxa-baidu-ai-cloud.png
Binary file not shown.
Binary file added assets/kedaya.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/modelflare.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/xcode.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 79 additions & 3 deletions cmd/fetch_codex_models/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import (
coreauth "github.com/router-for-me/CLIProxyAPI/v8/sdk/cliproxy/auth"
"github.com/router-for-me/CLIProxyAPI/v8/sdk/proxyutil"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
)

const (
Expand All @@ -46,6 +48,8 @@ const (
defaultCodexUserAgent = "codex_cli_rs/0.159.0 (Mac OS 26.3.1; arm64) iTerm.app/3.6.9"
defaultCodexOriginator = "codex_cli_rs"
accessTokenRefreshLeeway = 30 * time.Second
baselineModelSlug = "gpt-5.5"
baselineModelVisibility = "list"
)

func init() {
Expand Down Expand Up @@ -289,13 +293,85 @@ func fetchModels(ctx context.Context, auth *coreauth.Auth, accessToken, clientVe
return nil, 0, fmt.Errorf("models request failed with status %d: %s", httpResp.StatusCode, strings.TrimSpace(string(bodyBytes)))
}

count, errCount := countModels(bodyBytes)
if errCount != nil {
return nil, 0, errCount
bodyBytes, count, errEnsure := ensureBaselineModel(bodyBytes)
if errEnsure != nil {
return nil, 0, errEnsure
}
return bodyBytes, count, nil
}

func ensureBaselineModel(raw []byte) ([]byte, int, error) {
var payload struct {
Models []json.RawMessage `json:"models"`
}
if errUnmarshal := json.Unmarshal(raw, &payload); errUnmarshal != nil {
return nil, 0, fmt.Errorf("failed to parse response JSON: %w", errUnmarshal)
}
// Keep this check intentionally loose: fetch_codex_models dumps the upstream
// Codex API payload. Strict CPA catalog validation belongs in
// cmd/validate_codex_models and registry.ValidateCodexClientModelsJSON.
if payload.Models == nil {
return nil, 0, fmt.Errorf("response JSON does not contain models array")
}
if len(payload.Models) == 0 {
return raw, 0, nil
}

foundBaseline := false
for i, modelRaw := range payload.Models {
slugResult := gjson.GetBytes(modelRaw, "slug")
if slugResult.Type != gjson.String || strings.TrimSpace(slugResult.Str) != baselineModelSlug {
continue
}
foundBaseline = true
visResult := gjson.GetBytes(modelRaw, "visibility")
if visResult.Type != gjson.String || visResult.Str != baselineModelVisibility {
updated, errSet := sjson.SetBytes(raw, fmt.Sprintf("models.%d.visibility", i), baselineModelVisibility)
if errSet != nil {
return nil, 0, fmt.Errorf("failed to update %s visibility: %w", baselineModelSlug, errSet)
}
raw = updated
}
}

count := len(payload.Models)
if !foundBaseline {
cloned := append([]byte(nil), payload.Models[0]...)
var errSet error
cloned, errSet = sjson.SetBytes(cloned, "slug", baselineModelSlug)
if errSet != nil {
return nil, 0, fmt.Errorf("failed to set %s slug on cloned model: %w", baselineModelSlug, errSet)
}
visResult := gjson.GetBytes(cloned, "visibility")
if visResult.Type != gjson.String || visResult.Str != baselineModelVisibility {
cloned, errSet = sjson.SetBytes(cloned, "visibility", baselineModelVisibility)
if errSet != nil {
return nil, 0, fmt.Errorf("failed to set %s visibility on cloned model: %w", baselineModelSlug, errSet)
}
}
for _, reset := range []struct {
path string
value any
}{
{path: "tool_mode", value: "direct"},
{path: "use_responses_lite", value: false},
{path: "supports_reasoning_effort_updates", value: false},
} {
cloned, errSet = sjson.SetBytes(cloned, reset.path, reset.value)
if errSet != nil {
return nil, 0, fmt.Errorf("failed to set %s %s on cloned model: %w", baselineModelSlug, reset.path, errSet)
}
}
raw, errSet = sjson.SetRawBytes(raw, "models.-1", cloned)
if errSet != nil {
return nil, 0, fmt.Errorf("failed to append %s model: %w", baselineModelSlug, errSet)
}
count++
}

return raw, count, nil
}

func codexModelsURL(clientVersion string) (string, error) {
u, err := url.Parse(codexModelsBaseURL + codexModelsPath)
if err != nil {
Expand Down
99 changes: 98 additions & 1 deletion cmd/fetch_codex_models/main_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package main

import "testing"
import (
"testing"

"github.com/tidwall/gjson"
)

func TestCodexModelsURL(t *testing.T) {
got, err := codexModelsURL(" 0.144.1 ")
Expand Down Expand Up @@ -46,3 +50,96 @@ func TestCountModels(t *testing.T) {
t.Fatal("countModels(missing models) error = nil, want error")
}
}

func TestEnsureBaselineModel(t *testing.T) {
t.Run("clones first model as gpt-5.5 when missing", func(t *testing.T) {
raw := []byte(`{"models":[{"slug":"gpt-6.1-sol","display_name":"GPT-6.1-Sol","visibility":"list","tool_mode":"code_mode_only","use_responses_lite":true,"supports_reasoning_effort_updates":true},{"slug":"gpt-5.6-sol","visibility":"list"}]}`)
out, count, errEnsure := ensureBaselineModel(raw)
if errEnsure != nil {
t.Fatalf("ensureBaselineModel: %v", errEnsure)
}
if count != 3 {
t.Fatalf("count = %d, want 3", count)
}
if got := gjson.GetBytes(out, "models.0.slug").String(); got != "gpt-6.1-sol" {
t.Fatalf("models[0].slug = %q, want gpt-6.1-sol", got)
}
if got := gjson.GetBytes(out, "models.0.tool_mode").String(); got != "code_mode_only" {
t.Fatalf("models[0].tool_mode = %q, want code_mode_only", got)
}
if got := gjson.GetBytes(out, "models.2.slug").String(); got != "gpt-5.5" {
t.Fatalf("models[2].slug = %q, want gpt-5.5", got)
}
if got := gjson.GetBytes(out, "models.2.display_name").String(); got != "GPT-6.1-Sol" {
t.Fatalf("models[2].display_name = %q, want GPT-6.1-Sol", got)
}
if got := gjson.GetBytes(out, "models.2.visibility").String(); got != "list" {
t.Fatalf("models[2].visibility = %q, want list", got)
}
if got := gjson.GetBytes(out, "models.2.tool_mode"); got.Type != gjson.String || got.Str != "direct" {
t.Fatalf("models[2].tool_mode = %v (%s), want string \"direct\"", got.Value(), got.Type)
}
if got := gjson.GetBytes(out, "models.2.use_responses_lite"); got.Type != gjson.False {
t.Fatalf("models[2].use_responses_lite = %v (%s), want false", got.Value(), got.Type)
}
if got := gjson.GetBytes(out, "models.2.supports_reasoning_effort_updates"); got.Type != gjson.False {
t.Fatalf("models[2].supports_reasoning_effort_updates = %v (%s), want false", got.Value(), got.Type)
}
})

t.Run("clones first model and forces visibility to list when first model is hidden", func(t *testing.T) {
raw := []byte(`{"models":[{"slug":"gpt-reserve","visibility":"hide"}]}`)
out, count, errEnsure := ensureBaselineModel(raw)
if errEnsure != nil {
t.Fatalf("ensureBaselineModel: %v", errEnsure)
}
if count != 2 {
t.Fatalf("count = %d, want 2", count)
}
if got := gjson.GetBytes(out, "models.0.visibility").String(); got != "hide" {
t.Fatalf("models[0].visibility = %q, want hide", got)
}
if got := gjson.GetBytes(out, "models.1.slug").String(); got != "gpt-5.5" {
t.Fatalf("models[1].slug = %q, want gpt-5.5", got)
}
if got := gjson.GetBytes(out, "models.1.visibility").String(); got != "list" {
t.Fatalf("models[1].visibility = %q, want list", got)
}
})

t.Run("forces existing gpt-5.5 visibility to list when hidden", func(t *testing.T) {
raw := []byte(`{"models":[{"slug":"gpt-6.1-sol","visibility":"list"},{"slug":"gpt-5.5","visibility":"hide"}]}`)
out, count, errEnsure := ensureBaselineModel(raw)
if errEnsure != nil {
t.Fatalf("ensureBaselineModel: %v", errEnsure)
}
if count != 2 {
t.Fatalf("count = %d, want 2", count)
}
if got := gjson.GetBytes(out, "models.1.slug").String(); got != "gpt-5.5" {
t.Fatalf("models[1].slug = %q, want gpt-5.5", got)
}
if got := gjson.GetBytes(out, "models.1.visibility").String(); got != "list" {
t.Fatalf("models[1].visibility = %q, want list", got)
}
})

t.Run("forces existing gpt-5.5 visibility to exact list when padded or non-string", func(t *testing.T) {
for _, raw := range [][]byte{
[]byte(`{"models":[{"slug":"gpt-5.5","visibility":" list "}]}`),
[]byte(`{"models":[{"slug":"gpt-5.5","visibility":false}]}`),
} {
out, count, errEnsure := ensureBaselineModel(raw)
if errEnsure != nil {
t.Fatalf("ensureBaselineModel(%s): %v", raw, errEnsure)
}
if count != 1 {
t.Fatalf("count = %d, want 1", count)
}
vis := gjson.GetBytes(out, "models.0.visibility")
if vis.Type != gjson.String || vis.Str != "list" {
t.Fatalf("models[0].visibility = %v (%s), want string \"list\"", vis.Value(), vis.Type)
}
}
})
}
20 changes: 18 additions & 2 deletions cmd/fetch_devin_models/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,15 @@ var devinCompoundSuffixes = []struct {
{suffix: "-thinking", effort: ""},
{suffix: "-max-1m", effort: "max", readd: "-1m"},
{suffix: "-none-1m", effort: "none", readd: "-1m"},
// Lightning tier keeps the effort before the -lightning suffix upstream
// (e.g. swe-2-high-lightning), so it aggregates as <base>-lightning.
{suffix: "-minimal-lightning", effort: "minimal", readd: "-lightning"},
{suffix: "-low-lightning", effort: "low", readd: "-lightning"},
{suffix: "-medium-lightning", effort: "medium", readd: "-lightning"},
{suffix: "-high-lightning", effort: "high", readd: "-lightning"},
{suffix: "-xhigh-lightning", effort: "xhigh", readd: "-lightning"},
{suffix: "-max-lightning", effort: "max", readd: "-lightning"},
{suffix: "-none-lightning", effort: "none", readd: "-lightning"},
}

var devinSimpleEffortSuffixes = []struct {
Expand Down Expand Up @@ -571,12 +580,19 @@ func aggregateModels(raw []rawDevinModel) []devinModelJSON {
}
}

// Lightning display names strip both the effort word and "Lightning";
// re-append it so swe-2-lightning shows as "SWE-2 Lightning".
displayName := entry.displayName
if strings.HasSuffix(id, "-lightning") && !strings.HasSuffix(strings.ToLower(displayName), "lightning") {
displayName = strings.TrimSpace(displayName + " Lightning")
}

res = append(res, devinModelJSON{
ID: entry.baseID,
Object: "model",
Type: "devin",
OwnedBy: vendorName(entry.vendorID, entry.baseID),
DisplayName: entry.displayName,
DisplayName: displayName,
ContextLength: entry.contextLength,
MaxCompletionTokens: 64000,
SupportedInputModalities: modalities,
Expand All @@ -595,7 +611,7 @@ var devinDisplayNameSuffixes = []string{
" Low Thinking", " Medium Thinking", " High Thinking", " XHigh Thinking",
" Max Thinking", " No Thinking",
" Low", " Medium", " High", " XHigh", " Max", " None", " Minimal",
" Thinking", " Fast",
" Thinking", " Fast", " Lightning",
}

func cleanDisplayName(label string) string {
Expand Down
3 changes: 3 additions & 0 deletions cmd/fetch_devin_models/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ func TestSplitDevinUID(t *testing.T) {
{"swe-1-6-slow", "swe-1-6-slow", ""},
{"swe-1-6-fast", "swe-1-6", ""},
{"swe-2", "swe-2", ""},
{"swe-2-medium-lightning", "swe-2-lightning", "medium"},
{"swe-2-high-lightning", "swe-2-lightning", "high"},
{"swe-2-max-lightning", "swe-2-lightning", "max"},
}

for _, tt := range tests {
Expand Down
Loading
Loading