Compare commits

...

125 Commits

Author SHA1 Message Date
Markus Hartung
15a786b56f fix(docker): re-derive build memory budget from measured per-process RSS (#7518)
PR #11419 lowered OMNIROUTE_BUILD_WORKERS 8->3 using an INFERRED per-worker
peak (WORKER_PEAK_MB=2560) and treated the parent `next build` process's
RSS as bounded by OMNIROUTE_BUILD_MEMORY_MB (the V8 heap ceiling). Both
assumptions were wrong: the issue owner's own VPS reproduction (dmesg
OOM-killer report) measured the real per-process RSS directly at ~4.5 GB,
independent of NODE_OPTIONS, since Turbopack compiles in native/Rust memory
outside the V8 heap -- and that applies to the parent process too.

With OMNIROUTE_BUILD_WORKERS=3 (1 parent + 2 workers), the measured worst
case is 3 x 4500MB = 13500MB against a 12288MB (75% of 16GB) budget --
still over, matching the still-live "Publish to Docker Hub" CI failures
after #11419 merged (run 32907937950, 2026-08-25).

Lowers OMNIROUTE_BUILD_WORKERS to 2 (1 parent + 1 worker = 9000MB, fits
with headroom) and re-derives tests/unit/docker-build-memory-budget.test.ts's
model on the measured figure, applied uniformly to every process instead of
conflating the parent process with the V8 heap ceiling.
2026-08-26 12:51:43 -03:00
Diego Rodrigues de Sa e Souza
91aeca0440 fix(security): redact NVIDIA_API_KEY at the log sink in the ad-hoc diag script (#11639)
Merged via /merge-batch (2026-08-26, v3.8.51). Validado no worktree combinado.
2026-08-26 10:59:26 -03:00
Webman
49749eb0d0 fix(types): clear the two type regressions red on release/v3.8.51 (#11640)
Merged via /merge-batch (2026-08-26, v3.8.51). Confirma o fix do typecheck:core que eu vinha classificando como drift pré-existente nas últimas levas (zai-web.ts mimeType) — obrigado por resolver de vez. Validado: typecheck limpo, 7/7 testes passando.
2026-08-26 10:59:19 -03:00
Bob.Hou
8d17110082 fix(build): resolve workspace: protocol dependencies to concrete semver versions during prepublish (#11540) (#11641)
Merged via /merge-batch (2026-08-26, v3.8.51). Validado: typecheck/complexity/file-size/changelog verdes, 3/3 testes do prepublish workspace-protocol passando. Obrigado pela contribuição.
2026-08-26 10:59:14 -03:00
Webman
1ee4818224 deps: realign onnxruntime-node pin to @huggingface/transformers' 1.24.3 lockstep (#11633)
Merged via /merge-batch (2026-08-26, v3.8.51). Validado com `npm install` completo: 0 vulnerabilidades, lockfile consistente após o realinhamento do pin onnxruntime-node. Obrigado pela contribuição.
2026-08-26 09:54:52 -03:00
Prajeeth H
6afc7ddab0 fix(install): guard prepare script against missing husky (#11634)
Merged via /merge-batch (2026-08-26, v3.8.51). Validado: 5/5 testes passando, `npm install` limpo confirmando que o script prepare não quebra sem husky. Obrigado pela contribuição.
2026-08-26 09:54:48 -03:00
Webman
71fd806bb0 test(autoCombo): port models_dev_tier #11508 guard from node:test to vitest (#11635)
Merged via /merge-batch (2026-08-26, v3.8.51). Validado com o config correto (`vitest run --config vitest.mcp.config.ts`, que já inclui `tests/unit/autoCombo/**/*.test.ts`): 5/5 testes passando. Obrigado por destravar esse base-red.
2026-08-26 09:54:44 -03:00
Diego Rodrigues de Sa e Souza
adedc351d7 chore(quality): rebaseline file-size for #11083/#11631/#11628 growth (#11636)
Merged via /merge-batch (correção de lacuna, 2026-08-26). check:file-size confirmado OK após o rebaseline.
2026-08-26 09:52:44 -03:00
Webman
1d476e4ced fix(ci): resolve inherited release/v3.8.51 base-red CI failures (#11608)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). 7 conflitos, todos triviais/duplicados (mesmos base-reds já corrigidos por PRs paralelas mergeadas neste lote — #11580/#11582/#11583/#11585/#11588/#11589/#11590/#11591/#11609): mantida a versão já validada nesses casos. Validado: 68/68 testes passando. Obrigado por resolver os base-reds.
2026-08-26 09:28:08 -03:00
Meet shah
18d5b75335 chore(ci): unblock quality gates - env-doc sync + stryker tap.testFiles registration (#9282) (#11609)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Dois conflitos, ambos triviais: (1) stryker.conf.json — mesma linha com indentação diferente, mantida a indentação correta; (2) ts7-executor-shared-shapes.test.ts — mesma correção já coberta por #11591/#11608 (mergeados neste lote), mantido o describe/comentário melhor deste PR sobre a asserção já validada. Validado: 4/4 testes passando. Obrigado pela contribuição.
2026-08-26 09:26:37 -03:00
MumuTW
00d385b498 fix(autoCombo,sse): drop vendor-retired ids from the auto-combo pool and skip leftover arena_elo (#11625) (#11626)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Conflito real em taskFitness.ts: seu código pula corretamente as camadas 1-3 para ids vendor-retired (a versão anterior fazia lookup redundante de arena_elo/inherited/tier mesmo quando já sabia que o id era retired). Resolvido mantendo o skip antecipado. Validado: 23/23 testes passando. Obrigado pela contribuição.
2026-08-26 09:25:25 -03:00
Benson K B
7b9b36836c fix(db): fallback load STORAGE_ENCRYPTION_KEY from env files (#11614)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Encontrei um bug real na validação: o guard `NODE_ENV==="test"||VITEST` não cobre o test runner nativo do projeto (`node --import tsx/esm --test`, que não seta NODE_ENV), então o fallback estava lendo `~/.omniroute/.env` — o .env de PRODUÇÃO real do operador — durante qualquer execução de teste sem esse env var. Corrigi usando o `isTestContext()` já existente e mais robusto em `dataPaths.ts` (cobre `NODE_TEST_CONTEXT`/`--test` argv), e troquei o path hardcoded `os.homedir()/.omniroute` por `resolveDataDir()` para respeitar `DATA_DIR` quando configurado. Enviei a correção para o seu branch antes do merge. Validado: 7/7 testes de `db-encryption.test.ts` passando. Obrigado pela contribuição — a ideia central (fallback do STORAGE_ENCRYPTION_KEY) é boa e necessária.
2026-08-26 09:23:57 -03:00
Paco Cartones
ae8ab27294 fix(dashboard): restore focus after closing modals (#11607)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:22:26 -03:00
Paco Cartones
9237a0562f fix(dashboard): conceal locked hidden badge details (#11605)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:22:22 -03:00
Paco Cartones
c4d149c2eb fix(dashboard): keep Profile XP and level consistent (#11604)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:22:18 -03:00
Paco Cartones
a0422b9af8 fix(dashboard): harden search analytics responses (#11603)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:22:15 -03:00
Paco Cartones
5f5d1101ba fix(dashboard): enable keyboard activation for data-table rows (#11610)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:22:11 -03:00
vsd2807
5b8fe4d8c7 fix(handoff): enforce provider allowlist for universal handoff (#11602) (#11619)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:22:06 -03:00
Kobi Kadosh
d1768de716 feat(providers): add Nimble web search and fetch (#11620)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:22:03 -03:00
Mr White
c11f661a8a feat(resilience): add provider peak-hour protection (#11622)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:21:59 -03:00
Hsia97
0481f61750 fix: pass tool result content through as string in OpenAI/Claude -> Gemini translation (#11624)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:21:56 -03:00
KaspaPulse
86c03f1fed fix(sse): scope credential health to exact key (#11628)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:21:52 -03:00
zero-executioner
8abcd639d1 feat(providers): add 1min.ai provider (#11631)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:21:48 -03:00
rifqiawl
9f1f5ecf1f fix(kiro): add runtime.us-east-1.kiro.dev as first-attempt endpoint (#11517)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:21:44 -03:00
rifqiawl
e616130496 fix(providers): poll onboardUser LRO before classifying BYOP (#11519)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:21:41 -03:00
Paulo Roberto Fernandes Holanda
7a10d3856a fix: restore live websocket URL helpers (#11509)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:21:37 -03:00
Andrew B.
5984c43f5b feat(logs): add copy-all button to request detail modal (#11083)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:21:32 -03:00
Tobias Andersen
331580b499 fix(providers): mark Brave Search as no longer having a free tier (#11621)
Merged via /merge-batch (lote 2026-08-26 batch 2, v3.8.51). Boarded no worktree combinado junto com outras ~20 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e 292 testes focados (unit) + 18 (vitest) passando. Obrigado pela contribuição.
2026-08-26 09:21:27 -03:00
Diego Rodrigues de Sa e Souza
3a7ed20bcd chore(quality): rebaseline file-size for #11448/#11495/#11561 growth (#11630)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). check:file-size confirmado OK após o rebaseline.
2026-08-26 08:17:54 -03:00
Diego Rodrigues de Sa e Souza
9c34e88f6b feat(providers): add Opper as an API-key gateway provider (#11629)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Porta de #11538 com autoria original preservada — ver detalhes na descrição desta PR.
2026-08-26 08:17:03 -03:00
Rafa Martins
131f8cb15a fix(i18n): complete Brazilian Portuguese translations (#11558)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Branch original tinha divergido de um ponto bem antigo de `main` (phantom-diff, dezenas de commits já mergeados no meio); extraí o commit de valor real (completar traduções pt-BR) e reapliquei sobre o tip atual. Houve conflito genuíno em `pt-BR.json`: algumas chaves já tinham sido traduzidas por outra PR mais recente (mantive essas) e outras (errorOccurred/comboDeleted/hide/creating/comboCreated/swapFormats) só existiam em inglês até esta PR (apliquei a tradução de vocês). Validado: 134/134 testes de integridade i18n passando, incluindo paridade de chaves com en.json. Obrigado pela contribuição.
2026-08-26 08:15:50 -03:00
Rafa Martins
2617841449 fix: accept Gemini Web cookie exports (#11554)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). O branch original tinha divergido de um ponto bem antigo de `main` (phantom-diff — dezenas de commits já mergeados no meio); extraí os 2 commits de valor real (aceitar cookies completos/PSID/JSON exportado do Gemini Web) e reapliquei sobre o tip atual de `release/v3.8.51` (o commit adicional de 'restore endpoint page JSX' já estava coberto pelo tip, então não era necessário). Validado: 125/125 testes de `provider-validation-specialty.test.ts` passando. Obrigado pela contribuição.
2026-08-26 08:13:22 -03:00
Ronaldo Davi
65aeaeece8 Only advertise verified-working connections by default (#11448)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:11:35 -03:00
Paijo
d351960be9 feat(providers): verify-only health sweep for web-cookie connections (#11488) (#11495)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:11:30 -03:00
Burak Keskin
4914954866 fix(mitm): keep Windows DNS elevation off the POSIX sudo path (#11430) (#11542)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:11:26 -03:00
Abhishek Sharma
b7d91a6b6e fix(quota-share): give each in-flight request its own lease (#11547)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:11:22 -03:00
Nguyễn Viết Tuấn
ebbfcf4ffe fix(sse): scale chat admission by ingest byte budget instead of a fixed request count (#11548)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:11:18 -03:00
Az1muth
2d185de9d9 fix(sse): prevent client-abort (aborted/ECONNRESET) from crashing the server (#11556)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:11:14 -03:00
Giorgos Giakoumettis
c63e519b09 feat(tunnels): support named cloudflared tunnels via CLOUDFLARED_CONFIG (#11561)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:11:09 -03:00
vsd2807
a02b4b404d fix(search): prefer credentialed providers over duckduckgo-free fallback (#11524) (#11565)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:11:05 -03:00
Webman
6e96057f1d fix(sse): explicit types for openai-responses pureHelpers — clears last failing core typecheck gate (#11567)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:11:00 -03:00
Guhan K
5eebee5dcc fix(sse): do not 502 Claude Code /model probes (content:[] + max_tokens) (#11568)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:10:55 -03:00
Nguyen Thanh Dat
608c90f592 fix(cache): expire a semantic-cache row on its TTL, not at UTC midnight (#11559) (#11573)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:10:51 -03:00
Nguyen Thanh Dat
b61a530a33 fix(api): reconnect the /v1/models background-refresh scheduler (#11551) (#11574)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:10:47 -03:00
Amar Tinawi
6ffa012c3e test(chatcore): guard the response tool-name alias recovery (#11575)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:10:43 -03:00
Nguyen Thanh Dat
eccb66042c docs(env): document OMNIROUTE_CORPUS_CACHE_SIZE so Docs Gates goes green again (#11576)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:10:38 -03:00
Nguyen Thanh Dat
5c1a882b95 chore(stryker): register the two test files covering three mutated modules (#11577)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:10:34 -03:00
Nguyen Thanh Dat
8cb2d0c047 test(authz): pin the GET-exemption set by membership, not by count (#11531) (#11580)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:10:29 -03:00
Nguyen Thanh Dat
1ea13454d5 fix(check): await the now-async getExecutor in the known-symbols gate (#11421) (#11582)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:10:24 -03:00
Nguyen Thanh Dat
0a792216d6 test(build): pin the bundler flag to OMNIROUTE_USE_TURBOPACK, the contract it implements (#11583)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:10:20 -03:00
AStupidBear
4449ba3173 fix(opencode): hydrate Proxy Pool references for no-auth connections (#11584)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:10:16 -03:00
Nguyen Thanh Dat
fe12208e30 test(claude-web): anchor on the alias wiring, not on how the map builds it (#11585)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:10:12 -03:00
Nguyen Thanh Dat
f40f6e18da fix(pack): register bin/cli/utils/volatileEnvPath.mjs as a required artifact path (#11437) (#11588)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:10:08 -03:00
Nguyen Thanh Dat
91ede70bcb i18n(vi): translate the five reliability-column strings (#11589)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:10:04 -03:00
Nguyen Thanh Dat
954d58b528 test(models): pin qwen3.8-max resolution per provider, not across all four (#11590)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:09:59 -03:00
Nguyen Thanh Dat
88939a35d1 test(executors): drop the tool-truncation assertion #11444 removed the code for (#11591)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:09:55 -03:00
Nguyen Thanh Dat
b9fd4aa00b test(token-health): pin the real terminal-skip boundary, not the pre-exemption one (#11592)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:09:51 -03:00
Nguyen Thanh Dat
ff1ed20bb8 test(models): follow #11503's Gemini -high alias retarget (#11593)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:09:47 -03:00
Paco Cartones
5cc213e46b fix(dashboard): preserve combo success percentage scale (#11595)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:09:43 -03:00
solstxce
5d7d4cb953 fix(providers): route duckduckgo-web via duck.ai and self-heal stale model catalog (#11597)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:09:38 -03:00
Paco Cartones
bd4a7629b6 fix(ui): make console log controls accessible (#11599)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). Boarded no worktree combinado junto com outras ~30 PRs; validação única: typecheck/complexity/cognitive-complexity/changelog-integrity verdes, file-size rebaseado onde necessário (crescimento legítimo), lint com os mesmos 228 achados pré-existentes confirmados via sonda contra o tip puro (não introduzidos por este lote), e ~370 testes focados (unit + vitest) passando. Obrigado pela contribuição.
2026-08-26 08:09:34 -03:00
Meet shah
bfac589529 fix(autoCombo): lifecycle veto, deterministic capability merge, variant inheritance in models_dev_tier (#11508) (#11598)
Merged via /merge-batch (lote 2026-08-26, v3.8.51). As três correções mecânicas do #11508 aplicadas com clareza (veto de lifecycle, merge determinístico entre providers, herança de variante). Validado no worktree combinado: 5/5 testes focados passando, typecheck/complexity/changelog/file-size verdes (achados de lint pré-existentes confirmados via sonda contra o tip puro). Encontrei um bug real no próprio teste novo (profundidade de import relativo errada, `../../src/...` em vez de `../../../src/...`, causando ERR_MODULE_NOT_FOUND) e enviei a correção para o seu branch antes do merge — obrigado pela contribuição.
2026-08-26 08:09:21 -03:00
dependabot[bot]
e0ea3f92e1 deps: bump the development group across 1 directory with 8 updates (#11428)
Validated in a combined dependabot worktree off release/v3.8.51 tip alongside #11426 and #11440 — a fresh npm install of all three combined (2437 packages, 0 vulnerabilities) plus full-suite validation:
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:cycles — all OK, including through the @types/node 22→26 major jump
- npm run lint — 0 errors (after also draining an unrelated stale-suppressions cascade, see #11596)
- npm run test:vitest — 451/452 pass; the 1 failure (auto/glm materialization) is a pre-existing timing-flaky test, reproduced 11/11 pass ×3 in isolation, unrelated to this bump
- Node runtime unaffected — v24.16.0 unchanged, only the type definitions moved

8 development-group updates. The bun 1.3.14→1.4.0 + @types/bun bump aligns with the Bun-native infrastructure work merged earlier today (#11468/#11470/#11471/#11482), which was built against Bun 1.4+ assumptions.
2026-08-26 00:38:38 -03:00
dependabot[bot]
64ffddf5e5 deps: bump the production group across 1 directory with 11 updates (#11440)
Validated in a combined dependabot worktree off release/v3.8.51 tip alongside #11426 and #11428 — a fresh npm install of all three combined (2437 packages, 0 vulnerabilities) plus full-suite validation:
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:cycles — all OK
- npm run lint — 0 errors (after also draining an unrelated stale-suppressions cascade, see #11596)
- npm run test:vitest — 451/452 pass; the 1 failure (auto/glm materialization) is a pre-existing timing-flaky test, reproduced 11/11 pass ×3 in isolation, unrelated to this bump

11 production-group updates (aws-sdk bedrock-runtime, dompurify, fumadocs-core/ui, jose, lucide-react, marked, mermaid, next, onnxruntime-node, wreq-js), all patch/minor within their existing major lines.
2026-08-26 00:38:26 -03:00
dependabot[bot]
a9dd1dd0fe deps: bump electron from 43.4.0 to 43.4.1 in /electron (#11426)
Validated in a combined dependabot worktree off release/v3.8.51 tip alongside #11440 and #11428 — a fresh npm install of all three combined (2437 packages, 0 vulnerabilities) plus full-suite validation:
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:cycles — all OK
- npm run lint — 0 errors (after also draining an unrelated stale-suppressions cascade, see #11596)
- npm run test:vitest — 451/452 pass; the 1 failure (auto/glm materialization) is a pre-existing timing-flaky test, reproduced 11/11 pass ×3 in isolation, unrelated to this bump

Electron patch bump, upstream release notes list only crash fixes and stability backports.
2026-08-26 00:38:16 -03:00
Diego Rodrigues de Sa e Souza
f69cd9f3bd chore(quality): prune stale eslint-suppressions entries (#11596)
Verified in an isolated worktree off a fresh npm install: 228 → 0 lint errors, purely from removing the stale-suppression count-mismatch cascade. See PR body for the separate main-checkout node_modules finding.
2026-08-26 00:37:38 -03:00
Chewji
6eb7bf0ba9 fix(command-code): fallback to /alpha/generate for Go plan without Provider API access (#11455)
Validated in a combined sub-batch worktree off release/v3.8.51 tip. This PR's branch also carried ~88 already-merged commits from a stale rebase (phantom-diff); cherry-picked only the genuine value commit. That commit's own test file (command-code-executor.test.ts) predated #11421's async getExecutor() change and had 7 test failures from unresolved-Promise call sites (`.execute()` on a still-pending getExecutor() Promise, and in one case on execute() itself not being awaited) — fixed all 7 call sites to properly await both async calls, verified 16/16 pass, and pushed both the cherry-pick and the fix to this branch.
- Focused tests: command-code-executor.test.ts (16/16) + provider-validation-specialty.test.ts — 140/140 combined, part of sub-batch's full run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for tracing the Go-plan 403 to the v3.8.50 endpoint migration and building a clean fallback that preserves the new Provider-tier path while restoring CLI compatibility for Go plan.
2026-08-25 21:15:24 -03:00
adevwithpurpose
ae22c157f4 fix(ui): wrap quota card footer action buttons to prevent clipping Refresh button on narrow cards (#11464)
Validated in a combined sub-batch worktree off release/v3.8.51 tip. This PR's branch carried ~100 already-merged commits from a stale rebase (phantom-diff — every commit but the last matches history already on the release tip); cherry-picked only the genuine value commit (the flex-wrap fix itself) and pushed that to this branch.
- Focused tests: quota-card-expanded-footer-flex-wrap.test.ts, quota-card-expanded-sort-collapse.test.ts, quota-card-grid-mobile-7072.test.ts — part of sub-batch's 165/165 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for the clear root cause (extra View credits button + missing flex-wrap on the footer + overflow-hidden on the outer Card clipping the trailing Refresh now button).
2026-08-25 21:12:50 -03:00
Justin Hong
b84ae072ea fix(cli): write jcode settings as [providers.omniroute] in config.toml (#11484)
Validated in a combined sub-batch worktree off release/v3.8.51 tip. Its second commit reimplemented wsPath.ts's sanitizeLiveWsPort/resolveLiveWsUrl to fix a build break it hit — that exact break is already fixed on the current tip via #11502 (the original #11388 implementation restored verbatim). Conflicted against that; resolved by keeping the tip's established implementation and dropping the redundant reimplementation (both are functionally equivalent; the tip's carries the original #11331 doc comments and precedence contract). Pushed the same resolution to this branch.
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff
- Focused test: cli-settings-jcode.test.ts (integration) — part of sub-batch's 165/165 run

Thanks for the real end-to-end verification (production server, real ~/.jcode/config.toml, jcode --provider-profile omniroute serving a completion, jcode provider-doctor passing) — the managed-block approach (marker-delimited, preserves user-authored config, 409s instead of corrupting on a hand-written conflicting table) is exactly the right shape for this integration.
2026-08-25 21:11:50 -03:00
KaspaPulse
be6cbe7de5 fix(sessions): preserve legacy data when exclusive projection fails (#11469)
Validated in a combined sub-batch worktree off release/v3.8.51 tip.
- Focused test: exclusive-session-observability.test.ts — part of sub-batch's 165/165 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for the narrow failure boundary and the privacy-conscious warning (proven not to leak the caught error's sensitive fields) — a projection failure discarding valid legacy data was a real regression from #11389.
2026-08-25 21:08:29 -03:00
Syed Raheemuddin
721ee2a038 refactor(local-corpus): implement dynamic root resolution and LRU cache (#11491)
Validated in a combined sub-batch worktree off release/v3.8.51 tip. Also removed an unused variable (idx2) from the new test — pushed to this branch.
- Focused test: local-corpus-lru-cache.test.ts — 4/4 pass, part of sub-batch's 165/165 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff (after the idx2 fix)

Thanks for the LRU cache and path-traversal guard — preventing an unconfigured workspace path from indexing system root is a real safety improvement.
2026-08-25 21:08:05 -03:00
Nguyễn Viết Tuấn
892f359305 build(bun): allow Turbopack bundler flag on Bun 1.4+ with configurable Webpack fallback (#11471)
Validated in a combined 4-PR batch worktree off release/v3.8.51 tip (last of the Bun-native cluster; conflicted against the already-merged #11482's Dockerfile.bun hunk in the shared worktree — resolved by taking this PR's configurable ARG/ENV shape, which is exactly what it's designed to replace, and pushed the same resolution to this branch).
- Focused test: resolve-next-build-bundler-flag.test.mjs — 3/3 pass, part of batch's 5/5 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for validating with both node --test and bun test — good practice given the dual-runtime surface this touches.
2026-08-25 20:35:41 -03:00
Nguyễn Viết Tuấn
7b7196f05d fix(docker-bun): strip Node SQLite addon from runtime (#11482)
Validated in a combined 4-PR batch worktree off release/v3.8.51 tip (complements #11468 and #11470, both merged first). Conflicted against #11470's Dockerfile.bun hunk in the shared worktree — resolved additively (both the ownership hardening and the addon-stripping RUN block coexist, ordered so the strip runs as root before USER bun) and pushed the same resolution to this branch.
- Focused test: bun-runtime-native-addon.test.mjs — 1/1 pass, part of batch's 5/5 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for the isolated-probe root-causing (better-sqlite3 specifically, ruling out keytar/onnxruntime-node/sqlite-vec/tls-client-node/wreq-js/sharp) plus the production ARM64 evidence.
2026-08-25 20:34:05 -03:00
Nguyễn Viết Tuấn
a8f9024c20 fix(docker-bun): make Bun image install and SQLite startup reliable (#11470)
Validated in a combined 4-PR batch worktree off release/v3.8.51 tip (Bun-native SQLite infrastructure cluster; complements #11468 already merged).
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK (Docker build itself not executed in this environment; reviewed the Dockerfile.bun diff for correctness)
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for the two concrete failure modes fixed (missing postinstall.mjs during layer-cached bun install, ARM64 NAPI crash avoided by using the native bun:sqlite smoke check instead of rebuilding better-sqlite3) plus the non-root USER bun hardening.
2026-08-25 20:31:57 -03:00
Nguyễn Viết Tuấn
9ad90fe7a3 fix(bun): use native bun:sqlite during startup to avoid N-API crash (#11468)
Validated in a combined 4-PR batch worktree off release/v3.8.51 tip (Bun-native SQLite infrastructure cluster from the same contributor).
- Focused test: bunSqliteAdapter.test.ts — part of batch's 5/5 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for tracing this to the pre-boot better-sqlite3 require — a native NAPI abort that JS try/catch cannot recover from is exactly the kind of failure mode that needs the guard moved earlier, and aligning bootstrap/sync-env with the already-preferred bun:sqlite driver is the right fix.
2026-08-25 20:31:34 -03:00
Markus Hartung
3f6a881b6c fix(logging): raise chat-log array truncation cap to 1000 and unify duplicate implementations (#11499)
Validated in a combined 2-PR batch worktree off release/v3.8.51 tip (companion fix to #11473, merged first).
- Focused tests: chat-log-array-tail-items-default, chatcore-log-truncation, request-logger-bounded-clone, request-logger-bounded-idempotence, repro-7847-bound-client-raw-request — part of batch's 46/46 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for unifying the two independently-drifted truncation caps onto one configurable source — measured evidence that the storage ceiling comes from retention days, not the per-item cap, makes the 128→1000 raise a clear correctness improvement.
2026-08-25 20:11:56 -03:00
Markus Hartung
fff62f10a7 fix(responses-continuation): fail closed on a log-truncated stored input/output array (#11473)
Validated in a combined 2-PR batch worktree off release/v3.8.51 tip.
- Focused test: responses-continuation-store.test.ts — part of batch's 46/46 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for the live-verified root cause — a truncation sentinel getting forwarded upstream as a real Responses-API item, breaking the turn with a genuine 400, is exactly the kind of defect that's easy to miss without production traffic to reproduce against.
2026-08-25 20:11:46 -03:00
Dizzle
d3c395bbcf fix(free-tier): serve the Radar overlay from /api/free-tier/summary (#11550)
Validated in a combined 4-PR batch worktree off release/v3.8.51 tip. Also removed an unused `crypto` import from the new test file (one-line lint fix, 228→229 unrelated-drift comparison confirmed it was the only new finding) — pushed to this branch.
- Focused tests: free-tier-summary-radar-overlay.test.ts (9/9) + free-model-catalog/free-catalog-2026-07-expansion/free-providers-batch-2026-07 — part of batch's 60/60 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:docs-counts-sync — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff (after the crypto-import fix)

Thanks for this — the community/live feed entitlement distinction (never re-publishing paid feed content to anonymous callers) mirrors #9686's treatment carefully, and the catalogUpdatedAt honesty (null over a fabricated download-time stand-in) is the right call.
2026-08-25 19:49:00 -03:00
Dizzle
3863dab149 fix(chat): stop forwarding redundant provider-node routing segments to model lookup (#11557)
Validated in a combined 4-PR batch worktree off release/v3.8.51 tip.
- Focused test: model-connid-prefix-normalization-6772.test.ts — part of batch's 60/60 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:docs-counts-sync — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for closing this with production-log-shaped test cases — a deterministic upstream 404 loop from a duplicated routing segment is exactly the kind of defect that's easy to miss without real traffic shapes in the test suite.
2026-08-25 19:48:49 -03:00
Dizzle
ffd8984a59 docs(routing): LKGP sticks at provider level — align copy with routerStrategy contract (#11555)
Validated in a combined 4-PR batch worktree off release/v3.8.51 tip. Also removed a leftover changelog placeholder duplicate (0000-lkgp-doc-provider-stickiness.md, byte-identical content to the correctly-numbered 11555- fragment minus the PR link) — pushed to this branch.
- Focused test: router-strategies.test.ts — part of batch's 60/60 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:docs-counts-sync — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for the docs-accuracy follow-through — aligning the LKGP copy with what routerStrategy.ts actually does (provider-level, not target/model) closes a real gap between prose and behavior.
2026-08-25 19:48:40 -03:00
Dizzle
6787fc9aa9 docs: real PR links for merged changelog fragments; fix stale quality comment (#11553)
Validated in a combined 4-PR batch worktree off release/v3.8.51 tip.
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:docs-counts-sync — all OK
- Comment-only + changelog metadata fix, no runtime surface

Thanks for closing the placeholder-link loop before the release aggregator baked them into CHANGELOG.md — good timing call in the PR notes.
2026-08-25 19:48:29 -03:00
Bob.Hou
64a28b559c fix(combo): enable genuine quota-aware routing for generic providers (antigravity, claude, etc.) (#11411)
Validated in a combined 5-PR batch worktree off release/v3.8.51 tip.
- Focused test: universal-quota-aware-routing.test.ts — part of batch's 115/115 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for closing the gap where reset-aware/reset-window/headroom strategies were silently degenerating to round-robin for generic providers because the fetcher registry was never populated at startup — a subtle but real routing-quality regression.
2026-08-25 19:25:57 -03:00
Bob.Hou
98cec759ae fix(oauth): allow expired token retry before deactivation and activate expired retry loop (#P0) (#11414)
Validated in a combined 5-PR batch worktree off release/v3.8.51 tip.
- Focused tests: token-health-check-retry-deactivation.test.ts + token-health-check-kimi.test.ts + cursor-renewal.test.ts — part of batch's 115/115 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for restoring the retry-budget gate before deactivation — premature deactivation on a single transient refresh failure is a real P0-class defect for OAuth-connected accounts.
2026-08-25 19:25:48 -03:00
Bob.Hou
62b3f9d36d perf(core): eliminate async waterfalls across home, cache, and db operations (#11396) (#11512)
Validated in a combined 5-PR batch worktree off release/v3.8.51 tip.
- Focused test: perf-waterfall-elimination.test.ts — part of batch's 115/115 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for parallelizing these independent DB/settings reads — straightforward, low-risk perf hygiene with parity tests.
2026-08-25 19:25:38 -03:00
Bob.Hou
891c1af0ea fix(providers): remove duplicate 128-tool truncation in OpencodeExecutor (#11444) (#11518)
Validated in a combined 5-PR batch worktree off release/v3.8.51 tip (opencode.ts overlapped with already-merged #11409 — git auto-merged cleanly, no manual resolution needed).
- Focused test: opencode-tools-no-truncation.test.ts — part of batch's 115/115 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for catching the leftover duplicate truncation from #6193 — a silent 128-tool cap breaking subagent execution on oc/* models is a nasty one to trace back.
2026-08-25 19:25:28 -03:00
Bob.Hou
1ad06d2059 fix(translator): preserve exact tool name casing for Claude tool_use payloads (#11487) (#11520)
Validated in a combined 5-PR batch worktree off release/v3.8.51 tip.
- Focused test: claude-tool-name-casing.test.ts — part of batch's 115/115 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for tracing this to the REVERSE_MAP fallback — a client-dispatch-breaking casing bug is exactly the kind of thing that's easy to miss without a targeted test.
2026-08-25 19:25:18 -03:00
Webman
0023a9ec04 fix: make release/v3.8.50 CI gates green (run 32786966560 root causes) (#11450)
Validated in a combined 3-PR batch worktree off release/v3.8.51 tip. This PR conflicted against today's accumulated merges (mostly pure provider-count drift: 353 vs its 352 snapshot across 51 docs/i18n/SVG files — resolved to the release's current 353, confirmed byte-identical besides the count on diff). Two real code conflicts:
- src/lib/usage/providerLimits.ts: this PR's `syntheticCooldownOutlivedByRealWindows()` is genuinely new (didn't exist on the tip; a caller already referencing it elsewhere in the file confirmed it was required) — kept in full.
- tests/unit/providers-constants-split.test.ts: both sides' running-count comments land at the same 233 via different additions (this PR's volcengine-agent/coding-plan vs the v3.8.50 back-merge's Synthetic + Kilo Gateway, both already present in providers.ts) — combined as sequential history, no functional change.

Resolution pushed to the PR branch and re-validated:
- Focused tests: 8134-github-t5-fallback-filter, cc-compatible-provider, cli-oneproxy-commands, hard-session-lease-bypass-inventory, llm-selector-custom-vision-models, model-capabilities-registry, openapi-coverage, provider-limits-recovery, providers-constants-split, repro-glm-iso-reset-24h-cap, startup-stale-cooldown-recovery, memory-pipeline, security-hardening, skills-pipeline — part of batch's 165/165 node:test run; glmCodingProviderConfig.test.ts (vitest) 10/10
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:docs-counts-sync — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for this — root-causing all 18 failed jobs from a single CI run with gate-by-gate evidence (including the harder-to-spot ones like the antigravity BYOP legacy-ack misread and the reserved-alias `cc` guard) is exactly the kind of base-red drain this release needs.
2026-08-25 18:55:18 -03:00
Webman
9862f129e2 fix(electron): make the packaged Windows build pass the #7592 cold-restart smoke (#11443)
Validated in a combined 3-PR batch worktree off release/v3.8.51 tip.
- Focused test: electron-smoke-script.test.ts — part of batch's 165/165 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:docs-counts-sync — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Real hardware validation on a fresh packaged Windows build (Hard Rule #18) surfacing and fixing 5 genuine defects (GNU-tar drive-letter parsing, missing asar file, electron-builder's node_modules extraResources drop, USERPROFILE-derived userData path, unreachable driver-log assertion) is exactly the kind of investigation this repo needs more of. Thank you.
2026-08-25 18:54:20 -03:00
Webman
700819a29b fix(ci): boot protocol E2E on the peer-stamped custom server with preserved open bootstrap (#11535) (#11549)
Validated in a combined 3-PR batch worktree off release/v3.8.51 tip.
- Focused test: protocol-e2e-server-stamping-11535.test.ts — part of batch's 165/165 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:docs-counts-sync — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for the meticulous root-causing here — three distinct issues (server flavor, HOST pin, open-bootstrap env leak) traced to exact line numbers with live-boot before/after evidence.
2026-08-25 18:54:09 -03:00
Paijo
7cfabfc5c9 perf(executors): lazy-load the executor registry — defer class imports + construction to first use (#11220) (#11421)
Validated in a combined 3-PR batch worktree off release/v3.8.51 tip (a sibling PR from the same author, #11495, was held out — a typecheck error in zai-web.ts only reproduced with this PR + #11495 boarded together, and cleared without #11495; isolated this PR alone confirmed clean on its own too, so the interaction belonged to #11495's side — see its comment).
- Golden lock: executor-map-golden.test.ts — passes byte-identical (same keys, classes, provider identities, dispatch guards)
- Focused tests part of batch's 94/94 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for the measured, careful methodology here — the golden-lock contract plus the isolated DATA_DIR benchmarking make this an easy PR to trust despite the wide surface (72 files).
2026-08-25 18:22:46 -03:00
Paijo
026d26edb7 feat(providers): derive + surface expiry for JWT-bearing web cookies (#11497) (#11505)
Validated in a combined 3-PR batch worktree off release/v3.8.51 tip (a sibling PR from the same author, #11495, was held out — see its own comment for the isolated finding, unrelated to this diff).
- Focused test: web-cookie-expiry.test.ts — part of batch's 94/94 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for closing a real trust gap — operators deserve to know a cookie is about to expire before a live request fails.
2026-08-25 18:22:34 -03:00
Paijo
8a8d0cf336 fix(providers): stop silently dropping reasoning effort on opencode families (#10788) (#11409)
Validated in a combined 3-PR batch worktree off release/v3.8.51 tip (a sibling PR from the same author, #11495, was held out after an interaction-only typecheck error was isolated to it — reproduced clean without it, see #11495's own comment).
- Focused tests: opencode-go-effort-aliases-6922.test.ts, opencode-go-effort-aliases-8353.test.ts, chatcore-upstream-body.test.ts — part of batch's 94/94 node:test run
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: 228 pre-existing dashboard react-hooks/* findings, unrelated to this diff

Thanks for tracing this all the way to the wire format — forwarding the aliased id verbatim instead of injecting a field the non-DeepSeek families never had is exactly the right fix.
2026-08-25 18:22:23 -03:00
Dizzle
ee4e37154d feat(rankings): show what each provider actually served (#11546)
Validated in a combined 3-PR batch worktree off release/v3.8.51 tip.
- Focused tests, run with the correct vitest config (tests/unit/ui/*.tsx needs `--config vitest.config.ts`, not node:test — my invocation error, not the PR's): free-provider-rankings-page-usage.test.tsx + free-provider-rankings-page-authtype-6915.test.tsx — 9/9 pass; freeProviderRankings-usage-display.test.ts — pass
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK
- Full-repo lint: one flagged line in this file (91:5, react-hooks/set-state-in-effect on the mount-time fetchRankings() call) confirmed pre-existing and untouched by this diff — this PR's changes are confined to the fetch body's URL params and the new table column

Thanks for closing a real trust gap — an ELO-only ranking calling a 100%-error provider "healthy" is exactly the kind of thing a reliability column should catch, and the no-data-vs-0% distinction is the right call.
2026-08-25 16:31:11 -03:00
Dizzle
60eb0806df chore(free-models): derive the free-tier regime sets from the regime table (#11537)
Validated in a combined 3-PR batch worktree off release/v3.8.51 tip.
- Focused tests: free-regime-traits-derived-sets.test.ts, free-model-catalog.test.ts — pass; vitest autoCombo suite 108/111 (3 pre-existing timing-flaky failures unrelated to this diff, reproduced identically on the pure release/v3.8.51 tip in an isolated probe — auto/glm and Cerebras-rotation timeouts, none of the files this PR touches)
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK

Thanks for collapsing the four duplicated regime answers into one table-driven source — the `satisfies Record<...>` trick turning a missing answer into a compile error is a nice touch.
2026-08-25 16:30:59 -03:00
Dizzle
a63b3e21b9 fix(docs): Auto-Combo factor count is read from DEFAULT_WEIGHTS (#11545)
Validated in a combined 3-PR batch worktree off release/v3.8.51 tip. The prerequisite sibling (159→160 migrations) was already covered by #11502 — closed the redundant #11543 separately.
- New check:docs-counts gate: proven fail-before/pass-after per the PR's own methodology, re-verified here (PASS, 2 unrelated soft-drift notices on cloud-agent/A2A doc counts, non-blocking)
- Focused tests: check-docs-counts-sync.test.ts, combo-matrix/auto.test.ts, lkgp-enabled-context-11181.test.ts — pass
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity — all OK

Thanks for replacing seventeen hand-maintained factor-count claims with one source-derived gate.
2026-08-25 16:30:49 -03:00
MumuTW
ae7a843e86 fix(autoCombo,sse): catalog hygiene — retire dead FITNESS_TABLE rows, fix 7 BUILT_IN_ALIASES targets, add model-lifecycle gate (#11503) (#11507)
Validated in a combined 4-PR batch worktree off release/v3.8.51 tip. This PR's diff overlapped taskFitness.ts and autoCombo.test.ts with the already-merged #11492/#11506 — git's merge auto-resolved both hunks cleanly (non-overlapping layers: #11492/#11506 touch layer 2 arena lookup, this PR touches layer 4 static-table hygiene); verified no conflict markers remained and re-ran the full suite after boarding.
- npm run check:model-lifecycle — PASS, 68 retired ids, 1327 catalog ids, 0 violations (re-ran with the correct `node --import tsx/esm` loader after an initial bare-node invocation mistakenly failed on path-alias resolution — that was my invocation error, not the gate)
- Focused tests: fitness-table-hygiene-11503.test.ts, taskFitness-pattern-order-8603.test.ts, model-deprecation-aliases-11503.test.ts, check-model-lifecycle-gate.test.ts, model-deprecation.test.ts, autoCombo.test.ts — part of batch's 126/126 vitest + 246/246 node:test runs
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:cycles — all OK
- Full-repo lint: 228 problems remaining, all pre-existing dashboard react-hooks/* findings unrelated to this diff (zero errors in any file this PR touches)

Thanks for this — genuinely thorough methodology (segment-boundary matching, provider-scoped alias guard, offline lifecycle gate with a documented burn-down list for the 6 remaining catalog offenders).
2026-08-25 13:52:23 -03:00
MumuTW
a15af27c78 fix(intelligence): synthesize base-model arena rows from effort/harness variants; drop MODEL_ALIAS_MAP (#11504) (#11506)
Validated in a combined 4-PR batch worktree off release/v3.8.51 tip (stacked on #11492, merged first).
- TDD-first: the new base-model-synthesis describe block failed 5/5 pre-fix, passes now
- Focused test: tests/unit/arena-elo-sync.test.ts — 56/56 pass, part of batch's 246/246 node:test + 126/126 vitest runs
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:cycles — all OK

Thanks for closing the arena-lookup gap for harness/effort-annotated leaderboard rows and retiring MODEL_ALIAS_MAP's cross-generation score copying in favor of scoresAs + registry-owned aliases.
2026-08-25 13:51:56 -03:00
MumuTW
78d10da84c fix(autoCombo): inherit task fitness from base model for effort/alias variants (#11489) (#11492)
Validated in a combined 4-PR batch worktree off release/v3.8.51 tip.
- Focused tests: scoresAs-11489.test.ts + task-fitness-scores-as-11489.test.ts + autoCombo.test.ts — pass as part of batch's 126/126 vitest + 246/246 node:test runs
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:cycles — all OK

Thanks for closing the gap where effort/alias variants fell back to the wildcard score instead of inheriting their base model's task fitness.
2026-08-25 13:51:27 -03:00
MumuTW
17e4ddfc77 chore(release): clear release/v3.8.51 base-red gates — docs count, stryker list, lockfile host, stale suppressions, 7 lint regressions (#11502)
Validated in a combined 4-PR batch worktree off release/v3.8.51 tip.
- Every fix individually confirmed against the pristine tip, no runtime behavior change
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity, check:cycles — all OK
- Full-repo lint: 503 → 228 problems, confirming this PR's diagnosis of the exit-2 stale-suppressions + orphaned-code causes; the remaining 228 are pre-existing dashboard react-hooks/* findings this PR never claimed to touch
- node --test tests/unit/combo-routing-engine.test.ts, providers-constants-split.test.ts, and the providerLimits/videoBridge importers — all pass as part of the batch's 246/246 node:test run

Thanks for the meticulous base-red triage — this directly explains and fixes the largest lint-drift finding from the prior merge-batch session.
2026-08-25 13:51:18 -03:00
Paco Cartones
28601b456e fix(relay): strip unsafe forwarded headers (#11533)
Validated in a combined 10-PR batch worktree off release/v3.8.51 tip.
- Focused test: tests/unit/generated-relay-header-denylist.test.ts — 3/3 contract pass plus 30/30 related SSRF tests
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- Full-repo lint: 503 pre-existing problems confirmed identical on the pure release/v3.8.51 tip — unrelated to this diff

⚠️ base-red inherited: #11449

Thanks for applying one canonical header denylist across the generated Cloudflare/Vercel/Deno relays so hop-by-hop, framing, and proxy-auth/relay-control headers stop leaking upstream.
2026-08-25 13:12:50 -03:00
Paco Cartones
436ce4869f fix(tailscale): validate ports and quote MSI paths (#11534)
Validated in a combined 10-PR batch worktree off release/v3.8.51 tip.
- Focused test: tests/unit/tailscale-validation.test.ts — 2/2 pass plus 13/13 related Tailscale tests
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- Full-repo lint: 503 pre-existing problems confirmed identical on the pure release/v3.8.51 tip — unrelated to this diff

⚠️ base-red inherited: #11449

Thanks for rejecting out-of-range Tailscale ports and escaping apostrophes before they reach the Windows MSI installer PowerShell command.
2026-08-25 13:12:38 -03:00
Paco Cartones
e48ffd38d3 fix(authz): restrict tunnel process routes locally (#11531)
Validated in a combined 10-PR batch worktree off release/v3.8.51 tip.
- Focused tests: tests/unit/authz/route-guard-tunnel-processes-local-only.test.ts + tests/unit/authz/spawn-capable-prefixes-client-safe.test.ts — 6+ pass
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- Full-repo lint: 503 pre-existing problems confirmed identical on the pure release/v3.8.51 tip — unrelated to this diff

⚠️ base-red inherited: #11449

Thanks for closing the process-spawning tunnel routes to local-only (Hard Rule #15/#17 territory) while preserving authenticated remote read access to status endpoints.
2026-08-25 13:12:34 -03:00
Paco Cartones
30026b2e96 fix(idempotency): fingerprint Responses request semantics (#11532)
Validated in a combined 10-PR batch worktree off release/v3.8.51 tip.
- Focused test: tests/unit/idempotency-fusion-collision.test.ts — 8/8 pass
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- Full-repo lint: 503 pre-existing problems confirmed identical on the pure release/v3.8.51 tip — unrelated to this diff

⚠️ base-red inherited: #11449

Thanks for closing the idempotency-collision gap between unrelated Responses requests.
2026-08-25 13:12:18 -03:00
Paco Cartones
3804ffb6ff fix(router): preserve selected connection identity (#11530)
Validated in a combined 10-PR batch worktree off release/v3.8.51 tip.
- Focused test: tests/unit/router-strategies.test.ts — 22/22 pass
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- Full-repo lint: 503 pre-existing problems confirmed identical on the pure release/v3.8.51 tip — unrelated to this diff

⚠️ base-red inherited: #11449

Thanks for carrying the winning connectionId through cost/latency/SLA/LKGP so duplicate accounts dispatch through the connection actually ranked.
2026-08-25 13:12:15 -03:00
Paco Cartones
eb9b4cec54 fix(ci): skip stale release Docker publishes (#11527)
Validated in a combined 10-PR batch worktree off release/v3.8.51 tip. Fixes #11523.
- Focused test: tests/unit/build/docker-next-channel-8576.test.ts — 7/7 pass
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- Full-repo lint: 503 pre-existing problems confirmed identical on the pure release/v3.8.51 tip — unrelated to this diff

⚠️ base-red inherited: #11449

Thanks for treating Docker publishes from non-default frozen release branches as an expected no-op.
2026-08-25 13:12:02 -03:00
Paco Cartones
57461af5cf fix(duckduckgo): preserve streamed chunk boundaries (#11528)
Validated in a combined 10-PR batch worktree off release/v3.8.51 tip.
- Focused test: tests/unit/duckduckgo-stream-chunks.test.ts — 2/2 pass
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- Full-repo lint: 503 pre-existing problems confirmed identical on the pure release/v3.8.51 tip — unrelated to this diff

⚠️ base-red inherited: #11449

Thanks for keeping the streaming decoder/line-buffer intact across DuckDuckGo transport chunk boundaries.
2026-08-25 13:11:58 -03:00
Paco Cartones
1a8c6d13a1 fix(responses): preserve json_object response format (#11529)
Validated in a combined 10-PR batch worktree off release/v3.8.51 tip.
- Focused test: tests/unit/translator-openai-responses-req.test.ts — 58/58 pass
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- Full-repo lint: 503 pre-existing problems confirmed identical on the pure release/v3.8.51 tip — unrelated to this diff

⚠️ base-red inherited: #11449

Thanks for restoring json_object symmetry between the Chat Completions and Responses translators.
2026-08-25 13:11:45 -03:00
Paco Cartones
987b67420a fix(kimi-web): align health probe with executor domain (#11521)
Validated in a combined 10-PR batch worktree off release/v3.8.51 tip. Fixes #11515.
- Focused test: tests/unit/kimi-web-validation-11515.test.ts — 37/37 pass; live unauthenticated probe confirms www.kimi.ai/api/user returns the expected 401 boundary
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- Full-repo lint: 503 pre-existing problems confirmed identical on the pure release/v3.8.51 tip — unrelated to this diff

⚠️ base-red inherited: #11449

Thanks for aligning the health probe with the executor's actual domain plus the live verification.
2026-08-25 13:11:41 -03:00
Paco Cartones
a8dbf7bbb8 fix(cli): preserve existing admin password during setup (#11522)
Validated in a combined 10-PR batch worktree off release/v3.8.51 tip. Fixes #11494.
- Focused test: tests/unit/cli-setup-command.test.ts — 10/10 pass
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- Full-repo lint: 503 pre-existing problems confirmed identical on the pure release/v3.8.51 tip (isolated probe) — unrelated to this diff (bin/cli only)

⚠️ base-red inherited: #11449

Thanks for preventing INITIAL_PASSWORD from silently overwriting an operator's already-set admin password.
2026-08-25 13:11:28 -03:00
Diego Rodrigues de Sa e Souza
a179ffed5b feat(resilience): add hierarchical concurrency admission (#11493)
Cherry-pick of the 3 value commits from #11323 (by @RaviTharuma), dropping 17 already-merged rebase-baggage commits. Validated in a combined-batch worktree off release/v3.8.51 tip:
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- Focused tests, isolated re-run flake-free: accountSemaphore.test.ts 11/11, chatcore-hierarchical-admission.test.ts 2/2, resilience-settings-provider-quota-overrides.test.ts 12/12, i18n-vi-completeness.test.ts 5/5
- lint clean once isolated from the unrelated ESLint-10 suppressions regression carried by a separate PR in the batch

Closes #7778. Full credit to @RaviTharuma for the design and implementation.
2026-08-25 07:19:09 -03:00
Nguyen Thanh Dat
23fa2709a9 fix(db): keep tokenExpiresAt when a connection is created (#11368)
Validated in a combined-batch worktree off release/v3.8.51 tip alongside #11259 and the cherry-picked #11323 successor (#11493):
- Focused test: tests/unit/oauth-connection-tokenexpiresat-5326.test.ts — 3/3 pass, exercises the round-trip through createProviderConnection/getProviderConnections
- typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity gates — all OK
- One-string allowlist fix, TDD-proven (fails on base with tokenExpiresAt: null, passes with the change), mutation-checked

Thanks for restoring #5326's fix end to end — clean, minimal, well-tested.
2026-08-25 07:18:58 -03:00
Paijo
6435f618f4 fix(quota-share): release the winner's reserved in-flight slot (#11371) (#11408)
Merged into release/v3.8.51. Batch review caught that the slot-release replaced the #5923 recordComboFailure call on the no-executable-targets path (pin auto-clear would freeze); restored both effects side by side + regression guard in combo-routing-engine.test.ts (proven RED without the fix, GREEN after — 211/211 across the focused combo/quota/opencode battery, quota-share-strategy 31/31 on the final branch head). Thanks @oyi77!
2026-08-25 04:14:10 -03:00
Praveen K Palaniswamy
b39e5ecb20 feat(routing): subscription-first auto groupings (auto/subscription, auto/thrifty) [defer to 3.8.51] (#11146)
Merged into release/v3.8.51 via batch validation: subscription-ladder + free-regime vitest suites green (32/32) on the combined tree, check:provider-consistency OK (353 canonical providers), static gates green (virtualFactory.ts frozen at merge size with dated rebaseline). Also pushed a docs commit marking rungBudgetUsd as not-yet-enforced per review, and synced the branch onto the updated release tip. Strong opt-in design failing closed where money is involved — thanks @yourspraveen!
2026-08-25 01:44:24 -03:00
Burak Bayır
a0ceccc6f0 feat(search): add Xquik X search provider (#11370)
Merged into release/v3.8.51 via batch validation: xquik provider suites green on the combined tree (193 node:test assertions incl. your 7 new cases), check:provider-consistency OK (353 canonical providers), static gates green. Well-scoped fallbackOnly X-provider with clean citation building — thanks @kriptoburak!
2026-08-25 01:39:39 -03:00
Tuan Dinh
14ca809924 fix(providers): send Responses API payload during OpenAI-compatible validation (#11454)
Merged into release/v3.8.51 via batch validation: provider-validation-specialty suite green on the combined tree (193 node:test assertions across the batch's focused files), static gates green. Right fix for the Responses-API probe body (#11453) — thanks @tuandinh0801!
2026-08-25 01:39:19 -03:00
KaspaPulse
c8ca024e29 feat(dashboard): surface exclusive managed leases in Sessions view (#11389)
Merged into release/v3.8.51 via batch validation: exclusive-session-observability unit+UI suites green on the combined tree, static gates green. Nice additive observability layer over the #10362 lease backend — thanks @KaspaPulse!
2026-08-25 01:38:59 -03:00
Aman
613fc71e98 feat(providers): publish web-session credential contract (#11340)
Merged into release/v3.8.51 via batch validation: node:test web-session-contract suite green on the combined tree, static gates green (file-size/complexity/cognitive/changelog/typecheck). Clean credential-contract surface — thanks @Zartharas!
2026-08-25 01:38:39 -03:00
Dizzle
c472dbccc4 fix(free-models): stop reporting discontinued Pollinations models as free (#11441)
Merged into release/v3.8.51 via batch validation (combined tree): vitest autoCombo suite 32/32 incl. free-regime-not-read-by-predicate, static gates green (file-size / complexity / cognitive / changelog-integrity / typecheck:core). Compiler-checked FREE_REGIME_TRAITS table eliminating the discontinued-as-free routing bug — excellent work, thanks @maxmad64bis!
2026-08-25 01:37:45 -03:00
Diego Rodrigues de Sa e Souza
d82b68274c fix(sse): exact-domain cookie match and origin-equality URL assertions (#11452)
Clears CodeQL js/incomplete-url-substring-sanitization alerts #860-#865:

- volcengineConsoleAutoLogin: cookie domain filter now uses an exact/
  dot-suffix helper (isVolcengineCookieDomain) instead of substring
  includes(), rejecting look-alike hosts like volcengine.com.evil.test
- security-s1-s2-s4 tests: agent-card/agent.json URL assertions compare
  parsed origin equality instead of startsWith prefix

Co-authored-by: Markus Hartung <mail@hartmark.se>
2026-08-24 23:46:45 -03:00
Dizzle
943b9aaa84 fix(cli): flag a .env that lives inside the installed package (#11437)
Retargetado para release/v3.8.51 (release/v3.8.50 está congelada — freeze issue #11439). Resolvido o mesmo conflito não-relacionado em src/shared/utils/wsPath.ts (mesma causa do #11436 — refactor já mergeado na branch depois do fork deste PR; o diff real deste PR — bin/cli/utils/volatileEnvPath.mjs + bin/omniroute.mjs — ficou intacto) e revalidado: typecheck:core limpo, 12/12 testes focados passando.

Companion do #11436, decisão pura testável isoladamente, sem mudança de comportamento fora do caso volátil. Obrigado pela contribuição!
2026-08-24 20:10:08 -03:00
Dizzle
6e8fc94732 fix(cli): stop pre-filling the secrets the server owns (#11436)
Retargetado para release/v3.8.51 (release/v3.8.50 está congelada — freeze issue #11439). Resolvido um conflito de merge não-relacionado em src/shared/utils/wsPath.ts (originado de um refactor já mergeado nessa branch depois do fork deste PR; o diff real deste PR — scripts/dev/sync-env.mjs + tests/unit/sync-env.test.ts — ficou intacto) e revalidado: typecheck:core limpo, 13/13 testes focados passando.

Segue o precedente correto do #1622 (STORAGE_ENCRYPTION_KEY) para os dois secrets restantes que a postinstall preenchia por engano, defeituando o mecanismo de ensureSecrets(). Obrigado pela contribuição!
2026-08-24 20:04:11 -03:00
Xiangzhe
66ecc09050 chore(release): restore the living [3.8.51] CHANGELOG section
The cycle-open commit's root CHANGELOG hunk was lost in the rebase onto the
branch tip (the 42 i18n mirrors kept theirs, so the root and the mirrors had
drifted apart). Re-inserts the section with the three canonical headings.
2026-08-24 20:00:10 -03:00
Xiangzhe
65a1808f84 chore(release): open v3.8.51 development cycle
Completes the 0a.0b cut for the parallel-cycle model: the branch already existed
(cut from the v3.8.50 tip) but had never been bumped. Bumps package.json x3,
openapi.yaml and the lockfile, adds the living [3.8.51] CHANGELOG section with
the three canonical headings so aggregate-changelog.mjs cannot mis-target an
older published section, and syncs the 42 i18n mirrors.
2026-08-24 19:59:24 -03:00
Dizzle
a166752138 fix(radar): keep the feed's build date in the catalog cache (#11435)
Retargetado para release/v3.8.51 (release/v3.8.50 está congelada — freeze issue #11439). Validado em lote combinado (batch-0824h2) contra o tip de release/v3.8.51: typecheck:core limpo, gates estáticos + migration-numbering OK, 127/127 testes focados passando (8/8 do PR entre migration-163 e radar-feed-cache-generated-at).

Migração limpa (ADD COLUMN nullable, sem backfill necessário), aditiva na API, mantém "unknown" honesto para linhas antigas. Obrigado pela contribuição!
2026-08-24 19:57:24 -03:00
Markus Hartung
04dba0460e fix(responses-continuation): recover a real id/output for passthrough and translate-mode replies (#11434)
Retargetado para release/v3.8.51 (release/v3.8.50 está congelada — freeze issue #11439). Validado em lote combinado (batch-0824h2, junto de #11435/#11436/#11437) contra o tip de release/v3.8.51: typecheck:core limpo, gates estáticos OK, 127/127 testes focados passando.

Investigação sólida com repro real via container isolado, três causas independentes identificadas e corrigidas com testes de regressão dedicados para cada uma. Obrigado pela contribuição!
2026-08-24 19:57:12 -03:00
955 changed files with 51885 additions and 5986 deletions

View File

@@ -403,8 +403,17 @@ ALLOW_API_KEY_REVEAL=false
# OMNIROUTE_CHAT_LARGE_BODY_BYTES=262144
# Actual-byte hard cap enforced during bounded ingestion. Default 52428800 (50 MB).
# OMNIROUTE_CHAT_HARD_MAX_BODY_BYTES=52428800
# Maximum heavyweight requests simultaneously admitted in one process. Default 1.
# Legacy request-COUNT cap (#503-fanout). Now binds only when explicitly set here —
# left unset, heavyweight admission is gated by OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES below
# instead (an auto-derived byte budget), fixing coding-agent fan-out (multiple
# subagents/CLIs) collapsing to an effective concurrency of ~1 and 503ing.
# OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT=1
# Override for the auto-derived ingest byte budget (#503-fanout). Default: 25% of the
# process's effective memory ceiling (V8 heap limit, or the tighter cgroup/container
# limit) divided by an 8x transient-amplification factor, clamped between 8 MiB and
# 2 GiB; explicit overrides are clamped to the same safe range. Read
# chatAdmission.maxInflightBytes/budgetSource at /api/monitoring/health before overriding.
# OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES=134217728
# Heap-pressure shed ratio (heapUsed/heap_size_limit) for the structural admission gate
# (#10183, #10268): a second concurrent heavyweight request past OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT
# is only shed with a retryable 503 when the heap is ALSO under this much pressure — on a
@@ -916,6 +925,11 @@ NEXT_PUBLIC_ENABLE_SOCKS5_PROXY=true
# web_fetch). Default: 60000. Used by: open-sse/mcp-server/fetchTimeout.ts
# OMNIROUTE_MCP_UPSTREAM_TIMEOUT_MS=60000
# Maximum number of local-corpus index instances cached in memory.
# Used by: src/lib/localCorpus/configured.ts — bounds the LRU cache of
# LocalCorpusIndex objects (one per indexed root directory). Default: 5.
# OMNIROUTE_CORPUS_CACHE_SIZE=5
# Model catalog sync interval in hours.
# Used by: src/shared/services/modelSyncScheduler.ts — periodic model refresh.
# Default: 24
@@ -1027,6 +1041,16 @@ PROVIDER_LIMITS_SYNC_SPACING_MS=1500
# Used by: open-sse/services/compression/engines/rtk/filterLoader.ts. Default: 0.
#OMNIROUTE_RTK_TRUST_PROJECT_FILTERS=0
# Maximum concurrent synchronous compression workers. Excess jobs wait FIFO.
# Used by: open-sse/services/compression/compressionWorkerPool.ts. Default: 2.
#OMNI_COMPRESSION_WORKERS=2
# Per-job worker timeout (ms). A timed-out worker is terminated and the request fails open.
# Used by: open-sse/services/compression/compressionWorkerPool.ts. Default: 120000.
#OMNI_COMPRESSION_WORKER_TIMEOUT_MS=120000
# Terminate idle compression workers after this many milliseconds.
# Used by: open-sse/services/compression/compressionWorkerPool.ts. Default: 60000.
#OMNI_COMPRESSION_WORKER_IDLE_MS=60000
# T02 stacked-pipeline engine circuit-breaker (OPT-IN, default off). When enabled, a compression
# engine that throws repeatedly across requests is skipped (fail-open) for a cooldown.
# Used by: open-sse/services/compression/pipelineEngineBreaker.ts.
@@ -1778,6 +1802,13 @@ APP_LOG_TO_FILE=true
# SEMANTIC_CACHE_MAX_BYTES=4194304 # Max total cache size in bytes (default: 4 MB)
# SEMANTIC_CACHE_TTL_MS=1800000 # Cache entry TTL (default: 30 minutes)
# ── Local corpus index cache ──
# How many local-corpus roots keep a live in-memory index at once. The cache is
# LRU: reaching the limit evicts the least-recently-used root's index, which is
# then rebuilt on its next query. Clamped to a minimum of 1; a non-numeric value
# falls back to the default. Used by: src/lib/localCorpus/configured.ts
# OMNIROUTE_CORPUS_CACHE_SIZE=5
# ── In-memory log buffers ──
# Maximum recent stream events kept in memory for the Dashboard live view.
# STREAM_HISTORY_MAX=50
@@ -1973,6 +2004,26 @@ APP_LOG_TO_FILE=true
# Custom path to cloudflared binary for tunnel management.
# Used by: src/lib/cloudflaredTunnel.ts
# CLOUDFLARED_BIN=/usr/local/bin/cloudflared
#
# Transport protocol for the tunnel. One of: http2 (default), quic, auto.
# CLOUDFLARED_PROTOCOL=http2
#
# ── Named / persistent tunnel (stable hostname) ──
# By default OmniRoute runs an ephemeral quick tunnel (random *.trycloudflare.com
# URL that changes on every restart). To bind a stable, named hostname instead,
# create a locally-managed tunnel with the cloudflared CLI:
# cloudflared tunnel login
# cloudflared tunnel create <name>
# cloudflared tunnel route dns <name> ai.example.com
# then write a ~/.cloudflared/config.yml with `tunnel:`, `credentials-file:`, and
# `ingress:` rules routing your hostname to http://localhost:<PORT> (default 20128).
# Point OmniRoute at that config to switch into named-tunnel mode — it runs
# `cloudflared tunnel --config <path> run`.
# CLOUDFLARED_CONFIG=/home/you/.cloudflared/config.yml
# CLOUDFLARED_HOSTNAME is optional — when unset, OmniRoute reads the public hostname
# from the config's first ingress rule. Set it to override what is reported as
# publicUrl/apiUrl.
# CLOUDFLARED_HOSTNAME=ai.example.com
# ── Search cache ──
# TTL for search API response caching (Perplexity, Brave, etc.).
@@ -2011,6 +2062,9 @@ APP_LOG_TO_FILE=true
# CLIPROXYAPI_HOST=127.0.0.1
# CLIPROXYAPI_PORT=5544
# CLIPROXYAPI_CONFIG_DIR=~/.cli-proxy-api
# Management key for an externally managed instance. Embedded instances use
# OmniRoute's encrypted service key.
# CLIPROXYAPI_MANAGEMENT_KEY=
# ── Mux embedded service ──
# Override the port where the embedded Mux (coder/mux) agent-orchestration
@@ -2420,10 +2474,10 @@ APP_LOG_TO_FILE=true
# test suite must NEVER mutate the OS trust store (a fake test PEM installed via
# update-ca-certificates broke all system TLS on a persistent runner, 2026-07-05).
# OMNIROUTE_SKIP_SYSTEM_TRUST=1
# check-changelog-integrity.mjs (anti CHANGELOG-eat gate): explicit base ref
# override, and the justified-removal escape hatch for intentional bullet removals.
# check-changelog-integrity.mjs (anti CHANGELOG-eat gate): explicit base ref override.
# Intentional transformations require an exact reviewed entry in
# config/release/changelog-reconciliations.json; there is no runtime bypass.
# CHANGELOG_BASE_REF=origin/release/v0.0.0
# ALLOW_CHANGELOG_REMOVALS=1
# ── Remote audio provider nodes ──
# Used by: src/app/api/v1/_shared/audioProviderNodes.ts — lets the /v1/audio/*
@@ -3013,3 +3067,9 @@ QUOTA_STORE_DRIVER=sqlite
# without a configured budget are always considered affordable. Requires the
# provider_quota_state table (migration 148).
# OMNIROUTE_QUOTA_AWARE_ROUTING=0
# ─── LOCAL CORPUS (opt-in document index) ───
# Size of the in-memory LRU index cache for the local document corpus used by
# corpus-aware retrieval. Higher values keep more index entries hot.
# Used by: src/lib/localCorpus/configured.ts
# OMNIROUTE_CORPUS_CACHE_SIZE=5

View File

@@ -126,6 +126,7 @@ jobs:
- run: npm run check:route-validation:t06
- run: npm run check:any-budget:t11
- run: npm run check:provider-consistency
- run: npm run check:model-lifecycle
- run: npm run check:fetch-targets
- run: npm run check:deps
- run: npm run check:file-size

View File

@@ -68,6 +68,16 @@ jobs:
"$EVENT_NAME" "$REF_TYPE" "$REF_NAME" "$INPUT_VERSION" "$DEFAULT_BRANCH")
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
# Frozen release branches keep receiving coordination commits after the
# next cycle becomes the default branch. They must not overwrite :next,
# but that expected no-op is not a workflow failure.
if [ "$VERSION" = "skip" ]; then
echo "promote_latest=false" >> "$GITHUB_OUTPUT"
echo "skip=true" >> "$GITHUB_OUTPUT"
echo "Skipping Docker publish from non-default release branch: $REF_NAME"
exit 0
fi
# 2) Decide whether to promote :latest. Floating channels are never
# eligible, and the helper independently fails closed for non-semver.
PROMOTE="false"

View File

@@ -2,11 +2,11 @@ name: opencode-plugin CI
on:
push:
branches: [main, "release/**"]
branches: [main, release/v3.8.2]
paths:
- "@omniroute/opencode-plugin/**"
pull_request:
branches: [main, "release/**"]
branches: [main, release/v3.8.2]
paths:
- "@omniroute/opencode-plugin/**"
types: [opened, synchronize, reopened, ready_for_review]

View File

@@ -273,7 +273,7 @@ jobs:
migration-numbering public-creds db-rules known-symbols
route-guard-membership test-discovery test-runner-api
mutation-test-coverage any-budget:t11 build-scope pack-policy
complexity-ratchets
complexity-ratchets model-lifecycle
cycles lockfile duplication dead-code type-coverage compression-budget
# #8781: open-sse workspace typecheck gate — the workspace imports @/ which
# escapes to src/ via undeclared path aliases. See check-open-sse-typecheck.mjs.

1
.gitignore vendored
View File

@@ -14,6 +14,7 @@ _tasks/
.agents/**
.claude/**
.gemini/**
.code-forge/**
.config/**
.data/**
.logs/**

View File

@@ -46,7 +46,7 @@ Repository map and Reference Documentation sections below.
## Project at a Glance
**OmniRoute** — unified AI proxy/router. One endpoint, 350 LLM providers, auto-fallback.
**OmniRoute** — unified AI proxy/router. One endpoint, 354 LLM providers, auto-fallback.
| Layer | Location | Purpose |
| ------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -56,7 +56,7 @@ Repository map and Reference Documentation sections below.
| Translators | `open-sse/translator/` | Format conversion (OpenAI↔Claude↔Gemini) |
| Transformer | `open-sse/transformer/` | Responses API ↔ Chat Completions |
| Services | `open-sse/services/` | Combo routing, rate limits, caching, etc |
| Database | `src/lib/db/` | SQLite domain modules (159 migrations) |
| Database | `src/lib/db/` | SQLite domain modules (160 migrations) |
| Domain/Policy | `src/domain/` | Policy engine, cost rules, fallback logic |
| MCP Server | `open-sse/mcp-server/` | 110 tools (44 canonical + memory/skill/GitHub/pool/gamification/plugin/Notion/Obsidian/local-corpus/RTK modules), 3 transports (stdio / SSE / Streamable HTTP), 33 scopes |
| A2A Server | `src/lib/a2a/` | JSON-RPC 2.0 agent protocol |
@@ -83,7 +83,7 @@ Client → /v1/chat/completions (Next.js route)
API routes follow a consistent pattern: `Route → CORS preflight → Zod body validation → Optional auth (extractApiKey/isValidApiKey) → API key policy enforcement → Handler delegation (open-sse)`. No global Next.js middleware — interception is route-specific.
**Combo routing** (`open-sse/services/combo.ts`): 19 public strategies (priority, weighted, fill-first, round-robin, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, cache-optimized, context-relay, fusion, pipeline). Each target calls `handleSingleModel()` which wraps `handleChatCore()` with per-target error handling and circuit breaker checks. The `fusion` strategy is the exception: it fans out to a panel of models in parallel, then a judge model synthesizes one final answer (`open-sse/services/fusion.ts`). See `docs/routing/AUTO-COMBO.md` for the 14-factor Auto-Combo scoring + the full strategy table and `docs/architecture/RESILIENCE_GUIDE.md` for the 3 resilience layers.
**Combo routing** (`open-sse/services/combo.ts`): 19 public strategies (priority, weighted, fill-first, round-robin, p2c, random, least-used, cost-optimized, reset-aware, reset-window, headroom, strict-random, auto, lkgp, context-optimized, cache-optimized, context-relay, fusion, pipeline). Each target calls `handleSingleModel()` which wraps `handleChatCore()` with per-target error handling and circuit breaker checks. The `fusion` strategy is the exception: it fans out to a panel of models in parallel, then a judge model synthesizes one final answer (`open-sse/services/fusion.ts`). See `docs/routing/AUTO-COMBO.md` for the 15-factor Auto-Combo scoring + the full strategy table and `docs/architecture/RESILIENCE_GUIDE.md` for the 3 resilience layers.
---
@@ -197,7 +197,7 @@ baseCooldownMs * 2 ** failureIndex;
The anti-thundering-herd guard prevents concurrent failures on the same connection from
repeatedly extending the cooldown or double-incrementing `backoffLevel`.
Terminal states are not cooldowns. `banned`, `expired`, and `credits_exhausted` are
Terminal states are not cooldowns. `banned`, `expired` (which becomes terminal only after N bounded retries via `EXPIRED_RETRY_MAX`), and `credits_exhausted` are
intended to stay unavailable until credentials/settings change or an operator resets
them. Do not overwrite terminal states with transient cooldown state.
@@ -411,7 +411,7 @@ For any non-trivial change, read the matching deep-dive first:
| Repo navigation | `docs/architecture/REPOSITORY_MAP.md` |
| Architecture | `docs/architecture/ARCHITECTURE.md` |
| Engineering reference | `docs/architecture/CODEBASE_DOCUMENTATION.md` |
| Auto-Combo (14-factor scoring, 19 strategies) | `docs/routing/AUTO-COMBO.md` |
| Auto-Combo (15-factor scoring, 19 strategies) | `docs/routing/AUTO-COMBO.md` |
| Resilience (3 mechanisms) | `docs/architecture/RESILIENCE_GUIDE.md` |
| Reasoning replay | `docs/routing/REASONING_REPLAY.md` |
| Skills framework | `docs/frameworks/SKILLS.md` |

View File

@@ -16,6 +16,18 @@
---
## [3.8.51] — TBD
_Living section — cycle opened at the v3.8.50 freeze (parallel-cycle model). Bullets are aggregated from `changelog.d/` fragments at each `/generate-release` phase._
### ✨ New Features
### 🐛 Bug Fixes
### 📝 Maintenance
---
## [3.8.50] — TBD
_Living section — regenerated 2026-08-12 from all cycle commits (cycle open `ed2db6cb19` → tip). Bullets carry the merged PR and its author; direct pushes listed separately._
@@ -180,6 +192,7 @@ _Living section — regenerated 2026-08-12 from all cycle commits (cycle open `e
### 🐛 Bug Fixes
- **fix(build):** every route no longer answers HTTP 500 on artifacts built from the release tip ([#11343](https://github.com/diegosouzapw/OmniRoute/issues/11343)) — `next.config.mjs` aliased `better-sqlite3` to its build-time stub **unconditionally**, on the premise that `serverExternalPackages` still won at runtime. It does not: a Turbopack `resolveAlias` rewrites the request *before* the externals check, so the request stopped matching the `better-sqlite3` external entry and the stub was baked into the shipped bundle. The sync driver then failed with `r(...) is not a constructor`, fell through `node:sqlite` and sql.js, and the instrumentation hook aborted at boot. Same failure shape as [#6344](https://github.com/diegosouzapw/OmniRoute/issues/6344), so it gets the same treatment: the alias is opt-in via `OMNIROUTE_BETTER_SQLITE3_STUB=1` through the shared `scripts/build/better-sqlite3-stub-flag.mjs` helper — set it only on a build host that actually hits the SIGABRT build-worker teardown ([#10060](https://github.com/diegosouzapw/OmniRoute/issues/10060)); default builds externalize the real native addon. Regression guards: `tests/unit/better-sqlite3-stub-alias-11343.test.mjs` (5) and the env matrix in `tests/unit/next-config.test.ts`.
- **security(search)**: block SSRF via `/v1/search` `provider_options.baseUrl` for the Firecrawl search provider — the client-controlled override is now validated as a public URL before it is used to build the server-side fetch target, so a caller with a valid API key can no longer redirect search requests at loopback, RFC1918, or cloud-metadata hosts — thanks @zmf963
- **providers**: honor `PATCH /api/providers/[id]` so `omniroute providers rotate` stops 405ing (the OpenAPI spec and CLI already use PATCH) (PR #10366)
- **cli**: route provider test commands through configured connection test endpoints (#10570)

View File

@@ -181,10 +181,33 @@ ENV NODE_OPTIONS="--max-old-space-size=${OMNIROUTE_BUILD_MEMORY_MB}"
# workers for page-data collection (31 on a 32-core builder); on memory-tight
# hosts 31 workers + webpack's multi-GB heap blow past RAM and a worker dies
# with SIGSEGV at teardown ("worker exited with code: null and signal: SIGSEGV"),
# silently leaving no standalone bundle. Next derives the default worker count
# from CIRCLE_NODE_TOTAL (workers = N-1), so N=8 → 7 workers: fast enough while
# fitting comfortably in RAM on any host. (#10060)
ENV CIRCLE_NODE_TOTAL=8
# silently leaving no standalone bundle. Next derives the worker count from
# CIRCLE_NODE_TOTAL (workers = N-1). (#10060)
#
# Lowered 8 → 3 (7 workers → 2) in #11419, then 3 → 2 (2 workers → 1) in #7518.
# Every page-data worker inherits NODE_OPTIONS above, so the ceiling is per
# PROCESS, not per build: 7 workers on a 16 GB GitHub runner (ubuntu-24.04 /
# ubuntu-24.04-arm, 4 vCPU) exhausted the host and buildkit failed the whole
# step with `ResourceExhausted: ... cannot allocate memory`. The compile phase
# always finished ("✓ Compiled successfully in 4.2min"); the kernel killed the
# build right after "Collecting page data using N workers".
#
# #11419's first fix (8 → 3) modeled the per-worker peak as an INFERENCE
# (2560 MB, guessed from "7 workers didn't fit") and assumed the parent
# process's RSS tracked the V8 heap ceiling. Both assumptions were wrong: a
# live VPS reproduction (issue #7518, dmesg OOM-killer report) measured the
# real per-process RSS directly at ~4.5 GB, independent of the NODE_OPTIONS
# heap flag (Turbopack itself is native/Rust, outside the V8 heap) — and it
# applies to the parent process too, not just workers. 2 workers (3 processes
# × 4.5 GB = 13.5 GB) still didn't fit the 12.288 GB (75%) budget on a 16 GB
# runner, matching the still-live publish failures after #11419 merged. 1
# worker (2 processes × 4.5 GB = 9 GB) fits with headroom to spare.
# tests/unit/docker-build-memory-budget.test.ts does the arithmetic against
# the measured figure and fails if either knob is raised past what a 16 GB
# runner holds. Override for a big builder: `--build-arg
# OMNIROUTE_BUILD_WORKERS=8`.
ARG OMNIROUTE_BUILD_WORKERS=2
ENV CIRCLE_NODE_TOTAL=${OMNIROUTE_BUILD_WORKERS}
COPY . ./
RUN --mount=type=cache,id=s/92ca8a61-c1ba-421f-a389-d48ac7258c2d-next-cache,target=/app/.build/next/cache \

View File

@@ -19,23 +19,31 @@ RUN apt-get update \
FROM base AS builder
WORKDIR /app
COPY . .
# Cache dependency layer
COPY package.json bun.lock* pnpm-workspace.yaml* ./
COPY open-sse/package.json ./open-sse/package.json
COPY packages/ ./packages/
# Root postinstall helpers needed during bun install lifecycle
COPY scripts/build/ ./scripts/build/
COPY scripts/dev/sync-env.mjs ./scripts/dev/sync-env.mjs
# Fast Bun native package install
RUN bun install --include=optional --quiet
# Compile native better-sqlite3 Node-API addon under Bun
RUN if [ -d "node_modules/better-sqlite3" ]; then \
(cd node_modules/better-sqlite3 && bunx node-gyp rebuild); \
fi
# Fetch tls-client-node native binary if script exists
RUN if [ -f "node_modules/tls-client-node/scripts/postinstall.js" ]; then \
RUN if [ -f "node_modules/tls-client-node/scripts/postinstall.js" ] && [ ! -d "node_modules/tls-client-node/bin" ]; then \
bun node_modules/tls-client-node/scripts/postinstall.js || true; \
fi
# Disable Turbopack for Bun builder stage (Turbopack V8 internal worker bindings require Node)
ENV OMNIROUTE_USE_TURBOPACK=0
# Smoke check native database driver used by Bun (bun:sqlite)
RUN bun -e "import { Database } from 'bun:sqlite'; const db = new Database(':memory:'); db.query('SELECT 1 AS ok').get(); db.close(); console.log('bun:sqlite smoke: OK');"
COPY . .
# Turbopack is supported on Bun 1.4 + Next 16.3; override via --build-arg OMNIROUTE_USE_TURBOPACK=0 if needed
ARG OMNIROUTE_USE_TURBOPACK=1
ENV OMNIROUTE_USE_TURBOPACK=${OMNIROUTE_USE_TURBOPACK}
ARG OMNIROUTE_BASE_PATH=""
ENV OMNIROUTE_BASE_PATH=$OMNIROUTE_BASE_PATH
@@ -65,6 +73,7 @@ RUN apt-get update \
libsecret-1-0 \
ca-certificates \
curl \
sqlite3 \
&& rm -rf /var/lib/apt/lists/*
ENV NODE_ENV=production
@@ -76,11 +85,23 @@ ENV DATA_DIR=/app/data
RUN mkdir -p /app/data
COPY --from=builder /app/.build/next/standalone ./
COPY --from=builder /app/node_modules/better-sqlite3 ./node_modules/better-sqlite3
ENV OMNIROUTE_MIGRATIONS_DIR=/app/migrations
COPY --from=builder /app/scripts/dev/healthcheck.mjs ./healthcheck.mjs
# Bun uses bun:sqlite. Remove every standalone/vendor copy of the Node-only
# addon so no traced chunk can dlopen it and abort the process before fallback.
RUN find /app \
-path '*/node_modules/better-sqlite3' \
-prune \
-exec rm -rf '{}' + \
&& test -z "$(find /app -type f -name 'better_sqlite3.node' -print -quit)"
RUN chown -R bun:bun /app /app/data
USER bun
EXPOSE 20128
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
@@ -141,6 +162,7 @@ RUN apt-get update \
ENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
ENV PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium
# Return to the base image non-root user after the apt install (mirrors the
# Node Dockerfile runner-web stage, which re-asserts USER node).
# Drop back to default non-root user
USER bun
ENTRYPOINT ["bun", "dev/run-standalone.mjs"]

415
README.md
View File

@@ -7,7 +7,7 @@
# 🚀 OmniRoute — The Free AI Gateway
<img src="./docs/diagrams/readme-hero.svg" width="100%" alt="OmniRoute — Never stop coding. Every AI tool → 350 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot & Antigravity into FREE Claude / GPT / Gemini with auto-fallback. RTK + Caveman stacked compression saves 1595% tokens (~89% avg) — never hit limits. 350 AI providers · 90+ free tiers · ~1.51B free tokens/mo · 19 routing strategies · $0 to start."/>
<img src="./docs/diagrams/readme-hero.svg" width="100%" alt="OmniRoute — Never stop coding. Every AI tool → 353 providers — 90+ free — through one endpoint. Claude Code, Codex, Cursor, Cline, Copilot & Antigravity into FREE Claude / GPT / Gemini with auto-fallback. RTK + Caveman stacked compression saves 1595% tokens (~89% avg) — never hit limits. 353 AI providers · 90+ free tiers · ~1.51B free tokens/mo · 19 routing strategies · $0 to start."/>
</div>
@@ -17,9 +17,9 @@
</div>
> Stacking free tiers by hand is painful — dozens of SDKs, dozens of rate limits, and no idea how much you actually have. OmniRoute aggregates the **documented** free tiers of **42 provider pools / 495 models** into one honest number and shows it live on the dashboard (`/dashboard/free-tiers`).
> Stacking free tiers by hand is painful — dozens of SDKs, dozens of rate limits, and no idea how much you actually have. OmniRoute catalogs **455 free-tier entries across 40 recurring pool keys** and computes the token headline from the **20 pools with a published positive monthly budget**, deduplicated by shared pool. The result stays visible on the dashboard (`/dashboard/free-tiers`).
<img src="./docs/diagrams/free-tier-budget.svg" width="100%" alt="OmniRoute free-tier budget card: ~1.51B free tokens per month steady, up to ~2.13B in the first month with signup credits, from the documented free tiers of 42 provider pools / 495 models behind one endpoint. Honest pool-deduped math — each shared pool counted once (counting every rate limit 24/7 would read ~10B; not published), 15 providers ToS-flagged so you decide. Budget bar of the countable free pools with per-model grid (Mistral Large 3 1B, GPT-4o mini 150M, Gemini 2.5 Flash 60M … Claude Sonnet 4.5 25K), one-time first-month signup credits (vertex 300M, agentrouter 200M, predibase 25M, together 25M, glm-cn 20M, doubao 15M, ai21 10M, longcat 10M, deepseek 5M, hyperbolic 5M, nscale 5M), plus permanently-free no-token-cap providers (SiliconFlow, Z.AI GLM-Flash, Kilo, OpenCode Zen, baidu …) and a $10 OpenRouter top-up unlocking +24M/mo — surfaced separately so they never inflate the headline. Live used/remaining on /dashboard/free-tiers."/>
<img src="./docs/diagrams/free-tier-budget.svg" width="100%" alt="OmniRoute free-tier budget card: ~1.51B free tokens per month steady, up to ~2.13B in the first month with signup credits, from 40 documented recurring pool keys covering 455 cataloged free-tier entries behind one endpoint. Honest pool-deduped math — each shared pool counted once, including 20 recurring pools with a published positive monthly token budget; 15 providers are marked avoid in the terms-risk catalog so you decide. Budget bar includes Mistral 1B, LLM7 150M, Nara 150M, Gemini 60M and smaller pools, plus first-month signup credits and permanently-free no-token-cap providers surfaced separately so they never inflate the headline. Live used/remaining on /dashboard/free-tiers."/>
> Animated summary of the live `/dashboard/free-tiers` page. Full methodology (pool dedupe, credit tiers, provider terms): **[docs/reference/FREE_TIERS.md](docs/reference/FREE_TIERS.md)**.
>
@@ -61,14 +61,14 @@
<div align="center">
| | v3.8.49 | **v3.8.50** | `v3.8.51+` |
| ------------------------- | :-----: | :---------: | :---------: |
| 🌐 Providers | 290 | **342** | more queued |
| 🧠 Documented models | 1185 | **1202** | — |
| 🖼️ Modality Bridge | — | 🆕 vision | video |
| 📡 Radar free catalog | — | 🆕 opt-in | — |
| ⚖️ Quota-aware scheduling | — | | 🔭 next |
| 📊 Quota telemetry | — | | 🔭 next |
| | v3.8.49 | **v3.8.50** | `v3.8.51+` |
| ------------------------- | :-----: | :-----------------------: | :---------: |
| 🌐 Providers | 290 | **350** | more queued |
| 🧠 Unique chat model IDs | 1185 | **1312** | — |
| 🖼️ Modality Bridge | — | 🆕 vision + audio + video | — |
| 📡 Radar free catalog | — | 🆕 opt-in | — |
| ⚖️ Quota-aware scheduling | — | 🆕 Quota-Share | |
| 📊 Quota telemetry | — | 🆕 live | |
**→ [Roadmap](ROADMAP.md) — riding the rail to `v3.9.0 LTS`**
@@ -101,7 +101,7 @@
<tr>
<td align="right"><b>⚙️ Features</b></td>
<td align="center"><a href="#-combos--the-flagship">🎯 Combos</a></td>
<td align="center"><a href="#-349-ai-providers--90-free">🌐 Providers</a></td>
<td align="center"><a href="#-350-ai-providers--154-catalog-marked-free">🌐 Providers</a></td>
<td align="center"><a href="#-full-cli--a2a--mcp">🔌 CLI &amp; MCP</a></td>
</tr>
<tr>
@@ -126,7 +126,7 @@
<td align="right"><b>📦 Project</b></td>
<td align="center"><a href="#%EF%B8%8F-tech-stack">🛠️ Tech Stack</a></td>
<td align="center"><a href="#-documentation">📖 Docs</a></td>
<td align="center"><a href="#-500-contributors">👥 Contributors</a></td>
<td align="center"><a href="#-600-contributors">👥 Contributors</a></td>
</tr>
</table>
@@ -210,7 +210,7 @@ curl http://localhost:20128/v1/chat/completions \
</div>
<img src="./docs/diagrams/promise-pillars.svg" width="100%" alt="The Promise — One endpoint. 350 providers. Never stop building — OmniRoute picks the cheapest one that works. Six pillars: Never hit limits (auto-fallback across 350 providers in milliseconds, zero downtime) · Save up to 95% tokens (RTK + Caveman stacked compression cuts 1595%, ~89% avg on tool-heavy sessions) · $0 to start (90+ free tiers, 56 free forever — no card needed) · Every tool works (33 coding agents through one config) · One endpoint (OpenAI Claude Gemini Responses API at /v1) · Production-grade (circuit breakers, TLS stealth, MCP 110 tools, A2A, memory, guardrails, evals — 25,000+ tests)."/>
<img src="./docs/diagrams/promise-pillars.svg" width="100%" alt="The Promise — One endpoint and 353 providers. Automatic fallback keeps routing while another healthy target is available. Six pillars: resilient fallback across 353 providers · up to 95% token savings on eligible workloads · $0 to start with 90+ free tiers and 56 recurring/keyless free-forever providers · 35 CLI/agent integrations through one config · OpenAI, Claude, Gemini and Responses API compatibility at /v1 · production controls including circuit breakers, TLS stealth, MCP 110 tools, A2A, memory, guardrails, evals and 39,000+ static test declarations across 5,100+ tracked test files."/>
<br/>
<br/>
@@ -225,7 +225,7 @@ curl http://localhost:20128/v1/chat/completions \
<div align="center">
<img src="./docs/diagrams/tier-cascade.svg" width="100%" alt="OmniRoute request flow: your IDE or CLI (Claude Code, Cursor, Cline…) calls one local endpoint (http://localhost:20128/v1); the OmniRoute Smart Router (RTK + Caveman compression, 19 routing strategies, circuit breakers, TLS stealth, MCP, A2A, guardrails) auto-falls back across 4 provider tiers — Tier 1 Subscription (Claude Code, Codex, Copilot), quota out? Tier 2 API Key (DeepSeek, Groq, xAI), budget hit? Tier 3 Cheap (GLM $0.5, MiniMax $0.2), budget hit? Tier 4 Free (Kiro, Qoder, Pollinations) — always on."/>
<img src="./docs/diagrams/tier-cascade.svg" width="100%" alt="OmniRoute request flow: your IDE or CLI (Claude Code, Cursor, Cline…) calls one local endpoint (http://localhost:20128/v1); the OmniRoute Smart Router (RTK + Caveman compression, 19 routing strategies, circuit breakers, TLS stealth, MCP, A2A, guardrails) can fall back across 4 provider tiers while an eligible healthy target remains — Tier 1 Subscription, Tier 2 API Key, Tier 3 Cheap and Tier 4 Free."/>
</div>
@@ -318,7 +318,7 @@ curl http://localhost:20128/v1/chat/completions \
<img src="./docs/diagrams/strategies-grid.svg" width="100%" alt="All 19 combo routing strategies animated — one tile per strategy: priority, fill-first, weighted, round-robin, p2c, least-used, random, strict-random, cost-optimized, headroom, reset-window, reset-aware, context-relay, context-optimized, cache-optimized, lkgp, auto, fusion, pipeline. See the table above for what each one does."/>
> A **combo** is a chain of models OmniRoute routes across **automatically**. Quota runs out, a provider fails, or costs spike the combo silently slides to the next model. **This is what makes OmniRoute unbreakable.** 🛡️
> A **combo** is a chain of models OmniRoute routes across **automatically**. If quota runs out, a provider fails, or costs spike, the combo can move to the next eligible healthy model. 🛡️
### ⚡ Zero-config — just use `auto`
@@ -424,12 +424,12 @@ All **19** strategies — mix & match per combo step:
<tr>
<td align="center">16</td>
<td nowrap><code>lkgp</code></td>
<td>Last-Known-Good Path — sticky to the last successful target</td>
<td>Last-Known-Good Path — pins to the last successful provider, then falls back to rules</td>
</tr>
<tr>
<td align="center">17</td>
<td nowrap><code>auto</code></td>
<td>14-factor live scoring across every connection 🤖</td>
<td>15-factor live scoring across every connection 🤖</td>
</tr>
<tr>
<td align="center">18</td>
@@ -443,7 +443,7 @@ All **19** strategies — mix & match per combo step:
</tr>
</table>
<sub>The Auto-Combo engine scores every candidate on **14 factors** (health, quota, cost, latency, success rate, freshness…) — see [`docs/routing/AUTO-COMBO.md`](docs/routing/AUTO-COMBO.md).</sub>
<sub>The Auto-Combo engine scores every candidate on **15 factors** (health, quota, cost, latency, task fit, quality, session availability…) — see [`docs/routing/AUTO-COMBO.md`](docs/routing/AUTO-COMBO.md).</sub>
##
@@ -461,7 +461,7 @@ All **19** strategies — mix & match per combo step:
</div>
<img src="./docs/diagrams/comparison-table.svg" width="100%" alt="What sets OmniRoute apart — comparison table vs 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute: 350 providers, 90+ free providers built-in, 19 routing strategies, 12-engine token compression, built-in MCP server with 110 tools, A2A agent protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, Desktop/Termux/PWA, 43 i18n UI locales, 100% MIT self-hosted. OmniRoute is the only one with the full set; competitors show a mix of checks, partials and crosses. Verified from each project&apos;s docs."/>
<img src="./docs/diagrams/comparison-table.svg" width="100%" alt="What sets OmniRoute apart — a dated feature snapshot vs 9router, OpenRouter, CLIProxyAPI and LiteLLM across 13 capabilities. OmniRoute: 353 providers, 90+ free tiers built in, 19 routing strategies, 12-engine token compression, built-in MCP server with 110 tools, A2A agent protocol, persistent memory, guardrails, cloud agents, TLS fingerprint stealth, Desktop/Termux/PWA and 43 i18n UI locales. OmniRoute is MIT-licensed and self-hostable. Competitor capabilities and counts may change; see the linked methodology."/>
<sub>📊 Full methodology &amp; per-feature detail vs 9router, OpenRouter, CLIProxyAPI &amp; LiteLLM → [`docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md`](docs/comparison/OMNIROUTE_VS_ALTERNATIVES.md)</sub>
@@ -517,9 +517,9 @@ Pix copia-e-cola:
## 📡 OmniRoute Radar
The main free-tier headline remains **~1.53B tokens/month** from the documented,
The main free-tier headline remains **~1.51B tokens/month** from the documented,
pool-deduplicated catalog above. Temporary provider signup credits can separately lift the first
month to **~2.15B**. Radar is an optional, signed catalog overlay for people who want fresher
month to **~2.13B**. Radar is an optional, signed catalog overlay for people who want fresher
free-model availability between OmniRoute releases; the community catalog and every existing free
feature remain free.
@@ -548,7 +548,7 @@ the current catalog at **[radar.omniroute.online/planos](https://radar.omniroute
- **🗜️ Compression hardening** — default-on inflation guard, Caveman packs for DE / FR / JA + Chinese (wényán), RTK filters for Gradle & .NET. → [Compression](docs/compression/COMPRESSION_ENGINES.md)
- **💸 Honest flat-rate cost** — subscription / coding-plan providers read **$0** in cost analytics; budget, quota & routing keep estimating. → [API Reference](docs/reference/API_REFERENCE.md)
- **⚖️ Quota-Share routing** — split a shared account's quota fairly across pooled keys, work-conserving so idle slices are lent out. → [Resilience Guide](docs/architecture/RESILIENCE_GUIDE.md)
- **🤖 One-command CLI/agent setup** — `setup-*` configures 12+ coding tools; `omniroute run` launches 7 CLIs (Claude Code, Codex, Aider, Goose, OpenCode, Qwen Code, Gemini CLI) with zero config written; `omniroute configure` is an interactive provider+model picker with per-context favorites. → [CLI Integrations](docs/guides/CLI-INTEGRATIONS.md)
- **🤖 One-command CLI/agent setup** — 12 registered `setup-*` commands; `omniroute run` launches 7 CLIs (Claude Code, Codex, Aider, Goose, OpenCode, Qwen Code, Gemini CLI); `omniroute configure` supports 9 targets with an interactive provider+model picker and per-context favorites. → [CLI Integrations](docs/guides/CLI-INTEGRATIONS.md)
- **🛰️ Remote mode** — drive a remote OmniRoute with scoped tokens (`connect` / `contexts` / `tokens`) + an `antigravity` OAuth helper for VPS installs. → [Remote Mode](docs/guides/REMOTE-MODE.md)
- **🧭 Smarter auto-routing** — `auto/<category>:<tier>` combos, **Fusion** (model panel + judge), task-aware routing, per-request model / mode / USD-budget overrides. → [Auto-Combo](docs/routing/AUTO-COMBO.md)
- **🗜️ Pluggable compression** — 12 composable engines + Compression Studios: LLMLingua-2, two-tier Ultra, omniglyph, per-step fidelity gate, GCF v3.2, drag-reorder editor. → [Compression](docs/compression/COMPRESSION_ENGINES.md)
@@ -559,7 +559,7 @@ the current catalog at **[radar.omniroute.online/planos](https://radar.omniroute
- **🖼️ New endpoints** — `/v1/ocr` (Mistral OCR) and `/v1/audio/translations` (Whisper-style) round out the media surface. → [API Reference](docs/reference/API_REFERENCE.md)
- **🎨 Image / video / audio generation** — one API for media: xAI Grok Imagine & Novita AI video, ComfyUI, Freepik, Adobe Firefly, Microsoft Designer, Segmind, EdgeTTS. → [API Reference](docs/reference/API_REFERENCE.md)
- **🌍 Deployment & ops** — reverse-proxy `basePath`, browser-language auto-detect, per-key device tracking, root-less MITM trust, zh-TW localization. → [Environment](docs/reference/ENVIRONMENT.md)
- **🤝 More providers & agents** — Cursor Cloud Agent, Grok Build (xAI) with browser + OAuth login, Ollama first-class card, Claude Opus 5 & Sonnet 5, Kimi official partnership (Code/Web/Moonshot), Zed, Requesty, SenseNova, Yuanbao, Agnes AI… and a refreshed **350-provider catalog**. → [Providers](docs/reference/PROVIDER_REFERENCE.md)
- **🤝 More providers & agents** — Cursor Cloud Agent, Grok Build (xAI) with browser + OAuth login, Ollama first-class card, Claude Opus 5 & Sonnet 5, Kimi official partnership (Code/Web/Moonshot), Zed, Requesty, SenseNova, Yuanbao, Agnes AI… and a refreshed **353-provider catalog**. → [Providers](docs/reference/PROVIDER_REFERENCE.md)
- **📡 Routing transparency** — every response carries an `X-OmniRoute-Decision` header naming the strategy/provider/latency that served it, a new `cache-optimized` combo strategy + Auto-Combo `cacheAffinity` factor route repeat requests back to the connection holding the cached prefix, and a read-only `/v1/auto-combo/{channel}/candidates` endpoint exposes an `auto/*` channel's live candidate pool. → [Auto-Combo](docs/routing/AUTO-COMBO.md)
- **⚡ Local performance & infra** — one-click local Redis, Cloudflare Workers / Deno Deploy relay deployers, Bifrost & Mux as supervised embedded services. → [Embedded Services](docs/frameworks/EMBEDDED-SERVICES.md)
@@ -642,11 +642,11 @@ of your shell history. → [CLI Integrations](docs/guides/CLI-INTEGRATIONS.md)
<div align="center">
## 🌐 349 AI Providers — 90+ Free
## 🌐 353 AI Providers — 154 Catalog-Marked Free
</div>
> The most complete catalog of any open-source router: **350 providers**, **90+ with a free tier**, **56 free forever**.
> **353 registered providers** across the canonical chat, media, search, local, cloud-agent and system collections, including **154 carrying `hasFree: true` discovery metadata**. The chat model registry covers **268 providers / 2,566 distinct provider-model pairs / 1,312 raw model IDs**; the separate free-budget catalog has **455 per-model rows**, **40 recurring pools** and **56 recurring/keyless free-forever providers**. These are different denominators by design; definitions and pool-deduped calculations live in the [Provider Reference](docs/reference/PROVIDER_REFERENCE.md) and [Free Tiers](docs/reference/FREE_TIERS.md).
<div align="center">
@@ -679,7 +679,7 @@ of your shell history. → [CLI Integrations](docs/guides/CLI-INTEGRATIONS.md)
</tr>
</table>
<sub>…and 220+ more — every icon resolves live from the dashboard's provider catalog. 📖 [Provider Reference](docs/reference/PROVIDER_REFERENCE.md)</sub>
<sub>…and 330+ more — every icon resolves live from the dashboard's provider catalog. 📖 [Provider Reference](docs/reference/PROVIDER_REFERENCE.md)</sub>
<br/>
@@ -769,7 +769,7 @@ From inside the editor: open the **Extensions** view, search **"OmniRoute"**, cl
</div>
<img src="./docs/diagrams/privacy-local.svg" width="100%" alt="Private and local-first — your keys, your machine, your data; OmniRoute is a local proxy that never phones home. Eleven guarantees: runs 100% on your hardware (0 cloud hops), zero telemetry by default, credentials encrypted at rest (AES-256-GCM), no account or sign-up, hardened gateway (API-key scoping, IP filtering, rate limits, prompt-injection guard), loopback-only process routes, upstream header scrubbing, strictly opt-in PII redaction, sanitized errors that never leak internals, a local audit trail in your own SQLite, and MIT-licensed fully open-source code."/>
<img src="./docs/diagrams/privacy-local.svg" width="100%" alt="Private and local-first — OmniRoute's gateway and control plane run on your machine. Prompts are sent to the upstream provider selected for each request; OmniRoute adds no hosted prompt-processing hop and telemetry is disabled by default. Credentials are encrypted at rest with AES-256-GCM; controls include API-key scoping, IP filtering, rate limits, prompt-injection guards, upstream-header scrubbing, opt-in PII redaction, sanitized errors and a local SQLite audit trail. OmniRoute is MIT-licensed and self-hostable."/>
<sub>📖 [Authorization](docs/architecture/AUTHZ_GUIDE.md) · [Guardrails](docs/security/GUARDRAILS.md) · [Compliance](docs/security/COMPLIANCE.md)</sub>
@@ -810,7 +810,7 @@ Tokens are scoped `read` / `write` / `admin`; process-spawning routes stay loopb
<div align="left">
<img src="./docs/diagrams/cli-terminal.svg" width="50%" alt="Animated terminal demoing the OmniRoute CLI — omniroute providers list, omniroute combo list, omniroute health — cycling over the 80+ command surface: providers · oauth · keys · combo · nodes · models · cache · compression · cost · usage · quota · health · resilience · telemetry · logs · audit · mcp · a2a · cloud · memory · skills · eval · tunnel · backup · sync · webhooks · policy · pricing · translator · simulate …"/>
<img src="./docs/diagrams/cli-terminal.svg" width="50%" alt="Animated terminal demoing the OmniRoute CLI — omniroute providers list, omniroute combo list and omniroute health — cycling over the 85-command top-level surface: providers · oauth · keys · combo · nodes · models · cache · compression · cost · usage · quota · health · resilience · telemetry · logs · audit · mcp · a2a · cloud · memory · skills · eval · tunnel · backup · sync · webhooks · policy · pricing · translator · simulate …"/>
</div>
@@ -846,7 +846,7 @@ claude mcp add-server omniroute --type http --url http://localhost:20128/api/mcp
### 📖 How it works — pipeline, architecture & savings math
<img src="./docs/diagrams/compression-pipeline.svg" width="100%" alt="OmniRoute compression pipeline: a client request of 10,000 tokens passes through 12 stacked engines — Session-Dedup, CCR, Lite, RTK, Responses Tool Output, Headroom, Relevance, Caveman, Aggressive, LLMLingua-2, Ultra, OmniGlyph — and reaches the provider at about 1,080 tokens, up to 95% saved. Code, URLs and JSON are always preserved byte-perfect."/>
<img src="./docs/diagrams/compression-pipeline.svg" width="100%" alt="OmniRoute compression pipeline: an illustrative 10,000-token client request passes through 12 composable engines — Session-Dedup, CCR, Lite, RTK, Responses Tool Output, Headroom, Relevance, Caveman, Aggressive, LLMLingua-2, Ultra and OmniGlyph — and can reach the provider at about 1,080 tokens in the documented stacked example. Structured content is protected by preservation guards and per-step fidelity gates; explicit lossy or experimental modes may transform eligible content."/>
Default stacked combo runs `RTK → Caveman`. When both act on the same tool/context payload, savings compound:
@@ -1013,6 +1013,7 @@ Full table: [Docker Guide — runtime RAM](docs/guides/DOCKER_GUIDE.md#runtime-r
**🥟 Bun**
Standard `bun install` and global installation (`bun install -g omniroute`) are supported via Bun runtime detection:
- **Built-in `bun:sqlite`**: OmniRoute uses Bun's built-in `bun:sqlite` driver when running under Bun, falling back to `better-sqlite3` on Node.js or `sql.js`.
- **Automatic Webpack bundler selection**: Development (`bun run dev`) and production builds (`bun run build`) automatically detect Bun and disable Turbopack in favor of Webpack to prevent native V8 binding incompatibilities.
- **Dedicated Bun Dockerfile**: Multi-stage `Dockerfile.bun` for native Bun production deployments (`docker build -f Dockerfile.bun -t omniroute:bun .`).
@@ -1105,7 +1106,7 @@ same process on one port, so there is no separate CLI-only package today.
<div align="center">
<sub>Dados de cobertura social em 2026-08-17 · YT: 741 | TT: 137 | IG: 124 · Frescor (dias): YT 0 · TT 14 · IG 15</sub>
<sub>Snapshot do painel em 2026-08-24 · Catálogo bruto: YT 809 | TT 137 | IG 124 · Frescor (dias): YT 1 | TT 21 | IG 22</sub>
<table>
<tr>
@@ -1114,52 +1115,52 @@ same process on one port, so there is no separate CLI-only package today.
<img src="https://placehold.co/320x180/111827/FFFFFF?text=Instagram+Reel+%7C+nick_saraev&font=montserrat&bold=true" alt="Instagram Reel" width="300"/>
</a><br/>
<b>🎬 #1 — Instagram</b><br/>
<sub>nick_saraev — 1,628,910 views</sub>
<sub>nick_saraev — 3,042,474 views</sub>
</td>
<td align="center" width="320">
<a href="https://www.instagram.com/reel/DaSs65mMrHk/">
<img src="https://placehold.co/320x180/111827/FFFFFF?text=Instagram+Reel+%7C+theopenstack&font=montserrat&bold=true" alt="Instagram Reel — theopenstack" width="300"/>
</a><br/>
<b>🎬 #2 — Instagram</b><br/>
<sub>theopenstack — 692,419 views</sub>
</td>
<td align="center" width="320">
<a href="https://www.tiktok.com/@milesreevesai/video/7667980059189366019">
<img src="https://placehold.co/320x180/111827/FFFFFF?text=TikTok+%7C+milesreevesai&font=montserrat&bold=true" alt="TikTok — milesreevesai" width="300"/>
</a><br/>
<b>🎬 #3 — TikTok</b><br/>
<sub>milesreevesai — 620,400 views</sub>
</td>
<td align="center" width="320">
<a href="https://www.youtube.com/watch?v=QucgvbO5gsM">
<img src="https://img.youtube.com/vi/QucgvbO5gsM/maxresdefault.jpg" alt="YouTube — Vaibhav Sisinty" width="300"/>
</a><br/>
<b>🎬 #2 — YouTube</b><br/>
<sub>Vaibhav Sisinty — 373,084 views</sub>
<b>🎬 #4 — YouTube</b><br/>
<sub>Vaibhav Sisinty — 391,109 views</sub>
</td>
<td align="center" width="320">
<a href="https://www.youtube.com/shorts/fZIBK_4fKq8">
<img src="https://img.youtube.com/vi/fZIBK_4fKq8/maxresdefault.jpg" alt="YouTube Shorts" width="300"/>
<a href="https://www.instagram.com/reel/DbIt9AjK7-U/">
<img src="https://placehold.co/320x180/111827/FFFFFF?text=Instagram+Reel+%7C+buildwithai.club&font=montserrat&bold=true" alt="Instagram Reel — buildwithai.club" width="300"/>
</a><br/>
<b>🎬 #3YouTube Shorts</b><br/>
<sub>Nick Automates — 207,714 views</sub>
</td>
<td align="center" width="320">
<a href="https://www.tiktok.com/@milesreevesai/video/7667980059189366019">
<img src="https://placehold.co/320x180/111827/FFFFFF?text=TikTok+Top+1&font=montserrat&bold=true" alt="TikTok Thumbnail" width="300"/>
</a><br/>
<b>🎬 #4 — TikTok</b><br/>
<sub>milesreevesai — 620,400 views</sub>
</td>
<td align="center" width="320">
<a href="https://www.youtube.com/watch?v=LkP6ocAoQkk">
<img src="https://img.youtube.com/vi/LkP6ocAoQkk/maxresdefault.jpg" alt="Valency Labs" width="300"/>
</a><br/>
<b>🎬 #5 — YouTube</b><br/>
<sub>Valency Labs — 135,974 views</sub>
<b>🎬 #5Instagram</b><br/>
<sub>buildwithai.club — 347,652 views</sub>
</td>
</tr>
</table>
</div>
**Ranking completo (`v > 0`, maior alcance):**
**Ranking completo (URLs canônicas deduplicadas, `v > 0`, maior alcance):**
| #1 | #2 | #3 | #4 | #5 |
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| [nick_saraev — Instagram](https://www.instagram.com/reel/Da8ZthUPK98/) — **1,628,910** | [milesreevesai — TikTok](https://www.tiktok.com/@milesreevesai/video/7667980059189366019) — **620,400** | [Vaibhav Sisinty — YouTube](https://www.youtube.com/watch?v=QucgvbO5gsM) — **373,084** | [Nick Automates — YouTube Shorts](https://www.youtube.com/shorts/fZIBK_4fKq8) — **207,714** | [midudev — TikTok](https://www.tiktok.com/@midudev/video/7664636453544152342) — **177,800** |
| #1 | #2 | #3 | #4 | #5 |
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| [nick_saraev — Instagram](https://www.instagram.com/reel/Da8ZthUPK98/) — **3,042,474** | [theopenstack — Instagram](https://www.instagram.com/reel/DaSs65mMrHk/) — **692,419** | [milesreevesai — TikTok](https://www.tiktok.com/@milesreevesai/video/7667980059189366019) — **620,400** | [Vaibhav Sisinty — YouTube](https://www.youtube.com/watch?v=QucgvbO5gsM) — **391,109** | [buildwithai.club — Instagram](https://www.instagram.com/reel/DbIt9AjK7-U/) — **347,652** |
| #6 | #7 | #8 | #9 | #10 |
| ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| [theopenstack — Instagram](https://www.instagram.com/reel/DaSs65mMrHk/) — **155,453** | [t.ghoush.ai — TikTok](https://www.tiktok.com/@t.ghoush.ai/video/7669497680527248656) — **152,800** | [Valency Labs — YouTube](https://www.youtube.com/watch?v=LkP6ocAoQkk) — **135,974** | [Asati — YouTube](https://www.youtube.com/watch?v=JjPtJcqwhqg) — **126,130** | [Vaibhav Sisinty — YouTube](https://www.youtube.com/watch?v=NuNDpeZYQ28) — **122,672** |
| #6 | #7 | #8 | #9 | #10 |
| ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| [nivedan.ai — Instagram](https://www.instagram.com/reel/DbIrCksJiqq/) — **331,973** | [vaibhavsisinty — Instagram](https://www.instagram.com/reel/Dae05TSAK1l/) — **263,744** | [Nick Automates — YouTube Shorts](https://www.youtube.com/shorts/fZIBK_4fKq8) — **218,174** | [theroshankrishna — Instagram](https://www.instagram.com/reel/Dapjs58z0P0/) — **186,786** | [midudev — TikTok](https://www.tiktok.com/@midudev/video/7664636453544152342) — **177,800** |
Métricas de validação: 1002 vídeos rastreados · 7,069,190 visualizações conhecidas · 595 perfis/canais · 13+ idiomas · 13+ criadores.
Métricas canônicas em 2026-08-24: **1.029 vídeos únicos** · **11.132.922 visualizações conhecidas** (`v > 0`) · **639 canais/perfis por rede**. O painel bruto contém 1.070 linhas; 41 duplicatas do Instagram foram normalizadas pela URL canônica, mantendo a maior contagem por vídeo.
> 🎬 **Made a video about OmniRoute?** Open an [issue](https://github.com/diegosouzapw/OmniRoute/issues/new) or [discussion](https://github.com/diegosouzapw/OmniRoute/discussions) with the link — we'll feature it here.
@@ -1201,7 +1202,7 @@ Métricas de validação: 1002 vídeos rastreados · 7,069,190 visualizações c
<tr><td nowrap><b>Runtime</b></td><td>Node.js 22.x / 24.x LTS — <code>&gt;=22.22.2 &lt;23 || &gt;=24.0.0 &lt;27</code></td></tr>
<tr><td nowrap><b>Language</b></td><td>TypeScript 6.0 — <b>100% TypeScript</b> across <code>src/</code> and <code>open-sse/</code> (zero <code>any</code> in core since v2.0)</td></tr>
<tr><td nowrap><b>Framework</b></td><td>Next.js 16 + React 19 + Tailwind CSS 4</td></tr>
<tr><td nowrap><b>Database</b></td><td>better-sqlite3 (SQLite, WAL journaling) + LowDB (JSON legacy) — 120 domain modules, 159 migrations</td></tr>
<tr><td nowrap><b>Database</b></td><td>better-sqlite3 (SQLite, WAL journaling) + LowDB (JSON legacy) — 120 domain modules, 160 migrations</td></tr>
<tr><td nowrap><b>Memory</b></td><td>SQLite FTS5 full-text + int8-quantized vector embeddings, typed decay</td></tr>
<tr><td nowrap><b>Schemas</b></td><td>Zod 4 — MCP tool I/O validation + API contracts</td></tr>
<tr><td nowrap><b>Protocols</b></td><td>MCP (stdio / HTTP / SSE) + A2A v0.3 (JSON-RPC 2.0 + SSE)</td></tr>
@@ -1211,7 +1212,7 @@ Métricas de validação: 1002 vídeos rastreados · 7,069,190 visualizações c
<tr><td nowrap><b>Stealth</b></td><td>wreq-js — JA3 / JA4 TLS fingerprint impersonation, 3-level proxy</td></tr>
<tr><td nowrap><b>Resilience</b></td><td>Circuit breaker, exponential backoff, anti-thundering-herd, auto-combo self-healing</td></tr>
<tr><td nowrap><b>Logging</b></td><td>pino — structured JSON logs with request context</td></tr>
<tr><td nowrap><b>Testing</b></td><td>Node.js test runner + Vitest — <b>25,000+ test cases</b> across 3,300+ files (unit, integration, E2E, security, ecosystem)</td></tr>
<tr><td nowrap><b>Testing</b></td><td>Node.js test runner + Vitest — <b>39,000+ static test declarations</b> across 5,100+ tracked test files (unit, integration, E2E, security, ecosystem)</td></tr>
<tr><td nowrap><b>Platforms</b></td><td>Desktop (Electron) · Android (Termux) · PWA (any browser)</td></tr>
<tr><td nowrap><b>CI/CD</b></td><td>GitHub Actions — auto npm publish + Docker Hub on release</td></tr>
<tr><td nowrap><b>Links</b></td><td><a href="https://omniroute.online">Website</a> · <a href="https://www.npmjs.com/package/omniroute">npm</a> · <a href="https://hub.docker.com/r/diegosouzapw/omniroute">Docker Hub</a></td></tr>
@@ -1262,9 +1263,9 @@ Métricas de validação: 1002 vídeos rastreados · 7,069,190 visualizações c
<tr><td nowrap><b><a href="docs/compression/COMPRESSION_RULES_FORMAT.md">Compression Rules Format</a></b></td><td>JSON rule-pack schemas for Caveman and RTK filters</td></tr>
<tr><td nowrap><b><a href="docs/compression/COMPRESSION_LANGUAGE_PACKS.md">Compression Language Packs</a></b></td><td>Language detection and Caveman rule-pack authoring</td></tr>
<tr><td nowrap><b><a href="docs/architecture/RESILIENCE_GUIDE.md">Resilience Guide</a></b></td><td>Circuit breakers, cooldowns, queue, anti-thundering herd, TLS spoofing</td></tr>
<tr><td nowrap><b><a href="docs/routing/AUTO-COMBO.md">Auto-Combo Engine</a></b></td><td>14-factor scoring, mode packs, self-healing</td></tr>
<tr><td nowrap><b><a href="docs/routing/AUTO-COMBO.md">Auto-Combo Engine</a></b></td><td>15-factor scoring, mode packs, self-healing</td></tr>
<tr><td nowrap><b><a href="docs/ops/PROXY_GUIDE.md">Proxy Guide</a></b></td><td>3-level proxy system, 1proxy marketplace, registry CRUD</td></tr>
<tr><td nowrap><b><a href="docs/reference/FREE_TIERS.md">Free Tiers</a></b></td><td>90+ free providers consolidated directory (42 documented token pools / 495 models)</td></tr>
<tr><td nowrap><b><a href="docs/reference/FREE_TIERS.md">Free Tiers</a></b></td><td>Consolidated directory: 40 documented recurring pools / 455 cataloged free-tier entries</td></tr>
<tr><td nowrap><b><a href="docs/guides/FEATURES.md">Features Gallery</a></b></td><td>Visual dashboard tour with screenshots</td></tr>
<tr><td nowrap><b><a href="docs/architecture/CODEBASE_DOCUMENTATION.md">Codebase Documentation</a></b></td><td>Beginner-friendly codebase walkthrough</td></tr>
</table>
@@ -1275,7 +1276,7 @@ Métricas de validação: 1002 vídeos rastreados · 7,069,190 visualizações c
<tr><th align="left">Document</th><th align="left">Description</th></tr>
<tr><td nowrap><b><a href="docs/reference/API_REFERENCE.md">API Reference</a></b></td><td>All endpoints with examples</td></tr>
<tr><td nowrap><b><a href="docs/openapi.yaml">OpenAPI Spec</a></b></td><td>OpenAPI 3.0 specification</td></tr>
<tr><td nowrap><b><a href="open-sse/mcp-server/README.md">MCP Server</a></b></td><td>109 MCP tools, IDE configs, Python/TS/Go clients</td></tr>
<tr><td nowrap><b><a href="open-sse/mcp-server/README.md">MCP Server</a></b></td><td>110 MCP tools, IDE configs, Python/TS/Go clients</td></tr>
<tr><td nowrap><b><a href="docs/frameworks/MCP-SERVER.md">MCP Server Guide</a></b></td><td>MCP installation, transports, and tool reference</td></tr>
<tr><td nowrap><b><a href="src/lib/a2a/README.md">A2A Server</a></b></td><td>JSON-RPC 2.0 protocol, skills, streaming, task mgmt</td></tr>
<tr><td nowrap><b><a href="docs/frameworks/A2A-SERVER.md">A2A Server Guide</a></b></td><td>A2A agent card, tasks, skills, and streaming</td></tr>
@@ -1291,7 +1292,7 @@ Métricas de validação: 1002 vídeos rastreados · 7,069,190 visualizações c
<tr><td nowrap><b><a href="SECURITY.md">Security Policy</a></b></td><td>Vulnerability reporting and security practices</td></tr>
<tr><td nowrap><b><a href="docs/guides/I18N.md">i18n Guide</a></b></td><td>43-language support, translation workflow, RTL</td></tr>
<tr><td nowrap><b><a href="docs/ops/RELEASE_CHECKLIST.md">Release Checklist</a></b></td><td>Pre-release validation steps</td></tr>
<tr><td nowrap><b><a href="docs/ops/COVERAGE_PLAN.md">Coverage Plan</a></b></td><td>Test coverage strategy and 25,000+ test suite</td></tr>
<tr><td nowrap><b><a href="docs/ops/COVERAGE_PLAN.md">Coverage Plan</a></b></td><td>Test coverage strategy for 39,000+ static test declarations across 5,100+ tracked test files</td></tr>
</table>
<br/>
@@ -1302,93 +1303,123 @@ Métricas de validação: 1002 vídeos rastreados · 7,069,190 visualizações c
> OmniRoute is shaped by a passionate open-source community. These individuals have made exceptional contributions that directly impact the quality, stability, and reach of the project. **Thank you.**
### External contributors by merged pull requests
<table>
<tr><th align="center">Rank</th><th align="left">Contributor</th><th align="center">Merged PRs</th><th align="right">~Changed lines</th></tr>
<tr><td align="center">1</td><td align="left"><a href="https://github.com/backryun"><b>backryun</b></a></td><td align="center">190</td><td align="right">227,977</td></tr>
<tr><td align="center">2</td><td align="left"><a href="https://github.com/oyi77"><b>oyi77</b></a></td><td align="center">180</td><td align="right">407,678</td></tr>
<tr><td align="center">3</td><td align="left"><a href="https://github.com/rdself"><b>rdself</b></a></td><td align="center">145</td><td align="right">80,663</td></tr>
<tr><td align="center">4</td><td align="left"><a href="https://github.com/JxnLexn"><b>JxnLexn</b></a></td><td align="center">128</td><td align="right">387,049</td></tr>
<tr><td align="center">5</td><td align="left"><a href="https://github.com/KooshaPari"><b>KooshaPari</b></a></td><td align="center">101</td><td align="right">125,747</td></tr>
<tr><td align="center">6</td><td align="left"><a href="https://github.com/herjarsa"><b>herjarsa</b></a></td><td align="center">88</td><td align="right">230,872</td></tr>
<tr><td align="center">7</td><td align="left"><a href="https://github.com/RaviTharuma"><b>RaviTharuma</b></a></td><td align="center">79</td><td align="right">55,106</td></tr>
<tr><td align="center">8</td><td align="left"><a href="https://github.com/maxmad64bis"><b>maxmad64bis</b></a></td><td align="center">69</td><td align="right">394,715</td></tr>
<tr><td align="center">9</td><td align="left"><a href="https://github.com/artickc"><b>artickc</b></a></td><td align="center">59</td><td align="right">33,260</td></tr>
<tr><td align="center">10</td><td align="left"><a href="https://github.com/HouMinXi"><b>HouMinXi</b></a></td><td align="center">51</td><td align="right">47,334</td></tr>
<tr><td align="center">10</td><td align="left"><a href="https://github.com/chirag127"><b>chirag127</b></a></td><td align="center">51</td><td align="right">5,153</td></tr>
<tr><td align="center">12</td><td align="left"><a href="https://github.com/xz-dev"><b>xz-dev</b></a></td><td align="center">50</td><td align="right">245,976</td></tr>
<tr><td align="center">13</td><td align="left"><a href="https://github.com/hartmark"><b>hartmark</b></a></td><td align="center">47</td><td align="right">52,185</td></tr>
<tr><td align="center">14</td><td align="left"><a href="https://github.com/rqzbeh"><b>rqzbeh</b></a></td><td align="center">39</td><td align="right">143,181</td></tr>
<tr><td align="center">15</td><td align="left"><a href="https://github.com/dhaern"><b>dhaern</b></a></td><td align="center">34</td><td align="right">19,559</td></tr>
<tr><td align="center">16</td><td align="left"><a href="https://github.com/Dingding-leo"><b>Dingding-leo</b></a></td><td align="center">33</td><td align="right">1,986</td></tr>
<tr><td align="center">17</td><td align="left"><a href="https://github.com/NomenAK"><b>NomenAK</b></a></td><td align="center">32</td><td align="right">13,854</td></tr>
<tr><td align="center">18</td><td align="left"><a href="https://github.com/MumuTW"><b>MumuTW</b></a></td><td align="center">30</td><td align="right">16,953</td></tr>
<tr><td align="center">19</td><td align="left"><a href="https://github.com/benzntech"><b>benzntech</b></a></td><td align="center">29</td><td align="right">11,641</td></tr>
<tr><td align="center">20</td><td align="left"><a href="https://github.com/pacocartones"><b>pacocartones</b></a></td><td align="center">24</td><td align="right">9,331</td></tr>
<tr><td align="center">20</td><td align="left"><a href="https://github.com/Prudhvivuda"><b>Prudhvivuda</b></a></td><td align="center">24</td><td align="right">6,312</td></tr>
</table>
<sub>Frozen at live <code>release/v3.8.50</code> tip <code>dafb4ae808</code>, with merges through 2026-08-24 05:26:03 UTC. The paginated GitHub GraphQL census contains 5,911 merged PRs: 2,707 by the repository owner, 179 by Dependabot, and <b>3,025 external PRs from 535 distinct contributors</b>. “Changed lines” is GitHub additions + deletions and includes generated files, lockfiles, catalogs, translations and documentation; it is churn, not authored LOC. Ties at the cutoff are retained.</sub>
### GitHub-attributed commits
<table>
<tr>
<td align="center" width="160">
<a href="https://github.com/oyi77">
<img src="https://github.com/oyi77.png" width="40" style="border-radius:50%" alt="oyi77"/><br/>
<b>oyi77</b>
</a><br/>
<sub>🥇 213 commits • +114K lines</sub><br/>
<sub>Analytics engine, SQL aggregations,<br/>proxy marketplace, test coverage</sub>
</td>
<td align="center" width="160">
<a href="https://github.com/rdself">
<img src="https://github.com/rdself.png" width="40" style="border-radius:50%" alt="R.D. &amp; Randi"/><br/>
<b>R.D. &amp; Randi</b>
</a><br/>
<sub>🥈 108 commits • +38K lines</sub><br/>
<sub>Endpoints page, tunnel integrations,<br/>Docker workflows, A2A status, compression UI</sub>
</td>
<td align="center" width="160">
<a href="https://github.com/christopher-s">
<img src="https://github.com/christopher-s.png" width="40" style="border-radius:50%" alt="Chris Staley"/><br/>
<b>Chris Staley</b>
</a><br/>
<sub>🥉 70 commits • +1.8K lines</sub><br/>
<sub>SSE stream hardening, Responses API,<br/>Gemini pagination, test regression fixes</sub>
</td>
<td align="center" width="160">
<a href="https://github.com/zen0bit">
<img src="https://github.com/zen0bit.png" width="40" style="border-radius:50%" alt="zenobit"/><br/>
<b>zenobit</b>
</a><br/>
<sub>🏅 62 commits • +22K lines</sub><br/>
<sub>CI/CD pipeline, i18n for 33 languages,<br/>Void Linux package, platform fixes</sub>
</td>
<td align="center" width="160">
<a href="https://github.com/JxnLexn">
<img src="https://github.com/JxnLexn.png" width="40" style="border-radius:50%" alt="Jan Leon"/><br/>
<b>Jan Leon</b>
</a><br/>
<sub>🏅 58 commits • +22K lines</sub><br/>
<sub>Reasoning-effort routing, proxy controls,<br/>quota visibility, Live Zone compression</sub>
</td>
</tr>
<tr>
<td align="center" width="160">
<a href="https://github.com/backryun">
<img src="https://github.com/backryun.png" width="40" style="border-radius:50%" alt="backryun"/><br/>
<b>backryun</b>
</a><br/>
<sub>🏅 53 commits • +70K lines</sub><br/>
<sub>Provider catalog curation — Perplexity, Kimi,<br/>Cerebras, Copilot, LMArena refreshes</sub>
<sub>🥇 220 GitHub-attributed commits</sub>
</td>
<td align="center" width="160">
<a href="https://github.com/chirag127">
<img src="https://github.com/chirag127.png" width="40" style="border-radius:50%" alt="Chirag Singhal"/><br/>
<b>Chirag Singhal</b>
<a href="https://github.com/oyi77">
<img src="https://github.com/oyi77.png" width="40" style="border-radius:50%" alt="Paijo"/><br/>
<b>Paijo</b>
</a><br/>
<sub>🏅 46 commits • +4.8K lines</sub><br/>
<sub>Error sanitization, MITM prefill fix,<br/>fusion judge, breaker/429 correctness</sub>
<sub>🥈 219 GitHub-attributed commits</sub>
</td>
<td align="center" width="160">
<a href="https://github.com/kfiramar">
<img src="https://github.com/kfiramar.png" width="40" style="border-radius:50%" alt="kfiramar"/><br/>
<b>kfiramar</b>
<a href="https://github.com/rdself">
<img src="https://github.com/rdself.png" width="40" style="border-radius:50%" alt="Randi"/><br/>
<b>Randi</b>
</a><br/>
<sub>🏅 38 commits • +1.7K lines</sub><br/>
<sub>Codex websocket + passthrough, auth/onboarding,<br/>Electron hardening, DB migrations</sub>
<sub>🥉 108 GitHub-attributed commits</sub>
</td>
<td align="center" width="160">
<a href="https://github.com/benzntech">
<img src="https://github.com/benzntech.png" width="40" style="border-radius:50%" alt="Benson K B"/><br/>
<b>Benson K B</b>
<a href="https://github.com/RaviTharuma">
<img src="https://github.com/RaviTharuma.png" width="40" style="border-radius:50%" alt="Ravi Tharuma"/><br/>
<b>Ravi Tharuma</b>
</a><br/>
<sub>🏅 28 commits • +9.2K lines</sub><br/>
<sub>Electron desktop app, auto-updater,<br/>release build workflows, cross-platform CI</sub>
<sub>🏅 81 GitHub-attributed commits</sub>
</td>
<td align="center" width="160">
<a href="https://github.com/herjarsa">
<img src="https://github.com/herjarsa.png" width="40" style="border-radius:50%" alt="Hernan J. Ardila"/><br/>
<b>Hernan J. Ardila</b>
<a href="https://github.com/christopher-s">
<img src="https://github.com/christopher-s.png" width="40" style="border-radius:50%" alt="Chris"/><br/>
<b>Chris</b>
</a><br/>
<sub>🏅 25 commits • +174K lines</sub><br/>
<sub>Zero-latency combos, vision-bridge auto-routing,<br/>catalog context-length, resilience 429 hints</sub>
<sub>🏅 70 GitHub-attributed commits</sub>
</td>
<td align="center" width="160">
<a href="https://github.com/hartmark">
<img src="https://github.com/hartmark.png" width="40" style="border-radius:50%" alt="Markus Hartung"/><br/>
<b>Markus Hartung</b>
</a><br/>
<sub>🏅 69 GitHub-attributed commits · tied #6</sub>
</td>
</tr>
<tr>
<td align="center" width="160">
<a href="https://github.com/maxmad64bis">
<img src="https://github.com/maxmad64bis.png" width="40" style="border-radius:50%" alt="Dizzle"/><br/>
<b>Dizzle</b>
</a><br/>
<sub>🏅 69 GitHub-attributed commits · tied #6</sub>
</td>
<td align="center" width="160">
<a href="https://github.com/JxnLexn">
<img src="https://github.com/JxnLexn.png" width="40" style="border-radius:50%" alt="Jan Leon"/><br/>
<b>Jan Leon</b>
</a><br/>
<sub>🏅 64 GitHub-attributed commits</sub>
</td>
<td align="center" width="160">
<a href="https://github.com/zen0bit">
<img src="https://github.com/zen0bit.png" width="40" style="border-radius:50%" alt="zenobit"/><br/>
<b>zenobit</b>
</a><br/>
<sub>🏅 62 GitHub-attributed commits</sub>
</td>
<td align="center" width="160">
<a href="https://github.com/HouMinXi">
<img src="https://github.com/HouMinXi.png" width="40" style="border-radius:50%" alt="Bob.Hou"/><br/>
<b>Bob.Hou</b>
</a><br/>
<sub>🏅 51 GitHub-attributed commits · tied #10</sub>
</td>
<td align="center" width="160">
<a href="https://github.com/xz-dev">
<img src="https://github.com/xz-dev.png" width="40" style="border-radius:50%" alt="Xiangzhe"/><br/>
<b>Xiangzhe</b>
</a><br/>
<sub>🏅 51 GitHub-attributed commits · tied #10</sub>
</td>
</tr>
</table>
<sub>Rechecked at 2026-08-24 06:14:31 UTC: GitHub-attributed commits reported by the repository Contributors API for the <code>release/v3.8.50</code> default branch. The API returned 525 identities (415 users, 2 bots, 108 anonymous); this table excludes the maintainer, bots and anonymous identities and retains competition ties. It is distinct from both the merged-PR ranking above and the 639-person Git-metadata census below.</sub>
> 🙏 These contributors' features, bug fixes, and infrastructure improvements are a **core part** of what makes OmniRoute reliable and feature-rich. Every pull request, every test case, and every i18n translation file matters. Open source is built by people like them.
</div>
@@ -1405,25 +1436,48 @@ A heartfelt thank-you to the people who fund OmniRoute out of their own pocket
<table>
<tr>
<td align="center" width="180">
<a href="https://github.com/drewbitt">
<img src="https://github.com/drewbitt.png?size=140" width="72" style="border-radius:50%" alt="Andrew"/><br/>
<b>Andrew</b>
</a><br/>
<sub>💛 Active monthly sponsor</sub>
</td>
<td align="center" width="180">
<a href="https://github.com/psylligent">
<img src="https://github.com/psylligent.png?size=140" width="72" style="border-radius:50%" alt="Vlad I"/><br/>
<b>Vlad I</b>
</a><br/>
<sub>💛 Active monthly sponsor</sub>
</td>
<td align="center" width="180">
<a href="https://github.com/pacocartones">
<img src="https://github.com/pacocartones.png?size=140" width="72" style="border-radius:50%" alt="Paco Cartones"/><br/>
<b>Paco Cartones</b>
</a><br/>
<sub>💛 Active one-time sponsor</sub>
</td>
<td align="center" width="180">
<a href="https://github.com/igormorais123">
<img src="https://github.com/igormorais123.png?size=140" width="72" style="border-radius:50%" alt="Professor Igor Morais Vasconcelos"/><br/>
<b>Prof. Igor Morais</b>
</a><br/>
<sub>💛 Sponsor</sub>
<sub>💛 Past one-time supporter</sub>
</td>
<td align="center" width="180">
<a href="https://github.com/longtao77">
<img src="https://github.com/longtao77.png?size=140" width="72" style="border-radius:50%" alt="longtao"/><br/>
<b>longtao</b>
</a><br/>
<sub>💛 Sponsor</sub>
<sub>💛 Past one-time supporter</sub>
</td>
</tr>
</table>
<sub>… and others who prefer to stay private 💛</sub>
<sub>Public GitHub Sponsors revalidated on 2026-08-24. GitHub's <code>activeOnly</code> status determines the active labels above; previously disclosed public one-time supporters remain thanked, and private sponsors remain anonymous.</sub>
<b><a href="https://github.com/sponsors/diegosouzapw">💖 Become a sponsor →</a></b> — every dollar keeps OmniRoute free and independent.
</div>
@@ -1432,11 +1486,13 @@ A heartfelt thank-you to the people who fund OmniRoute out of their own pocket
<div align="center">
## 👥 320+ Contributors
## 👥 600+ Contributors
</div>
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=400&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=639&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
<sub>Audited on 2026-08-24 at frozen base <code>ac02c5b42f</code> and rechecked at live <code>release/v3.8.50</code> tip <code>dafb4ae808</code>: <b>639 normalized human Git identities</b> — 407 appear as commit authors (including the maintainer) and 232 only in explicit <code>Co-authored-by</code> trailers. The census normalizes GitHub noreply handles, excludes 26 bot/agent/service/placeholder identities, and does not merge ordinary email addresses merely because their display names match.</sub>
### How to Contribute
@@ -1453,7 +1509,8 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines.
```bash
# Create a release — npm publish happens automatically
gh release create v3.8.2 --title "v3.8.2" --generate-notes
VERSION=x.y.z
gh release create "v${VERSION}" --title "v${VERSION}" --generate-notes
```
<br/>
@@ -1495,88 +1552,108 @@ gh release create v3.8.2 --title "v3.8.2" --generate-notes
OmniRoute stands on the shoulders of giants. It started as a fork of **[9router](https://github.com/decolua/9router)** and a TypeScript port of the Go project **[CLIProxyAPI](https://github.com/router-for-me/CLIProxyAPI)** — and from there, every subsystem below was inspired by an open-source project that got there first. Each one shaped a concrete piece of OmniRoute. This is our thank-you to all of them. 🙏
> ⭐ star counts as of July 2026 — go give these projects a star.
> ⭐ star counts verified from GitHub's REST API on August 24, 2026 — go give these projects a star. Counts are an exact dated snapshot and will naturally change.
### 🧬 Lineage & gateway
<table>
<tr><th align="left">Project</th><th align="center">⭐</th><th align="left">How it inspired OmniRoute</th></tr>
<tr><td nowrap><b><a href="https://github.com/decolua/9router">9router</a></b></td><td align="center">22.7k</td><td>The original project this fork is built on — extended here with multi-modal APIs and a full TypeScript rewrite.</td></tr>
<tr><td nowrap><b><a href="https://github.com/router-for-me/CLIProxyAPI">CLIProxyAPI</a></b></td><td align="center">43.6k</td><td>The Go implementation that inspired this JavaScript / TypeScript port.</td></tr>
<tr><td nowrap><b><a href="https://github.com/BerriAI/litellm">LiteLLM</a></b></td><td align="center">54.0k</td><td>The AI gateway whose public pricing dataset feeds our cost-tracking sync and whose provider-normalization model informed our routing.</td></tr>
<tr><td nowrap><b><a href="https://github.com/decolua/9router">9router</a></b></td><td align="center">26,161</td><td>The original project this fork is built on — extended here with multi-modal APIs and a full TypeScript rewrite.</td></tr>
<tr><td nowrap><b><a href="https://github.com/router-for-me/CLIProxyAPI">CLIProxyAPI</a></b></td><td align="center">48,497</td><td>The Go implementation that inspired this JavaScript / TypeScript port.</td></tr>
<tr><td nowrap><b><a href="https://github.com/BerriAI/litellm">LiteLLM</a></b></td><td align="center">57,100</td><td>The AI gateway whose public pricing dataset feeds our cost-tracking sync and whose provider-normalization model informed our routing.</td></tr>
<tr><td nowrap><b><a href="https://github.com/miuuyy/codex-chatgpt-web">codex-chatgpt-web</a></b></td><td align="center">1,410</td><td>MIT source adapted into the vendored ChatGPT Web → Codex Responses bridge, including browser-session, response-framing, usage and web-search adapters.</td></tr>
<tr><td nowrap><b><a href="https://github.com/Alishahryar1/free-claude-code">free-claude-code</a></b></td><td align="center">48,112</td><td>Patterns ported into stream recovery, no-thinking aliases, fallback web search, sliding-window limits, log redaction and hardened launcher flows.</td></tr>
<tr><td nowrap><b><a href="https://github.com/standardagents/composer-api">composer-api</a></b></td><td align="center">322</td><td>Cursor Composer tool-choice, output-constraint and tool-commit patterns adapted into the native Cursor executor.</td></tr>
<tr><td nowrap><b><a href="https://github.com/ndycode/codex-multi-auth">codex-multi-auth</a></b></td><td align="center">457</td><td>Fresh-login and refresh-token rotation patterns ported into Codex OAuth reauthentication.</td></tr>
<tr><td nowrap><b><a href="https://github.com/ex-machina-co/opencode-anthropic-auth">opencode-anthropic-auth</a></b></td><td align="center">510</td><td>Claude Code-compatible transform defaults and billing-header behavior generalized into OmniRoute's config-driven bridge.</td></tr>
<tr><td nowrap><b><a href="https://github.com/520mmxx/grok2api-merged">grok2api-merged</a></b></td><td align="center">2</td><td>Its Grok model mappings, fake-TypeError Statsig generator, request and device defaults, and NDJSON response processor were materially adapted into OmniRoute's Grok Web executor.</td></tr>
<tr><td nowrap><b><a href="https://github.com/TQZHR/grok2api">TQZHR/grok2api</a></b></td><td align="center">705</td><td>The principal transitive code source behind grok2api-merged; its model, header, payload, Statsig and processor implementations are preserved in the Grok Web lineage.</td></tr>
<tr><td nowrap><b><a href="https://github.com/chenyme/grok2api">chenyme/grok2api</a></b></td><td align="center">7,520</td><td>The underlying MIT source for Grok payload and device defaults, the Statsig generator, and the <code>result.response</code> processor carried through TQZHR and grok2api-merged.</td></tr>
<tr><td nowrap><b><a href="https://github.com/miuzhaii/grok2api-pro">grok2api-pro</a></b></td><td align="center">27</td><td>A transitive source credited by grok2api-merged for its proxy-pool layer; OmniRoute preserves that lineage notice but does not claim a proxy-pool port in its bounded Grok Web executor.</td></tr>
<tr><td nowrap><b><a href="https://github.com/CNFlyCat/GrokProxy">GrokProxy</a></b></td><td align="center">50</td><td>Its cookie-authenticated Grok proxy and <code>result.response.token</code> streaming pattern informed OmniRoute's Grok Web transport.</td></tr>
<tr><td nowrap><b><a href="https://github.com/lianying1716/GrokBridge">GrokBridge</a></b></td><td align="center">5</td><td>The original Grok Web implementation consulted its HTTP/browser upstream design; its direct HTTP path derives from GrokProxy, so no independent code port is claimed.</td></tr>
<tr><td nowrap><b><a href="https://github.com/imjustprism/grok-web-api">grok-web-api</a></b></td><td align="center">14</td><td>Its Rust <code>ChatOptions</code> and response-envelope schemas informed OmniRoute's TypeScript Grok request and streaming-response types.</td></tr>
</table>
### 🗜️ Context & token compression — engines
<table>
<tr><th align="left">Project</th><th align="center">⭐</th><th align="left">How it inspired OmniRoute</th></tr>
<tr><td nowrap><b><a href="https://github.com/JuliusBrussee/caveman">Caveman</a></b></td><td align="center">90.8k</td><td>The viral "why use many token when few token do trick" project — its caveman-speak philosophy powers our standard compression mode and 30+ filler/condensation rules.</td></tr>
<tr><td nowrap><b><a href="https://github.com/rtk-ai/rtk">RTK Rust Token Killer</a></b></td><td align="center">71.8k</td><td>High-performance command-output compression — inspired our RTK engine, JSON filter DSL, raw-output recovery and the stacked RTK → Caveman pipeline.</td></tr>
<tr><td nowrap><b><a href="https://github.com/headroomlabs-ai/headroom">headroom</a></b></td><td align="center">60.1k</td><td>Reversible context-compression (SmartCrusher) — inspired our <code>headroom</code> engine and the <code>ccr</code> retrieve-marker pattern.</td></tr>
<tr><td nowrap><b><a href="https://github.com/microsoft/LLMLingua">LLMLingua</a></b></td><td align="center">6.5k</td><td>Prompt-compression research (LLMLingua / LLMLingua-2) — inspired our async, code-safe, fail-open <code>llmlingua</code> engine.</td></tr>
<tr><td nowrap><b><a href="https://github.com/atjsh/llmlingua-2-js">llmlingua-2-js</a></b></td><td align="center">30</td><td>The JS/ONNX port (MobileBERT / XLM-RoBERTa) used as the worker-thread backend for our LLMLingua engine.</td></tr>
<tr><td nowrap><b><a href="https://github.com/leninejunior/troglodita">Troglodita</a></b></td><td align="center">26</td><td>PT-BR token compression — powers our pt-BR language pack: pleonasm reduction and filler removal tuned for Brazilian-Portuguese grammar.</td></tr>
<tr><td nowrap><b><a href="https://github.com/DietrichGebert/ponytail">ponytail</a></b></td><td align="center">86.0k</td><td>The viral "lazy senior dev" YAGNI-coder skill — inspired our <b>less-code</b> Output Style: smallest-working-change steering that cuts _generated_ code (the output-axis sibling to Caveman's terse prose).</td></tr>
<tr><td nowrap><b><a href="https://github.com/JuliusBrussee/caveman">Caveman</a></b></td><td align="center">100,538</td><td>The viral "why use many token when few token do trick" project — its caveman-speak philosophy powers our standard compression mode and 30+ filler/condensation rules.</td></tr>
<tr><td nowrap><b><a href="https://github.com/rtk-ai/rtk">RTK Rust Token Killer</a></b></td><td align="center">77,185</td><td>High-performance command-output compression — inspired our RTK engine, JSON filter DSL, raw-output recovery and the stacked RTK → Caveman pipeline.</td></tr>
<tr><td nowrap><b><a href="https://github.com/headroomlabs-ai/headroom">headroom</a></b></td><td align="center">67,310</td><td>Reversible context-compression (SmartCrusher) — inspired our <code>headroom</code> engine and the <code>ccr</code> retrieve-marker pattern.</td></tr>
<tr><td nowrap><b><a href="https://github.com/microsoft/LLMLingua">LLMLingua</a></b></td><td align="center">6,598</td><td>Prompt-compression research (LLMLingua / LLMLingua-2) — inspired our async, code-safe, fail-open <code>llmlingua</code> engine.</td></tr>
<tr><td nowrap><b><a href="https://github.com/atjsh/llmlingua-2-js">llmlingua-2-js</a></b></td><td align="center">31</td><td>The JS/ONNX port (MobileBERT / XLM-RoBERTa) used as the worker-thread backend for our LLMLingua engine.</td></tr>
<tr><td nowrap><b><a href="https://github.com/leninejunior/troglodita">Troglodita</a></b></td><td align="center">40</td><td>PT-BR token compression — powers our pt-BR language pack: pleonasm reduction and filler removal tuned for Brazilian-Portuguese grammar.</td></tr>
<tr><td nowrap><b><a href="https://github.com/DietrichGebert/ponytail">ponytail</a></b></td><td align="center">108,957</td><td>The viral "lazy senior dev" YAGNI-coder skill — inspired our <b>less-code</b> Output Style: smallest-working-change steering that cuts _generated_ code (the output-axis sibling to Caveman's terse prose).</td></tr>
<tr><td nowrap><b><a href="https://github.com/ayghri/i-have-adhd">i-have-adhd</a></b></td><td align="center">23,526</td><td>Its action-first, ADHD-friendly response style was adapted into OmniRoute's concise output style across five languages.</td></tr>
</table>
### 🧩 Compact formats, token research & code-aware tooling
<table>
<tr><th align="left">Project</th><th align="center">⭐</th><th align="left">How it inspired OmniRoute</th></tr>
<tr><td nowrap><b><a href="https://github.com/toon-format/toon">TOON</a></b></td><td align="center">24.9k</td><td>Token-Oriented Object Notation — its columnar, header-plus-rows model shaped our tabular compaction stage.</td></tr>
<tr><td nowrap><b><a href="https://github.com/blackwell-systems/gcf">GCF Graph Compact Format</a></b></td><td align="center">22</td><td>First inspired our tabular compaction stage; now its zero-dependency, lossless generic-profile encoder is <b>vendored directly</b> as the Headroom codec (MIT, SPDX-marked), with later numeric-domain and count-mismatch correctness fixes.</td></tr>
<tr><td nowrap><b><a href="https://github.com/ooples/token-optimizer-mcp">token-optimizer-mcp</a></b></td><td align="center">444</td><td>Brotli/SQLite cache + per-session context-delta — inspired our <code>session-dedup</code> engine.</td></tr>
<tr><td nowrap><b><a href="https://github.com/Mibayy/token-savior">token-savior</a></b></td><td align="center">1.1k</td><td>Bash-output compaction + MCP profiles — inspired our compression bail-out discipline and MCP tool-manifest reduction.</td></tr>
<tr><td nowrap><b><a href="https://github.com/ppgranger/token-saver">token-saver</a></b></td><td align="center">117</td><td>Content-aware, per-file-type output compression with failure-aware bail-out — validated our per-type dispatch and minimum-gain skip.</td></tr>
<tr><td nowrap><b><a href="https://github.com/alexgreensh/token-optimizer">token-optimizer</a></b></td><td align="center">1.7k</td><td>"Find the ghost tokens" — its offload + recoverable-handle pattern informed our CCR offload thinking.</td></tr>
<tr><td nowrap><b><a href="https://github.com/Shweta-Mishra-ai/tokenmizer">TokenMizer</a></b></td><td align="center">16</td><td>A session-graph + cross-turn line-dedup blueprint that informed our session-dedup design.</td></tr>
<tr><td nowrap><b><a href="https://github.com/toon-format/toon">TOON</a></b></td><td align="center">25,233</td><td>Token-Oriented Object Notation — its columnar, header-plus-rows model shaped our tabular compaction stage.</td></tr>
<tr><td nowrap><b><a href="https://github.com/blackwell-systems/gcf">GCF Graph Compact Format</a></b></td><td align="center">41</td><td>Its compact graph format and generic-profile design informed OmniRoute's tabular compaction and Headroom codec format.</td></tr>
<tr><td nowrap><b><a href="https://github.com/blackwell-systems/gcf-typescript">gcf-typescript</a></b></td><td align="center">4</td><td>The MIT TypeScript implementation directly vendored and extended as the Headroom generic-profile codec.</td></tr>
<tr><td nowrap><b><a href="https://github.com/ooples/token-optimizer-mcp">token-optimizer-mcp</a></b></td><td align="center">494</td><td>Brotli/SQLite cache + per-session context-delta — inspired our <code>session-dedup</code> engine.</td></tr>
<tr><td nowrap><b><a href="https://github.com/Mibayy/token-savior">token-savior</a></b></td><td align="center">1,122</td><td>Bash-output compaction + MCP profiles — inspired our compression bail-out discipline and MCP tool-manifest reduction.</td></tr>
<tr><td nowrap><b><a href="https://github.com/ppgranger/token-saver">token-saver</a></b></td><td align="center">138</td><td>Content-aware, per-file-type output compression with failure-aware bail-out — validated our per-type dispatch and minimum-gain skip.</td></tr>
<tr><td nowrap><b><a href="https://github.com/alexgreensh/token-optimizer">token-optimizer</a></b></td><td align="center">1,951</td><td>"Find the ghost tokens" — its offload + recoverable-handle pattern informed our CCR offload thinking.</td></tr>
<tr><td nowrap><b><a href="https://github.com/Shweta-Mishra-ai/tokenmizer">TokenMizer</a></b></td><td align="center">28</td><td>A session-graph + cross-turn line-dedup blueprint that informed our session-dedup design.</td></tr>
<tr><td nowrap><b><a href="https://github.com/jessefreitas/OmniCompress">OmniCompress</a></b></td><td align="center">3</td><td>Rust columnar-JSON + content-addressed retrieve + cross-message dedup — validated our <code>headroom</code>/<code>ccr</code>/<code>session-dedup</code> engine design and the cache-stable "compressed form is position-independent" invariant.</td></tr>
<tr><td nowrap><b><a href="https://github.com/atlassian-labs/mcp-compressor">mcp-compressor</a></b></td><td align="center">98</td><td>MCP tool-schema/description compression — informed our MCP tool-manifest cardinality reduction.</td></tr>
<tr><td nowrap><b><a href="https://github.com/pdavis68/RepoMapper">RepoMapper</a></b></td><td align="center">187</td><td>Aider-style repo-map ranking — informed our repo-map / retrieval-ranking exploration.</td></tr>
<tr><td nowrap><b><a href="https://github.com/atlassian-labs/mcp-compressor">mcp-compressor</a></b></td><td align="center">113</td><td>MCP tool-schema/description compression — informed our MCP tool-manifest cardinality reduction.</td></tr>
<tr><td nowrap><b><a href="https://github.com/pdavis68/RepoMapper">RepoMapper</a></b></td><td align="center">197</td><td>Aider-style repo-map ranking — informed our repo-map / retrieval-ranking exploration.</td></tr>
<tr><td nowrap><b><a href="https://github.com/mrsimpson/quiet-shell-mcp">quiet-shell-mcp</a></b></td><td align="center">4</td><td>Declarative shell-output reduction over MCP — validated our declarative bash-output compaction.</td></tr>
<tr><td nowrap><b><a href="https://github.com/dsherret/ts-morph">ts-morph</a></b></td><td align="center">6.1k</td><td>TypeScript Compiler API toolkit — inspired our parser-based comment removal that preserves string, template and regex literals.</td></tr>
<tr><td nowrap><b><a href="https://github.com/dsherret/ts-morph">ts-morph</a></b></td><td align="center">6,162</td><td>TypeScript Compiler API toolkit — inspired our parser-based comment removal that preserves string, template and regex literals.</td></tr>
</table>
### 🧠 Memory & RAG
<table>
<tr><th align="left">Project</th><th align="center">⭐</th><th align="left">How it inspired OmniRoute</th></tr>
<tr><td nowrap><b><a href="https://github.com/mem0ai/mem0">Mem0</a></b></td><td align="center">61.2k</td><td>Universal memory layer — its proxy-as-write/read-boundary model shaped our memory architecture.</td></tr>
<tr><td nowrap><b><a href="https://github.com/letta-ai/letta">Letta (MemGPT)</a></b></td><td align="center">23.9k</td><td>Stateful agents with tiered memory — inspired our Context Control & Recovery (CCR) tiered model.</td></tr>
<tr><td nowrap><b><a href="https://github.com/onestardao/WFGY">WFGY</a></b></td><td align="center">1.8k</td><td>The ProblemMap taxonomy of 16 recurring RAG/LLM failure modes — the shared vocabulary in our troubleshooting guide.</td></tr>
<tr><td nowrap><b><a href="https://github.com/mem0ai/mem0">Mem0</a></b></td><td align="center">63,902</td><td>Universal memory layer — its proxy-as-write/read-boundary model shaped our memory architecture.</td></tr>
<tr><td nowrap><b><a href="https://github.com/letta-ai/letta">Letta (MemGPT)</a></b></td><td align="center">24,382</td><td>Stateful agents with tiered memory — inspired our Context Control & Recovery (CCR) tiered model.</td></tr>
<tr><td nowrap><b><a href="https://github.com/onestardao/WFGY">WFGY</a></b></td><td align="center">1,781</td><td>The ProblemMap taxonomy of 16 recurring RAG/LLM failure modes — the shared vocabulary in our troubleshooting guide.</td></tr>
</table>
### 🛰️ Traffic inspection, MITM & transparent proxy
<table>
<tr><th align="left">Project</th><th align="center">⭐</th><th align="left">How it inspired OmniRoute</th></tr>
<tr><td nowrap><b><a href="https://github.com/chouzz/llm-interceptor">llm-interceptor</a></b></td><td align="center">49</td><td>MITM interception/analysis of coding-assistant ↔ LLM traffic — our Traffic Inspector ports its SSE merge, conversation normalization, host passthrough and secret masking (MIT).</td></tr>
<tr><td nowrap><b><a href="https://github.com/InterceptSuite/ProxyBridge">ProxyBridge</a></b></td><td align="center">5.5k</td><td>Transparent per-process proxy routing — inspired our crash-safe MITM teardown, socket idle-timeouts, <code>/proc</code> process attribution and TPROXY capture.</td></tr>
<tr><td nowrap><b><a href="https://github.com/chouzz/llm-interceptor">llm-interceptor</a></b></td><td align="center">66</td><td>MITM interception/analysis of coding-assistant ↔ LLM traffic — our Traffic Inspector ports its SSE merge, conversation normalization, host passthrough and secret masking. The upstream's complete license text is still under provenance review.</td></tr>
<tr><td nowrap><b><a href="https://github.com/InterceptSuite/ProxyBridge">ProxyBridge</a></b></td><td align="center">5,995</td><td>Transparent per-process proxy routing — inspired our crash-safe MITM teardown, socket idle-timeouts, <code>/proc</code> process attribution and TPROXY capture.</td></tr>
</table>
### 📚 Model data, observability & UI
<table>
<tr><th align="left">Project</th><th align="center">⭐</th><th align="left">How it inspired OmniRoute</th></tr>
<tr><td nowrap><b><a href="https://github.com/anomalyco/models.dev">models.dev</a></b></td><td align="center">6.0k</td><td>Open database of AI model specs, pricing and capabilities — synced natively into our model catalog.</td></tr>
<tr><td nowrap><b><a href="https://github.com/xyflow/xyflow">React Flow / xyflow</a></b></td><td align="center">37.7k</td><td>The node-based graph library powering our real-time Compression Studio and Combo/Routing Studio.</td></tr>
<tr><td nowrap><b><a href="https://github.com/langchain-ai/langgraph">LangGraph</a></b></td><td align="center">37.6k</td><td>LangGraph Studio's live workflow-graph visualization inspired our Studios' real-time cascade view.</td></tr>
<tr><td nowrap><b><a href="https://github.com/langfuse/langfuse">Langfuse</a></b></td><td align="center">31.4k</td><td>Its trace → span → generation observability model shaped our Compression Studio waterfall.</td></tr>
<tr><td nowrap><b><a href="https://github.com/kiali/kiali">Kiali</a></b></td><td align="center">3.6k</td><td>Istio service-mesh observability — inspired our circuit-breaker badges and error-edge visuals in the Routing/Combo Studio.</td></tr>
<tr><td nowrap><b><a href="https://github.com/lobehub/lobe-icons">lobe-icons</a></b></td><td align="center">2.2k</td><td>AI/LLM brand logos that render the provider icons across our dashboard.</td></tr>
<tr><td nowrap><b><a href="https://github.com/anomalyco/models.dev">models.dev</a></b></td><td align="center">6,555</td><td>Open database of AI model specs, pricing and capabilities — synced natively into our model catalog.</td></tr>
<tr><td nowrap><b><a href="https://github.com/xyflow/xyflow">React Flow / xyflow</a></b></td><td align="center">38,108</td><td>The node-based graph library powering our real-time Compression Studio and Combo/Routing Studio.</td></tr>
<tr><td nowrap><b><a href="https://github.com/langchain-ai/langgraph">LangGraph</a></b></td><td align="center">40,314</td><td>LangGraph Studio's live workflow-graph visualization inspired our Studios' real-time cascade view.</td></tr>
<tr><td nowrap><b><a href="https://github.com/langfuse/langfuse">Langfuse</a></b></td><td align="center">33,592</td><td>Its trace → span → generation observability model shaped our Compression Studio waterfall.</td></tr>
<tr><td nowrap><b><a href="https://github.com/kiali/kiali">Kiali</a></b></td><td align="center">3,631</td><td>Istio service-mesh observability — inspired our circuit-breaker badges and error-edge visuals in the Routing/Combo Studio.</td></tr>
<tr><td nowrap><b><a href="https://github.com/lobehub/lobe-icons">lobe-icons</a></b></td><td align="center">2,428</td><td>AI/LLM brand logos that render the provider icons across our dashboard.</td></tr>
<tr><td nowrap><b><a href="https://github.com/lipis/flag-icons">flag-icons</a></b></td><td align="center">12,354</td><td>Provides the MIT-licensed SVG flags used by the README language selector.</td></tr>
</table>
### 🛡️ Security
<table>
<tr><th align="left">Project</th><th align="center">⭐</th><th align="left">How it inspired OmniRoute</th></tr>
<tr><td nowrap><b><a href="https://github.com/tldrsec/awesome-secure-defaults">awesome-secure-defaults</a></b></td><td align="center">710</td><td>A curated list of secure-by-default libraries that guides our security choices (Helmet.js, DOMPurify, ssrf-req-filter, safe-regex, Google Tink).</td></tr>
<tr><td nowrap><b><a href="https://github.com/tldrsec/awesome-secure-defaults">awesome-secure-defaults</a></b></td><td align="center">721</td><td>A curated list of secure-by-default libraries that guides our security choices (Helmet.js, DOMPurify, ssrf-req-filter, safe-regex, Google Tink).</td></tr>
</table>
### 🧭 Complementary tools
<table>
<tr><th align="left">Project</th><th align="center">⭐</th><th align="left">How it inspired OmniRoute</th></tr>
<tr><td nowrap><b><a href="https://github.com/BlockRunAI/ClawRouter">ClawRouter</a></b></td><td align="center">6,564</td><td>Inspired request deduplication, emergency zero-cost fallback, pluggable Auto-Combo strategies and multilingual intent classification.</td></tr>
<tr><td nowrap><b><a href="https://github.com/lbjlaq/Antigravity-Manager">Antigravity-Manager</a></b></td><td align="center">30,652</td><td>Its account-aware model remapping, executable-path validation and plan-label behavior informed OmniRoute's Antigravity runtime.</td></tr>
<tr><td nowrap><b><a href="https://github.com/jlcodes99/vscode-antigravity-cockpit">vscode-antigravity-cockpit</a></b></td><td align="center">4,817</td><td>Its compact quota-reset countdown format inspired the corresponding provider-limit display in OmniRoute.</td></tr>
<tr><td nowrap><b><a href="https://github.com/iOfficeAI/AionUi">AionUi</a></b></td><td align="center">32,230</td><td>Its ACP integrations inspired OmniRoute's automatic detection of installed CLI agents.</td></tr>
<tr><td nowrap><b><a href="https://github.com/steipete/CodexBar">CodexBar</a></b></td><td align="center">20,507</td><td>Identified the Grok Build quota surface; OmniRoute then verified and corrected the live wire format independently.</td></tr>
</table>
## 📄 License
@@ -1589,7 +1666,7 @@ MIT License - see [LICENSE](LICENSE) for details.
**[⬆ Back to top](#-omniroute)** · Built with ❤️ for the open-source AI community.
<sub>OmniRoute v3.8.49 · Node ≥22.22.2 · MIT License · <a href="https://omniroute.online">omniroute.online</a></sub>
<sub>OmniRoute v3.8.50 · Node ≥22.22.2 · MIT License · <a href="https://omniroute.online">omniroute.online</a></sub>
</div>
<!-- GitHub Discussions enabled for community Q&A -->

View File

@@ -169,7 +169,8 @@ export async function runSetupClaudeCommand(opts = {}) {
let detail = `HTTP ${res.status}`;
try {
const errorBody = await res.json();
const serverMsg = errorBody?.error?.message || errorBody?.error || errorBody?.message || "";
const serverMsg =
errorBody?.error?.message || errorBody?.error || errorBody?.message || "";
if (serverMsg) detail += `${serverMsg}`;
} catch {}
throw new Error(detail);

View File

@@ -24,9 +24,9 @@ function wantsProviderSetup(opts) {
return opts.addProvider || Boolean(opts.provider) || Boolean(opts.apiKey);
}
async function resolvePassword(opts, prompt, nonInteractive) {
if (opts.password) return opts.password;
if (process.env.INITIAL_PASSWORD) return process.env.INITIAL_PASSWORD;
async function resolvePassword(opts, prompt, nonInteractive, settings) {
if (opts.password !== undefined) return opts.password;
if (!settings.password && process.env.INITIAL_PASSWORD) return process.env.INITIAL_PASSWORD;
if (nonInteractive) return "";
const answer = await prompt.ask("Set an admin password now? [y/N]", "N");
@@ -41,9 +41,9 @@ async function resolvePassword(opts, prompt, nonInteractive) {
}
async function setupPassword(db, opts, prompt, nonInteractive) {
const password = await resolvePassword(opts, prompt, nonInteractive);
const settings = getSettings(db);
const password = await resolvePassword(opts, prompt, nonInteractive, settings);
if (!password) {
const settings = getSettings(db);
if (!settings.password) {
updateSettings(db, { requireLogin: false });
}

View File

@@ -5,6 +5,7 @@ import { fileURLToPath } from "node:url";
import { execFile } from "node:child_process";
import { promisify } from "node:util";
import { t } from "../i18n.mjs";
import { npmBin, npmExecOptions } from "../npm-exec.mjs";
const execFileAsync = promisify(execFile);
@@ -31,9 +32,13 @@ export async function getCurrentVersion() {
// they were already on the latest version (#4376). `execFn` is injectable for tests.
export async function getLatestVersion(execFn = execFileAsync) {
try {
const { stdout } = await execFn("npm", ["view", "omniroute", "version", "--prefer-online"], {
timeout: 15000,
});
// argv is all literals, so enabling the shell on win32 cannot splice a
// runtime value into the command line (Hard Rule #13).
const { stdout } = await execFn(
npmBin(),
["view", "omniroute", "version", "--prefer-online"],
npmExecOptions(process.platform, { timeoutMs: 15000 })
);
return stdout.trim();
} catch {
return null;
@@ -114,9 +119,11 @@ export async function runUpdateCommand(opts = {}) {
if (showChangelog) {
try {
const { stdout } = await execFileAsync("npm", ["view", "omniroute", "changelog"], {
timeout: 10000,
});
const { stdout } = await execFileAsync(
npmBin(),
["view", "omniroute", "changelog"],
npmExecOptions(process.platform, { timeoutMs: 15000 })
);
if (stdout.trim()) {
console.log(stdout.trim());
} else {

View File

@@ -26,7 +26,8 @@
"testFailed": "Teste do provedor falhou: {error}",
"loginEnabled": "Login: habilitado (senha atualizada)",
"loginDisabled": "Login: desabilitado",
"providerInfo": "Provedor: {info}"
"providerInfo": "Provedor: {info}",
"opencode": "Instala e configura o plugin @omniroute/opencode-plugin incluído para o OpenCode"
},
"doctor": {
"title": "OmniRoute Doctor",
@@ -254,7 +255,9 @@
"no_recovery": "Desabilitar reinício automático em crash (modo debug)",
"max_restarts": "Máximo de reinícios em 30s antes de desistir (padrão: 2)",
"tray": "Mostrar ícone na bandeja do sistema (apenas desktop, opt-in)",
"no_tray": "Desabilitar ícone na bandeja do sistema"
"no_tray": "Desabilitar ícone na bandeja do sistema",
"tls_cert": "Caminho para um certificado TLS (PEM) para servir HTTPS (também OMNIROUTE_TLS_CERT)",
"tls_key": "Caminho para a chave privada TLS (PEM) para servir HTTPS (também OMNIROUTE_TLS_KEY)"
},
"backup": {
"title": "Backup",

View File

@@ -38,7 +38,8 @@
"testFailed": "提供者测试失败:{error}",
"loginEnabled": "登录:已启用(密码已更新)",
"loginDisabled": "登录:已禁用",
"providerInfo": "提供者:{info}"
"providerInfo": "提供者:{info}",
"opencode": "安装并配置随附的 @omniroute/opencode-plugin 以用于 OpenCode"
},
"doctor": {
"title": "OmniRoute 诊断",
@@ -252,7 +253,9 @@
"no_recovery": "禁用崩溃自动重启(调试模式)",
"max_restarts": "30 秒内的最大崩溃重启次数默认2",
"tray": "显示系统托盘图标(仅桌面,选择加入)",
"no_tray": "禁用系统托盘图标"
"no_tray": "禁用系统托盘图标",
"tls_cert": "用于提供 HTTPS 服务的 TLS 证书PEM路径也可用 OMNIROUTE_TLS_CERT",
"tls_key": "用于提供 HTTPS 服务的 TLS 私钥PEM路径也可用 OMNIROUTE_TLS_KEY"
},
"backup": {
"title": "备份",
@@ -1258,5 +1261,69 @@
"search": "搜索 npm 注册表中的可用插件",
"update": "更新已安装的插件",
"scaffold": "搭建新的插件模板"
},
"authExport": {
"description": "导出已解密的提供者凭据(仅限本地,明文输出)",
"idOpt": "仅导出与此 id/名称/提供者匹配的连接",
"formatOpt": "输出格式json 或 env",
"outOpt": "将输出写入文件而非标准输出(以 0600 权限写入)",
"forceOpt": "确认你了解此操作会打印/写入明文密钥",
"warning": "⚠ 此操作会打印/写入已解密的明文 API 密钥和 OAuth 令牌。请确保你的屏幕、shell 历史记录以及任何输出文件保持私密。",
"confirmHeading": "⚠ 警告:此操作会以明文导出已解密的提供者凭据",
"confirmBody": "此命令会为所选连接解密并打印/写入 apiKey、accessToken、refreshToken 和\nidToken。请将输出视为机密。",
"confirmFooter": "如需确认,请运行:\n omniroute auth export --force",
"missingKey": "导出凭据需要 STORAGE_ENCRYPTION_KEY。",
"notFound": "未找到连接:{id}",
"invalidFormat": "无效格式:{format}。请使用 json 或 env。"
},
"radar": {
"description": "检查并同步本地 Radar 目录订阅源",
"status": "显示本地 Radar 设置和订阅源缓存状态",
"sync": "通过本地服务器同步目录、推荐、优惠和 Intel"
},
"launch": {
"description": "启动指向 OmniRoute 的 Claude Code本地或远程使用 --profile",
"token": "Claude 客户端应发送的令牌ANTHROPIC_AUTH_TOKEN",
"notRunning": "无法在 {port} 访问 OmniRoute。请使用 “omniroute serve” 启动它。",
"notFound": "在 PATH 中未找到 “claude” CLI。"
},
"run": {
"description": "通过 OmniRoute 启动受支持的 CLI 目标"
},
"setupClaude": {
"description": "从 OmniRoute 模型目录生成 ~/.claude/profiles 的 Claude Code 配置文件"
},
"connect": {
"description": "连接到远程 OmniRoute 服务器并进入远程模式"
},
"tokens": {
"description": "管理限定范围的 CLI 访问令牌(远程模式)"
},
"configure": {
"description": "从活动服务器选择提供者+模型并配置受支持的本地 CLI"
},
"launchCodex": {
"description": "启动指向 OmniRoute 的 Codex CLI本地或远程 VPS"
},
"setupCodex": {
"description": "从 OmniRoute 实时模型目录生成 ~/.codex 配置文件"
},
"packs": {
"description": "管理可选的运行时包ML / 浏览器自动化)",
"listDescription": "列出可选包及其安装状态",
"installDescription": "将可选包安装到 DATA_DIR",
"verifyDescription": "根据随附的校验和索引验证已安装的包",
"removeDescription": "移除已安装的可选包",
"sourceOpt": "存放包负载和包索引的目录",
"warnNoIndex": "未找到 optional-packs.index.json —— 此检出无法进行安装/验证(桌面捆绑包会附带它)",
"errUnknown": "未知的包:{name}",
"errNoIndex": "未找到包索引;请通过 --source <dir> 传入存放包负载的目录(桌面捆绑包会将其附带在应用旁)",
"installed": "包 “{name}” 已安装并在 {dir} 验证通过",
"restartHint": "请重启 OmniRoute 服务器(或桌面应用),以便运行时加载该包",
"removed": "包 “{name}” 已移除",
"notInstalled": "包 “{name}” 未安装",
"verifyOk": "所有已安装的包均已验证通过",
"verifyFailed": "{count} 个包验证失败",
"noneInstalled": "未安装可选包"
}
}

View File

@@ -38,7 +38,8 @@
"testFailed": "提供者測試失敗:{error}",
"loginEnabled": "登入:已啟用(密碼已更新)",
"loginDisabled": "登入:已停用",
"providerInfo": "提供者:{info}"
"providerInfo": "提供者:{info}",
"opencode": "安裝並配置隨附的 @omniroute/opencode-plugin 以用於 OpenCode"
},
"doctor": {
"title": "OmniRoute 診斷",
@@ -252,7 +253,9 @@
"no_recovery": "停用崩潰自動重啟(除錯模式)",
"max_restarts": "30 秒內的最大崩潰重啟次數預設2",
"tray": "顯示系統托盤圖示(僅桌面,選擇加入)",
"no_tray": "停用系統托盤圖示"
"no_tray": "停用系統托盤圖示",
"tls_cert": "用於提供 HTTPS 服務的 TLS 憑證PEM路徑也可用 OMNIROUTE_TLS_CERT",
"tls_key": "用於提供 HTTPS 服務的 TLS 私鑰PEM路徑也可用 OMNIROUTE_TLS_KEY"
},
"backup": {
"title": "備份",
@@ -1258,5 +1261,69 @@
"search": "搜尋 npm 登錄檔中的可用外掛",
"update": "更新已安裝的外掛",
"scaffold": "搭建新的外掛模板"
},
"authExport": {
"description": "匯出已解密的提供者憑據(僅限本機,明文輸出)",
"idOpt": "僅匯出與此 id/名稱/提供者相符的連線",
"formatOpt": "輸出格式json 或 env",
"outOpt": "將輸出寫入檔案而非標準輸出(以 0600 權限寫入)",
"forceOpt": "確認你了解此操作會列印/寫入明文密鑰",
"warning": "⚠ 此操作會列印/寫入已解密的明文 API 金鑰和 OAuth 令牌。請確保你的螢幕、shell 歷史記錄以及任何輸出檔案保持私密。",
"confirmHeading": "⚠ 警告:此操作會以明文匯出已解密的提供者憑據",
"confirmBody": "此命令會為所選連線解密並列印/寫入 apiKey、accessToken、refreshToken 和\nidToken。請將輸出視為機密。",
"confirmFooter": "如需確認,請執行:\n omniroute auth export --force",
"missingKey": "匯出憑據需要 STORAGE_ENCRYPTION_KEY。",
"notFound": "找不到連線:{id}",
"invalidFormat": "無效格式:{format}。請使用 json 或 env。"
},
"radar": {
"description": "檢查並同步本機 Radar 目錄訂閱來源",
"status": "顯示本機 Radar 設定和訂閱來源快取狀態",
"sync": "透過本機伺服器同步目錄、推薦、優惠和 Intel"
},
"launch": {
"description": "啟動指向 OmniRoute 的 Claude Code本機或遠端使用 --profile",
"token": "Claude 用戶端應傳送的令牌ANTHROPIC_AUTH_TOKEN",
"notRunning": "無法在 {port} 存取 OmniRoute。請使用「omniroute serve」啟動它。",
"notFound": "在 PATH 中找不到「claude」CLI。"
},
"run": {
"description": "透過 OmniRoute 啟動受支援的 CLI 目標"
},
"setupClaude": {
"description": "從 OmniRoute 模型目錄產生 ~/.claude/profiles 的 Claude Code 配置檔"
},
"connect": {
"description": "連線到遠端 OmniRoute 伺服器並進入遠端模式"
},
"tokens": {
"description": "管理限定範圍的 CLI 存取令牌(遠端模式)"
},
"configure": {
"description": "從使用中的伺服器選擇提供者+模型並配置受支援的本機 CLI"
},
"launchCodex": {
"description": "啟動指向 OmniRoute 的 Codex CLI本機或遠端 VPS"
},
"setupCodex": {
"description": "從 OmniRoute 即時模型目錄產生 ~/.codex 配置檔"
},
"packs": {
"description": "管理可選的執行階段套件ML / 瀏覽器自動化)",
"listDescription": "列出可選套件及其安裝狀態",
"installDescription": "將可選套件安裝到 DATA_DIR",
"verifyDescription": "根據隨附的總和檢查碼索引驗證已安裝的套件",
"removeDescription": "移除已安裝的可選套件",
"sourceOpt": "存放套件負載和套件索引的目錄",
"warnNoIndex": "找不到 optional-packs.index.json —— 此檢出無法進行安裝/驗證(桌面套件會隨附它)",
"errUnknown": "未知的套件:{name}",
"errNoIndex": "找不到套件索引;請透過 --source <dir> 傳入存放套件負載的目錄(桌面套件會將其隨附在應用程式旁)",
"installed": "套件「{name}」已安裝並在 {dir} 驗證通過",
"restartHint": "請重新啟動 OmniRoute 伺服器(或桌面應用程式),以便執行階段載入該套件",
"removed": "套件「{name}」已移除",
"notInstalled": "套件「{name}」未安裝",
"verifyOk": "所有已安裝的套件均已驗證通過",
"verifyFailed": "{count} 個套件驗證失敗",
"noneInstalled": "未安裝可選套件"
}
}

34
bin/cli/npm-exec.mjs Normal file
View File

@@ -0,0 +1,34 @@
// Spawning npm from the CLI, on every platform.
//
// On Windows npm is `npm.cmd`, a batch wrapper. Node ≥ 24 refuses to spawn a
// `.cmd` without a shell (nodejs/node#52554), and a bare `npm` can additionally
// resolve to an extensionless shim that `CreateProcess` cannot execute — so the
// call fails with `EINVAL` or `ENOENT` while npm works fine in the same terminal.
// `src/lib/services/installers/utils.ts` already solves this for the server; this
// is the same rule for the `bin/cli` entry points, which cannot import TypeScript.
//
// SECURITY (Hard Rule #13): enabling the shell means the SHELL splits the command
// line, not `execFile`. Every argv element passed alongside these options must be
// a literal — never a runtime value — or it must be validated first. Callers that
// need to pass a user-supplied name have to guard it themselves.
/** The npm binary to spawn on this platform. */
export function npmBin(platform = process.platform) {
const isBun = Boolean(process.versions.bun);
if (platform === "win32") return isBun ? "bun.exe" : "npm.cmd";
return isBun ? "bun" : "npm";
}
/**
* `execFile` / `spawnSync` options for an npm call.
*
* @param {NodeJS.Platform} platform
* @param {{ timeoutMs?: number, stdio?: string }} [options]
*/
export function npmExecOptions(platform = process.platform, options = {}) {
const base = {};
if (options.timeoutMs !== undefined) base.timeout = options.timeoutMs;
if (options.stdio !== undefined) base.stdio = options.stdio;
if (platform !== "win32") return { ...base, shell: false };
return { ...base, shell: true, windowsHide: true };
}

View File

@@ -26,6 +26,17 @@ let resolvedCached = null;
export async function loadSqliteRuntime() {
if (resolvedCached) return resolvedCached;
if (process.versions.bun) {
try {
const bunSqlite = await import("bun:sqlite");
resolvedCached = {
driver: { kind: "bun-sqlite", Database: bunSqlite.Database },
source: "bun-sqlite",
};
return resolvedCached;
} catch {}
}
const bundled = await tryLoadBundled();
if (bundled) {
resolvedCached = { driver: bundled, source: "bundled" };

View File

@@ -2,6 +2,7 @@ import { existsSync, mkdirSync, writeFileSync, chmodSync } from "node:fs";
import { join } from "node:path";
import { homedir } from "node:os";
import { execSync } from "node:child_process";
import { pathToFileURL } from "node:url";
const RUNTIME_DIR = join(homedir(), ".omniroute", "runtime");
// systray2 is a maintained fork with prebuilt binaries — installed lazily at runtime,
@@ -16,6 +17,16 @@ export const SYSTRAY_PACKAGE = "systray2";
export const SYSTRAY_VERSION = "2.1.4";
const SYSTRAY_SPEC = `${SYSTRAY_PACKAGE}@${SYSTRAY_VERSION}`;
// Dynamic `import()` resolves its specifier as a URL, not a filesystem path.
// On Windows the lazily-installed systray2 lives at an absolute path whose
// leading drive letter the ESM loader parses as an unsupported URL scheme
// (e.g. `c:`) and rejects. Build a file:// URL so the tray import works on
// Windows too. Same defect fixed for the CLI db-fallback imports in #11238,
// missed at this call site.
export function systrayModuleSpecifier(runtimeDir: string): string {
return pathToFileURL(join(runtimeDir, "node_modules", SYSTRAY_PACKAGE)).href;
}
export function resolveSystrayBinName(platform: NodeJS.Platform): string | null {
if (platform === "win32") return "tray_windows_release.exe";
if (platform === "darwin") return "tray_darwin_release";
@@ -60,8 +71,7 @@ export async function loadSystray(): Promise<(new (...args: unknown[]) => unknow
// drop the +x bit on extraction (observed on macOS).
chmodSystrayBinAt(RUNTIME_DIR, process.platform);
try {
const modPath = join(RUNTIME_DIR, "node_modules", SYSTRAY_PACKAGE);
const mod = await import(modPath);
const mod = await import(systrayModuleSpecifier(RUNTIME_DIR));
return (mod.default ?? mod.SysTray ?? mod) as (new (...args: unknown[]) => unknown) | null;
} catch (err) {
console.warn(`[omniroute] tray runtime import failed: ${(err as Error).message}`);

View File

@@ -114,10 +114,13 @@ function writeLinuxSystemdUnit(cliPath) {
const unitDir = dirname(linuxSystemdUnitPath());
mkdirSync(unitDir, { recursive: true });
const envFile = join(userHomeDir(), ".omniroute", ".env");
const nodeBinDir = dirname(process.execPath);
const userLocalBin = join(userHomeDir(), ".local", "bin");
const pathEnv = `${nodeBinDir}:${userLocalBin}:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin`;
const lines = [
"[Unit]",
"Description=OmniRoute AI proxy router",
"After=network-online.target",
"After=network-online.target graphical-session.target",
"Wants=network-online.target",
"",
"[Service]",
@@ -134,6 +137,7 @@ function writeLinuxSystemdUnit(cliPath) {
`ExecStart=${buildServeExecLine(cliPath, { tray: false })}`,
"Restart=on-failure",
"RestartSec=5",
`Environment="PATH=${pathEnv}"`,
];
if (existsSync(envFile)) lines.push(`EnvironmentFile=-${envFile}`);
lines.push("", "[Install]", "WantedBy=default.target", "");

View File

@@ -0,0 +1,37 @@
import { sep } from "node:path";
/**
* A `.env` inside the installed package directory does not survive an update:
* `npm i -g` replaces that directory wholesale, and postinstall recreates the
* file from `.env.example`. The CLI announces every env file it loads without
* distinguishing the ones that last from the one that doesn't.
*
* Returns the warning to print, or null when there is nothing worth saying.
*
* Two conditions, both required, so a development checkout never sees this:
* - the file sits inside the package root, and that root is inside a
* `node_modules` directory — i.e. an installed package, not a checkout,
* where the same path is stable and documented in SETUP_GUIDE.md;
* - the file actually supplied at least one value. First writer wins, so a
* file entirely shadowed by a durable one supplied nothing, and losing it
* costs nothing.
*
* @param {{ envPath: string, packageRoot: string, durableEnvPath: string, suppliedKeys: boolean }} args
* @returns {string | null}
*/
export function describeVolatileEnvWarning({ envPath, packageRoot, durableEnvPath, suppliedKeys }) {
if (!suppliedKeys) return null;
if (envPath === durableEnvPath) return null;
if (!isInsideInstalledPackage(packageRoot)) return null;
if (!envPath.startsWith(packageRoot + sep)) return null;
return (
`${envPath} lives inside the installed package: updating OmniRoute replaces it. ` +
`Move the values you set to ${durableEnvPath}, which updates leave alone.`
);
}
/** True when the path sits under a `node_modules` directory. */
function isInsideInstalledPackage(dir) {
return typeof dir === "string" && dir.split(sep).includes("node_modules");
}

View File

@@ -29,6 +29,7 @@ import { getDefaultDataDir } from "./cli/data-dir.mjs";
import { shouldProvisionStorageKey } from "./cli/utils/storageKeyProvision.mjs";
import { isVersionFastPath } from "./cli/utils/versionFastPath.mjs";
import { parseEnvValue } from "./cli/utils/parseEnvValue.mjs";
import { describeVolatileEnvWarning } from "./cli/utils/volatileEnvPath.mjs";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
@@ -91,9 +92,7 @@ function migrateElectronServerEnv(dataDir) {
const serverEnvPath = join(dataDir, "server.env");
if (existsSync(envPath) || !existsSync(serverEnvPath)) return;
writeFileSync(envPath, readFileSync(serverEnvPath, "utf-8"), "utf-8");
console.log(
` \x1b[2m♻ Migrated Electron secrets from ${serverEnvPath} to ${envPath}\x1b[0m`
);
console.log(` \x1b[2m♻ Migrated Electron secrets from ${serverEnvPath} to ${envPath}\x1b[0m`);
} catch {
// Ignore errors migrating server.env — fall back to normal env loading below.
}
@@ -164,6 +163,21 @@ function loadEnvFile() {
const setter = winner ? winner : "the environment";
console.warn(` \x1b[33m⚠ ${key} in ${loser} is ignored, ${setter} set it first\x1b[0m`);
}
// The package directory is replaced by the next `npm i -g`, so a .env kept
// there is silently lost. Say so once, and only when that file actually
// supplied something.
const durableEnvPath = join(process.env.DATA_DIR || getDefaultDataDir(), ".env");
const suppliedKeys = [...keyOrigin.values()].some((origin) => origin === join(ROOT, ".env"));
const volatileWarning = describeVolatileEnvWarning({
envPath: join(ROOT, ".env"),
packageRoot: ROOT,
durableEnvPath,
suppliedKeys,
});
if (volatileWarning && loadedEnvPaths.includes(join(ROOT, ".env"))) {
console.warn(` \x1b[33m⚠ ${volatileWarning}\x1b[0m`);
}
}
loadEnvFile();
@@ -247,16 +261,16 @@ if (shouldProvisionStorageKey(process.argv)) {
const langEnv = process.env.OMNIROUTE_LANG;
const chosen = langArg || langEnv;
if (chosen) {
const { setLocale } = await import(
pathToFileURL(join(ROOT, "bin", "cli", "i18n.mjs")).href
);
const { setLocale } = await import(pathToFileURL(join(ROOT, "bin", "cli", "i18n.mjs")).href);
setLocale(chosen);
}
}
// Register update notifier — checks npm once per 24h, notifies on exit via stderr.
const _pkg = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8"));
const _notifier = updateNotifier ? updateNotifier({ pkg: _pkg, updateCheckInterval: 1000 * 60 * 60 * 24 }) : null;
const _notifier = updateNotifier
? updateNotifier({ pkg: _pkg, updateCheckInterval: 1000 * 60 * 60 * 24 })
: null;
process.on("exit", () => {
if (!_notifier || !_notifier.update) return;
if (process.env.OMNIROUTE_NO_UPDATE_NOTIFIER) return;
@@ -265,7 +279,15 @@ process.on("exit", () => {
const outputIdx = process.argv.indexOf("--output");
const outputVal = outputIdx >= 0 ? process.argv[outputIdx + 1] : null;
if (outputVal === "json" || outputVal === "jsonl" || outputVal === "csv") return;
if (process.argv.some((a) => a.startsWith("--output=json") || a.startsWith("--output=jsonl") || a.startsWith("--output=csv"))) return;
if (
process.argv.some(
(a) =>
a.startsWith("--output=json") ||
a.startsWith("--output=jsonl") ||
a.startsWith("--output=csv")
)
)
return;
if (_notifier.update) {
_notifier.notify({
defer: false,

View File

@@ -0,0 +1 @@
- **feat(audio):** proxy native ElevenLabs voices, text-to-speech, and speech-to-text HTTP routes through stored OmniRoute credentials, preserving query strings, multipart uploads, binary responses, and upstream errors (#10556).

View File

@@ -0,0 +1 @@
- Added Google AI Studio Gemini batch text-to-speech support through `POST /v1/audio/speech`.

View File

@@ -0,0 +1,3 @@
- Run synchronous RTK and Caveman request compression in a bounded worker-thread pool, keeping
large `/v1/responses` compression heaps outside the HTTP isolate while preserving strict
fail-open behavior and per-engine telemetry.

View File

@@ -0,0 +1 @@
- **feat(routing):** subscription-first auto groupings — `auto/subscription` routes only through plan-included connections with a documented hard-stop overage and fails closed on exhaustion, while `auto/thrifty` orders the pool `subscription → keyless → free → cheap → premium` and steps up one rung at a time as each is exhausted. Billing class comes from a curated per-connection catalog (uncurated is treated as metered, never plan-included), both reuse STRICT_ZERO_COST's per-connection verification, and a quota reading whose `resetAt` has passed is now refreshed regardless of TTL so routing returns to plan capacity as soon as it resets ([#11146](https://github.com/diegosouzapw/OmniRoute/pull/11146))

View File

@@ -0,0 +1 @@
- **feat(providers):** publish a management-authenticated versioned web-session credential contract from OmniRoute's canonical browser credential metadata ([#11340](https://github.com/diegosouzapw/OmniRoute/pull/11340)) — thanks @Zartharas

View File

@@ -0,0 +1 @@
- **feat(video bridge):** harden the optional drill-down cache substrate with exact-path broker policy, canonical principal/session/media isolation, independent retained-byte quotas, cancellation-safe commits, rejection of excess or non-canonical Base64 padding and non-JPEG/truncated media, warning-sensitive full JPEG canonicalization that strips trailing polyglot bytes, server-derived dimensions, and auditable derivation metadata; production tenant binding and multi-resolution selection remain follow-up work ([#11369](https://github.com/diegosouzapw/OmniRoute/pull/11369))

View File

@@ -0,0 +1 @@
- **feat(search):** Add Xquik X search with typed results, credential validation, REST routing, and MCP selection ([#11370](https://github.com/diegosouzapw/OmniRoute/pull/11370)) — thanks @kriptoburak

View File

@@ -0,0 +1 @@
- **feat(video):** add an opt-in focused analysis mode that safely uses a normalized, 500-code-point latest-user hint for task-aware frame captions while preserving full-mode prompts, temporal-window isolation, and cache identity without storing raw task text ([#11383](https://github.com/diegosouzapw/OmniRoute/pull/11383)).

View File

@@ -0,0 +1 @@
- **feat(dashboard):** surface durable exclusive managed leases in the existing Sessions view, keeping leased clients visible across idle gaps while marking connections with in-flight work as active ([#11389](https://github.com/diegosouzapw/OmniRoute/pull/11389)) — thanks @KaspaPulse

View File

@@ -0,0 +1 @@
- **build(bun):** allow Turbopack bundler flag on Bun 1.4+ with configurable Webpack fallback ([#11471](https://github.com/diegosouzapw/OmniRoute/pull/11471)) — thanks @TheDemonTuan

View File

@@ -0,0 +1 @@
- **feat(rankings):** the Free Provider Rankings page shows what each provider actually served over the last 24 h. It ranked by ELO alone, which left a provider that answers every call with an error in first place; the usage data was already served by the API but never requested. A provider with too small a sample shows a dash, not a number ([#11546](https://github.com/diegosouzapw/OmniRoute/pull/11546))

View File

@@ -0,0 +1 @@
- feat(services): show sanitized CLIProxyAPI account health from its authenticated management API without exposing credentials, file paths, or raw account metadata (#6342)

View File

@@ -0,0 +1 @@
- **feat(providers):** add **Nimble** as a web-search and web-fetch provider (`nimble-search`) — `/v1/search` routes to Nimble's search API at `lite` depth (locale, freshness and include/exclude domain filters mapped onto the shared request contract), and `/v1/web/fetch` routes to Nimble Extract, which covers all four fetch formats (`markdown`, `html`, `links`, `screenshot`) from a single call. One API key serves both surfaces.

View File

@@ -0,0 +1 @@
- **feat(providers):** Add **Opper** as an API-key gateway provider — EU-hosted AI gateway with 700+ models from 30+ providers behind one OpenAI-compatible API and one key (`OPPER_API_KEY`); model ids use `provider/model` format (e.g. `anthropic/claude-sonnet-4-6`, `openai/gpt-5`); live model catalog at `https://api.opper.ai/v3/compat/models`; entry mirrors `requesty` (same shape, `passthroughModels: true`, no static seed)

View File

@@ -0,0 +1 @@
- **fix(github):** proactive credential health now verifies GitHub access tokens through the existing Copilot token exchange, marks only a confirmed `401 Unauthorized` as expired, and leaves rate limits, permission failures, upstream failures, and network errors routable ([#10352](https://github.com/diegosouzapw/OmniRoute/issues/10352)) — thanks @RaviTharuma

View File

@@ -0,0 +1 @@
- **fix(providers):** Antigravity OAuth marks connects with no Cloud Code projectId as degraded instead of a false "Connected"; BYOP detection at connect time, auto-disable of confirmed-missing accounts, and selection-side rotation ([#11284](https://github.com/diegosouzapw/OmniRoute/issues/11284))

View File

@@ -0,0 +1 @@
- **fix(db):** group model patterns escape regex metacharacters, so `gpt-4.1*` no longer matches `gpt-4o1-preview` and a pattern like `gpt-4(*` no longer throws `SyntaxError` out of the completion and `/v1/models` paths ([#11311](https://github.com/diegosouzapw/OmniRoute/pull/11311))

View File

@@ -0,0 +1 @@
- **fix(db):** the upstream proxy URL check judges the host by address instead of by spelling, so `http://[::ffff:169.254.169.254]`, `[::ffff:10.0.0.5]`, ULA/link-local and CGNAT targets are refused like their dotted equivalents ([#11319](https://github.com/diegosouzapw/OmniRoute/pull/11319))

View File

@@ -0,0 +1 @@
- **fix(i18n):** three `pt` strings had dropped their placeholders — the cache tile's subtitle repeated its own label instead of showing `{total}` — and a unit test now enforces placeholder parity with `en` across all locales ([#11325](https://github.com/diegosouzapw/OmniRoute/pull/11325))

View File

@@ -0,0 +1 @@
- **fix(kie):** map the remaining `google-imagen/*` KIE Market catalog ids (`nano-banana`, `nano-banana-pro`, `nano-banana-edit`) to their real, KIE-documented upstream `model` values — `#11225`'s fix only covered `nano-banana-2` ([#11326](https://github.com/diegosouzapw/OmniRoute/pull/11326)).

View File

@@ -0,0 +1 @@
- **fix(security):** `proxy-authorization` and `proxy-authenticate` are refused as upstream/custom headers, so a proxy credential is no longer forwarded to the model provider — the canonical denylist now matches the RFC 7230 §6.1 set the rest of the codebase already strips ([#11328](https://github.com/diegosouzapw/OmniRoute/pull/11328))

View File

@@ -0,0 +1 @@
- **fix(video-bridge):** fall back to the deterministic active-window midpoint when a one-frame scene-aware budget cannot preserve both timeline ends; a real FFmpeg fixture matrix now covers rapid cuts, gradual changes, static and short clips, and detector failure ([#11344](https://github.com/diegosouzapw/OmniRoute/pull/11344)).

View File

@@ -0,0 +1 @@
- **fix(translator):** Codex Responses tool calls translated for Claude clients no longer emit a duplicate `tool_use` block with the same ID and an empty name, preventing Claude Code from terminating with `No such tool available` ([#11347](https://github.com/diegosouzapw/OmniRoute/pull/11347))

View File

@@ -0,0 +1 @@
- **fix(video-bridge):** burn high-contrast timestamps into every bounded contact-sheet cell and add a real-model A/B harness whose promotion verdict stays `HOLD` until token, latency, and quality evidence is actually executed ([#11350](https://github.com/diegosouzapw/OmniRoute/pull/11350))

View File

@@ -0,0 +1 @@
- **fix(video):** fingerprint protected Video Bridge bytes, coalesce concurrent work, and fail open when the bounded TTL/LRU result cache is unavailable or corrupt ([#11362](https://github.com/diegosouzapw/OmniRoute/pull/11362))

View File

@@ -0,0 +1 @@
- **fix(catalog):** keep large `/v1/models` builds responsive by reusing the build-local capability snapshot throughout enrichment and Auto-Combo preparation, yielding cooperatively while constructing virtual candidate pools, and avoiding unrelated synchronous database diagnostics on the cache-TTL read path ([#11367](https://github.com/diegosouzapw/OmniRoute/pull/11367))

View File

@@ -0,0 +1 @@
- **Provider connections:** keep `tokenExpiresAt` when a connection is created. The create-path allowlist omitted it, so every insert stored NULL and the dashboard token badge could read a fresh connection as expired until its first background refresh ([#11368](https://github.com/diegosouzapw/OmniRoute/pull/11368)).

View File

@@ -0,0 +1 @@
- **fix(video):** apply the caption-frame cap after bounded visual deduplication, preserve first/final candidates plus small high-contrast motion and text changes, and version the dedup policy in result-cache identity ([#11382](https://github.com/diegosouzapw/OmniRoute/pull/11382)).

View File

@@ -0,0 +1 @@
- **Live dashboard:** honour the WebSocket port reported by `/api/v1/ws?handshake=1` instead of the port compiled into the bundle, so a `LIVE_WS_PORT` override reaches prebuilt Docker/npm images and Combo Studio Live connects behind a reverse proxy ([#11331](https://github.com/diegosouzapw/OmniRoute/issues/11331)).

View File

@@ -0,0 +1 @@
- **fix(dashboard):** Model Database sync interval slider ticks now match the thumb position — checkpoint-space slider with magnetic snap on release ([#11394](https://github.com/diegosouzapw/OmniRoute/pull/11394)) — thanks @An0nym0us92

View File

@@ -0,0 +1 @@
- **fix(radar):** the catalog feed cache now keeps `generatedAt`, the date the feed's data was built, next to `fetchedAt`, the date this install downloaded it (#11435). The feed schema requires that date and the sync path validates it, but the cache dropped it — so a feed fetched minutes ago and one carrying weeks-old figures looked identical to everything downstream, including the dashboard's "Last fetched" line. `getRadarCatalog().meta` and `GET /api/radar/status` now report both dates, the latter as its own field rather than folded into `version` — and omitted entirely for the offers and intel caches, which keep no build date, where a `null` would read as "unknown" rather than "never stored". The dashboard still shows only the fetch time; surfacing the build date there needs a new translated label and is left to a follow-up. Rows cached before migration 163 read back as `null`: unknown stays unknown instead of borrowing the fetch time. The referrals cache has persisted the same date since migration 142.

View File

@@ -0,0 +1 @@
- **fix(cli):** postinstall no longer fills `JWT_SECRET` and `API_KEY_SECRET` in the installed package's `.env` (#11436). `.env.example` ships both blank on purpose: the server restores them from its durable store, or generates and persists them there, in `ensureSecrets()`. Pre-filling them defeated that — the file lives inside the package directory, so `npm i -g` replaced it and postinstall wrote _different_ values, while `ensureSecrets()` (which only acts on an empty variable) never got to restore the real ones. Both secrets rotated silently on every update, invalidating dashboard sessions and API-key CRCs. `STORAGE_ENCRYPTION_KEY` left the same list for the same reason in #1622; its comment pointed at a function that no longer exists and now names the real provisioning path.

View File

@@ -0,0 +1 @@
- **fix(cli):** the CLI now says when a loaded `.env` lives inside the installed package directory (#11437). It already announces every env file it reads, without distinguishing the ones that survive an update from the one that does not: `npm i -g` replaces the package directory wholesale, so values set there are gone at the next update, silently. The warning names the durable path to move them to, and fires only when that file actually supplied a value — a file entirely shadowed by a durable one supplied nothing. A development checkout stays silent: there the same path is stable and documented in `SETUP_GUIDE.md`.

View File

@@ -0,0 +1 @@
- **fix(free-models):** the shared `isFreeModel()` predicate no longer reports catalog entries marked `freeType: "discontinued"` as free, so `hidePaidModels` can't route to Pollinations' seven premium models that now require a paid key ([#11441](https://github.com/diegosouzapw/OmniRoute/pull/11441))

View File

@@ -0,0 +1 @@
- **fix(bun):** use native `bun:sqlite` in `bootstrap-env` and `sync-env` to avoid loading `better-sqlite3` N-API addon during Bun startup ([#11468](https://github.com/diegosouzapw/OmniRoute/pull/11468)) — thanks @TheDemonTuan

View File

@@ -0,0 +1 @@
- **fix(docker-bun):** make `Dockerfile.bun` install reliable with pre-install script helpers and native `bun:sqlite` smoke check ([#11470](https://github.com/diegosouzapw/OmniRoute/pull/11470)) — thanks @TheDemonTuan

View File

@@ -0,0 +1 @@
- **fix(docker-bun):** remove every vendored `better-sqlite3` native addon from the Bun runtime image so startup cannot abort before the `bun:sqlite` fallback ([#11482](https://github.com/diegosouzapw/OmniRoute/pull/11482)) — thanks @TheDemonTuan

View File

@@ -0,0 +1 @@
- **fix(autoCombo):** effort/alias model variants (`gpt-5.6-sol-xhigh`, `gpt-5.6`, cursor's `claude-4.6-opus-high`) inherit their base model's task fitness instead of falling to the wildcard 0.5 ([#11492](https://github.com/diegosouzapw/OmniRoute/pull/11492))

View File

@@ -0,0 +1 @@
- **fix(intelligence):** Arena ELO sync stores a synthesized base-model row for every effort/harness variant (`claude-opus-5-max``claude-opus-5`, `gpt-5.6-sol-xhigh (codex-harness)``gpt-5.6-sol`), so bare model requests reach the synced intelligence layer instead of the static fallback table; the hand-maintained `MODEL_ALIAS_MAP` — which collapsed generations (`gpt-5.5``gpt-5`) — is gone ([#11506](https://github.com/diegosouzapw/OmniRoute/pull/11506))

View File

@@ -0,0 +1 @@
- **fix(autoCombo,sse):** catalog hygiene — the static task-fitness table no longer ranks retired models above live ones (dead rows dropped, patterns matched on segment boundaries), the 7 deprecation aliases that forwarded to retired or non-existent models now point at the vendors' published replacements, an alias is no longer rewritten when the serving provider offers the id as-is, and a new `check:model-lifecycle` gate diffs both tables against a vendor lifecycle snapshot ([#11507](https://github.com/diegosouzapw/OmniRoute/pull/11507))

View File

@@ -0,0 +1 @@
- Treat Docker publishing from a non-default release branch as an expected skip instead of a failed workflow, while preserving the guard that prevents it from overwriting the `next` channel.

View File

@@ -0,0 +1 @@
- fix(search): prefer credentialed providers over duckduckgo-free fallback (#11524) — the fallback-only loop ran before the credentialed-providers loop in `executeWebSearch`, making configured providers unreachable when `duckduckgo-free` was available.

View File

@@ -0,0 +1 @@
- **fix(ci):** protocol-clients E2E harness boots the peer-stamped custom server (`run-next.mjs dev`) instead of the bare `next` CLI, so `LOCAL_ONLY` locality resolves from the real TCP peer stamp and `/api/mcp/audit` answers 200 (open bootstrap preserved via an `OMNIROUTE_E2E_BOOTSTRAP_MODE=open` credential clear in `run-next.mjs`, pinned to loopback `HOST`) instead of a deterministic 403 (#11535)

View File

@@ -0,0 +1 @@
- **fix(docs):** the Auto-Combo engine is described with the number of factors it actually declares. Four different counts were in circulation — 6, 9, 13 and 14 across `AGENTS.md`, four guides and six code comments — while `DEFAULT_WEIGHTS` declares 15. `check:docs-counts` now reads that number from the source, so adding a factor without updating the prose fails CI ([#11545](https://github.com/diegosouzapw/OmniRoute/pull/11545))

View File

@@ -0,0 +1 @@
- **fix(quota-share):** in-flight leases are per request, so an aborted request's slot ages out instead of being kept alive by later traffic on the same connection ([#11547](https://github.com/diegosouzapw/OmniRoute/pull/11547)) — thanks @abhisheksharma2411

View File

@@ -0,0 +1 @@
- The free-tier summary route now serves the refreshed Radar catalog when the feed is active — the same numbers the dashboard shows — and states which catalog answered plus its real build date, instead of always reporting release-frozen figures with a stale curation date. The supporter-key live feed stays reserved to authenticated callers of the instance.

View File

@@ -0,0 +1 @@
- fix(chat): shed any of the matched provider-node's routing identifiers (public prefix or internal id) before model lookup, so composites like `<connId>/<connId>/<model>` no longer reach upstream verbatim (#11557)

View File

@@ -0,0 +1 @@
- **fix(cache):** a semantic-cache entry now expires on its TTL instead of surviving until the next UTC midnight, and `dbEntries` stops counting expired rows ([#11573](https://github.com/diegosouzapw/OmniRoute/pull/11573))

View File

@@ -0,0 +1 @@
- **fix(api):** `/v1/models` schedules its stale-while-revalidate rebuild through Next's `after()` again, so a stale catalog reaches the client before the rebuild blocks the event loop ([#11574](https://github.com/diegosouzapw/OmniRoute/pull/11574))

View File

@@ -0,0 +1 @@
- **fix(check):** the `known-symbols` executor conformance gate awaits the now-async `getExecutor()`, so it stops reporting all 142 registered aliases as dead symbols and can detect a lazy import that fails ([#11582](https://github.com/diegosouzapw/OmniRoute/pull/11582))

View File

@@ -0,0 +1 @@
- **fix(pack):** register `bin/cli/utils/volatileEnvPath.mjs` in `PACK_ARTIFACT_REQUIRED_PATHS`, so the prune can no longer silently drop a module the published CLI imports on every boot ([#11588](https://github.com/diegosouzapw/OmniRoute/pull/11588))

View File

@@ -0,0 +1 @@
- **i18n(vi):** translate the five reliability-column strings on the free-provider rankings page, which rendered as `__MISSING__:` markers in the Vietnamese UI ([#11589](https://github.com/diegosouzapw/OmniRoute/pull/11589))

View File

@@ -0,0 +1 @@
- **fix(dashboard):** Provider Stats now displays combo success rates on their native 0100 percentage scale instead of multiplying them twice ([#11595](https://github.com/diegosouzapw/OmniRoute/pull/11595)) — thanks @pacocartones

View File

@@ -0,0 +1 @@
- **fix(providers):** route DuckDuckGo Web Chat through the verified `duck.ai` endpoint, refresh its free model catalog, and avoid forwarding unsolved anti-abuse challenges ([#11597](https://github.com/diegosouzapw/OmniRoute/pull/11597))

View File

@@ -0,0 +1 @@
- **fix(ui):** Console log Refresh and Copy controls now expose localized accessible names, keep copy actions visible on keyboard focus, and announce copy completion safely ([#11599](https://github.com/diegosouzapw/OmniRoute/pull/11599)) — thanks @pacocartones

View File

@@ -0,0 +1 @@
- fix(handoff): enforce provider allowlist for universal handoff (#11602) — universal handoff now skips summarization when the selected summary model's provider is not included in the configured provider allowlist.

View File

@@ -0,0 +1 @@
- **fix(dashboard):** Show a stable error state when Search Analytics returns an HTTP error or malformed data ([#11603](https://github.com/diegosouzapw/OmniRoute/pull/11603)) — thanks @pacocartones

View File

@@ -0,0 +1 @@
- **fix(dashboard):** Keep the Profile level and progress aligned with aggregate XP, including bounded handling for invalid totals ([#11604](https://github.com/diegosouzapw/OmniRoute/pull/11604)) — thanks @pacocartones

View File

@@ -0,0 +1 @@
- **fix(dashboard):** Prevent locked hidden badges from revealing their icon or opening private badge details before they are earned ([#11605](https://github.com/diegosouzapw/OmniRoute/pull/11605)) — thanks @pacocartones

View File

@@ -0,0 +1 @@
- **fix(dashboard):** Restore keyboard focus after shared modals close and cancel delayed autofocus during cleanup ([#11607](https://github.com/diegosouzapw/OmniRoute/pull/11607)) — thanks @pacocartones

View File

@@ -0,0 +1 @@
- **fix(dashboard):** Enable Enter and Space activation for clickable data-table rows without hijacking nested controls ([#11610](https://github.com/diegosouzapw/OmniRoute/pull/11610)) — thanks @pacocartones

View File

@@ -0,0 +1 @@
- **fix(autoCombo,sse):** vendor-retired catalog ids are dropped from the auto-combo candidate pool and no longer win on leftover `arena_elo` / `user_override` rows; `getModelLifecycleDecision` consults `model-lifecycle.json` (prefix-stripped) so aggregator traffic is not `untracked` for ids the snapshot already knows ([#11625](https://github.com/diegosouzapw/OmniRoute/issues/11625))

View File

@@ -0,0 +1 @@
- **fix(docker):** re-derive the Docker build's worker-pool memory budget from the MEASURED ~4.5 GB per-process RSS (the issue owner's own VPS dmesg OOM-killer reproduction) instead of the stale 2560 MB/worker inference #11419 shipped, and lower `OMNIROUTE_BUILD_WORKERS` 3 → 2 so 1 parent + 1 page-data worker (2 processes × 4.5 GB = 9 GB) fits the 12.288 GB (75%) budget on a 16 GB GitHub Actions runner — the previous default (1 parent + 2 workers = 13.5 GB) still overcommitted the runner and kept "Publish to Docker Hub" failing with `cannot allocate memory` after #11419 merged (#7518).

View File

@@ -0,0 +1 @@
- **fix(electron):** the packaged Windows desktop build now passes the #7592 cold-restart smoke end to end. Five defects were found and fixed on the way: (1) optional-pack staging failed on any machine whose `tar` is GNU tar — it reads the drive letter in an absolute `-f C:\...` archive path as a remote rsh host (`Cannot connect to C:`), so staging now passes a bare filename with `cwd` at the tarball directory and surfaces tar stderr on failure; (2) the Electron `files` allowlist was missing `lib/loginHeaderCapture.js`, so the packaged main process crashed at startup with `Cannot find module './lib/loginHeaderCapture'`; (3) electron-builder ≥26 injects an `!**/node_modules/**` ignore into every extraResources pattern list that no positive filter can override, which silently dropped the staged runtime `node_modules` (including the better-sqlite3 N-API prebuild) from `resources/app` — a fresh v3.8.50 desktop build would have shipped with no native SQLite driver and reproduced the #7592 sql.js fallback on every machine; an `afterPack` hook now restores the staged `node_modules` after packing; (4) the packaged-app smoke harness redirected `USERPROFILE` into its temp DATA_DIR, but Electron resolves the Roaming profile from `%USERPROFILE%\AppData\Roaming\<name>` (USERPROFILE takes precedence over the APPDATA env var) and the path service throws instead of creating it, so `requestSingleInstanceLock()` returned false and the app exited(0) silently before `app.whenReady()` — the harness now pre-creates the derived tree, and `ensureSmokeEnvDirs` is exported and unit-tested; (5) the #7592 driver assertion parsed a `[DB] Driver: ...` line that the server's primary DB path never printed (only the unused `openDatabaseAsync()` did) — `getDbInstance()` now emits the same line on open so the guard can actually assert the native driver. Also: the smoke env-allowlist unit test hardcoded POSIX paths and could only pass on Linux/macOS; expectations are now host-agnostic, with new regression tests for the USERPROFILE-derived tree and `tarPack` under absolute Windows-style paths

View File

@@ -0,0 +1 @@
- **fix(autoCombo):** layer 3 (`models_dev_tier`) no longer scores retired models as premium, merge cross-provider capability rows deterministically, and inherit tier scores through variant ids ([#11508](https://github.com/diegosouzapw/OmniRoute/issues/11508)). `getModelsDevTierFitness` now vetoes ids present in `config/quality/model-lifecycle.json` with status `retired` before any other signal; `loadModelCapabilities()` aggregates per `model_id` (any-non-null-true for booleans, max for `limit_context`) instead of last-write-wins over SQLite's undefined row order; a capabilities miss retries through `resolveScoresAs()`'s base id and reports `models_dev_tier:inherited`, matching layers 12 (#11492). Adds `getModelsDevTierFitnessWithSource()` and an `invalidateCapabilitiesCache()` test/ops hook.

View File

@@ -0,0 +1 @@
- fix(sse): accept Claude `content:[]` + `stop_reason: max_tokens`/`tool_use` in `detectMalformedNonStream` (match `isEmptyContentResponse`) so Claude Code `/model` probes with `max_tokens: 1` no longer become a false 502

View File

@@ -0,0 +1 @@
- **fix(cli):** `omniroute update` now finds npm on Windows. It called `execFile("npm", …)` with no shell, and on Node ≥ 24 a `.cmd` wrapper cannot be spawned that way (nodejs/node#52554) — while a bare `npm` can also resolve to an extensionless shim `CreateProcess` refuses. The result was `✖ Could not check latest version. Is npm available?` in a terminal where `npm view omniroute version` worked fine, so the updater was unusable on Windows even though nothing was wrong with the install. This is the same class as #5379/#5542, which fixed the server-side calls; the CLI entry points were missed because they are plain `.mjs` and cannot import the TypeScript helper. `bin/cli/npm-exec.mjs` now states the same rule for them: `npm.cmd` plus a shell on win32, no shell anywhere else. Both npm lookups in `update.mjs` (version and changelog) pass a literal argv array, so enabling the shell cannot splice a runtime value into the command line — a test asserts that and fails if a future edit interpolates one. (#11335)

View File

@@ -0,0 +1 @@
- **fix(compression):** use `pathToFileURL` in `compressionWorkerPool` so bundlers (Webpack / Turbopack) do not attempt static asset resolution of missing `compressionWorker.js` during build

View File

@@ -0,0 +1 @@
- Fixed DuckDuckGo streaming responses losing JSON lines and UTF-8 characters split across network chunks.

View File

@@ -0,0 +1 @@
- Harden generated Cloudflare, Vercel, and Deno relays by stripping hop-by-hop, framing, and proxy authentication headers before forwarding requests upstream.

View File

@@ -0,0 +1 @@
- **fix(usage):** z.ai/GLM coding-plan subscription keys now render their quota cards again, with absolute credits. Z.ai's `/api/monitor/usage/quota/limit` switched these keys from `TOKENS_LIMIT` to `CREDIT_LIMIT` rows (same `unit`/`number` semantics: unit=3/number=5 → 5-hour window, unit=6/number=1 → weekly), and the parser only matched `TOKENS_LIMIT`/`TIME_LIMIT`, so both rows were dropped and the subscription card rendered empty. `CREDIT_LIMIT` is now accepted alongside `TOKENS_LIMIT`, and when the row carries absolute credit fields (`usage`/`currentValue`/`remaining`) they are preferred over the percent-only scale, so the card shows `3341 / 28000` like z.ai's own dashboard instead of `11 / 100`

View File

@@ -0,0 +1 @@
- **fix(auth):** a connection's `lastError` now names the real upstream failure instead of the bare string `Provider error`. `markAccountUnavailable` kept the reason only when it was already a string, so every other shape collapsed to that literal — and the shape that matters most is not a string: a failed `fetch` arrives as `TypeError: fetch failed` with the actionable part on `error.cause.code`, which means a wrong port, a firewall, a DNS failure and a blocked proxy all looked identical in the dashboard and in the console line. `describeUpstreamFailure` (in `src/shared/utils/upstreamError.ts`, reusing the `extractErrorMessage` that already parsed provider bodies) reads Error messages and appends the transport code when the message does not already carry it, reads the usual provider JSON shapes (`error.message`, `message`, string `error`, `detail`, `errors[]`), and falls back to the code alone before giving up. It never serializes the error object wholesale, so a request body or header attached to an error cannot leak into the stored reason — pinned by a test.

View File

@@ -0,0 +1 @@
- **fix(live-ws):** the Live dashboard socket can now be pointed at a reverse proxy without rebuilding the image. `NEXT_PUBLIC_*` is inlined at BUILD time, so a prebuilt Docker or npm image never carries an operator's `NEXT_PUBLIC_LIVE_WS_PUBLIC_URL` — which is exactly why the browser discovers the socket through `/api/v1/ws?handshake=1` instead. The server side of that handshake, however, read only the `NEXT_PUBLIC_`-prefixed name, so it had nothing to echo: behind Traefik the dashboard kept dialling `wss://<host>:20132/live-ws` and sat on "Live disabled — WebSocket disconnected. Showing last known state." `LIVE_WS_PUBLIC_URL` is now read at runtime alongside the existing `LIVE_WS_HOST` / `LIVE_WS_PORT`, and the prefixed name stays supported as the fallback, so deployments that already set it are unaffected. Only `ws://` and `wss://` values are accepted, matching the guard the client already applies. (#11331)

View File

@@ -0,0 +1 @@
- Fixed auto-router strategies preserving the selected connection through ranking and dispatch when multiple connections share the same provider and model.

View File

@@ -0,0 +1 @@
- Preserve Chat Completions JSON-object response formats when translating requests to the Responses API.

View File

@@ -0,0 +1 @@
- Fix idempotency fingerprints so Responses API requests include `input` and other semantic generation fields using stable serialization, while excluding credentials and request metadata.

View File

@@ -0,0 +1 @@
- **fix(sessions):** preserve legacy Sessions data when the additive exclusive-session projection is unavailable, returning an empty projection and warning only once per contiguous outage instead of failing the endpoint; the Sessions badge intentionally reflects the merged legacy and exclusive row count introduced by [#11389](https://github.com/diegosouzapw/OmniRoute/pull/11389)

Some files were not shown because too many files have changed in this diff Show More