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!
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!
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!
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!
Validated on a 3-PR combined board: traffic-inspector-beginner-header suite green within the board's 30/30, typecheck:core + dashboard-typecheck clean, gates within baseline. Purpose-first orientation header for Traffic Inspector, existing inspection UI untouched. Thank you @ignamiranda!
Validated on a 3-PR combined board: sidebar-customization + sidebar-essentials-static 30/30 combined (across the board's 4 focused files), typecheck:core + dashboard-typecheck clean, gates within baseline. New Essentials sidebar preset gives first-time users a short beginner path while advanced tools stay reachable via Command Palette search. Thank you @ignamiranda!
Validated on the combined 8-PR board: home-page-static 4/4, check:dashboard-typecheck clean (220 pre-existing, all within frozen baseline — zero syntax errors), 88/88 across the board's focused suites, static gates within baseline. The soft first-run readiness card replaces the hard Home→onboarding redirect with a dismissable 4-step path. Thank you @ignamiranda!
Validated on the combined 12-PR batch board + the resolved merge against the post-#11232 tip: focused suites 73/73 (learned-reasoning-effort-caps, synced-capabilities-learned-effort-override, synced-effort-suffix-learned-validation, effort-tiers-loop-catalog-e2e, reasoning-effort-clamp-and-retry, reasoning-effort-learned-capability) + opencode-plugin effort-tier-variants 4/4, typecheck:core clean, gates within baseline. The stacked-branch conflict after #11232 squash-landed was resolved by hand (the learned-caps module keeps both the Set API and the new model-scoped lookup). The effort_tiers loop is closed end-to-end: catalog advertises exactly what the upstream accepts, and -<tier> suffix variants resolve against the learned set. Thank you @maxmad64bis!
Validated on the combined 12-PR batch board: combo-max-global-attempts-config 4/4 plus the neighboring combo suites green, typecheck:core clean, gates within baseline. clampGlobalAttempts mirrors clampComboDepth with a 200 hard cap, so a bad config can never disable the budget. Closes the configurability item from #11134. Thank you @pacocartones!
Validated on the combined 12-PR batch board: focused node:test suites green (incl. provider-rate-limit-overrides-schema + ratelimit-admission-control-6593 isolated 11/11 + the new EditConnectionModal vitest 3/3), typecheck:core clean, all static gates within baseline. Pushed one follow-up commit to your branch with the real Vietnamese translations for the two new keys (repo convention: vi never ships __MISSING__ placeholders). Per-connection maxWaitMs override lands, folding the zai-web exception into the general mechanism. Thank you @maxmad64bis!
Validated on the combined batch board over tip 0b41259f: static gates clean, typecheck:core clean, 430+ focused tests green across 5 groups.
--tray returns after readiness and survives terminal close, with tray-mode autostart on macOS/Windows/Linux while headless Linux keeps the systemd user service. tray-detached + autostart suites green. Closes#11229. Thank you @tuandinh0801!
Merged after count reconciliation: the branch's regenerated docs claimed 57 free forever / 157 migrations from its older base; gate-verified values on the current tip are 56 free forever (Logfare carries a Free badge via gateways.ts freeNote but has no freeModelCatalog per-model entries, so the live-code counter stays at 56) and 159 migrations — the README/SVGs now match the check:docs-counts output exactly. provider-consistency OK at 267 registry / 349 canonical. logfare-registry 4/4, icon + KNOWN_PNGS + discovery-set membership all verified present. Closes#10644. Thank you @jonlwheat2-gif!
* feat(api): structured ?format=json for the self-service usage endpoint
GET /api/usage/om-usage already let any key read its own usage — personal
daily/weekly USD limits and the provider quota snapshot — but only as
text/plain, which a UI cannot parse safely. OmniCopilot issue #8 asks exactly
for this surface.
Adds ?format=json, returning the ApiKeyUsageLimitStatus + UsageSnapshot the
text is rendered from. Text and JSON share the same collectors
(collectUsageSnapshots, getApiKeyUsageLimitStatus), so the two can never
disagree about a number. The response is a discriminated union: a key without
allowUsageCommand (403) or an invalid key (401) returns
{ allowed:false, error:{message} }, distinct from allowed:true with empty
sections — the state a panel must render as "nothing learned yet", not a
refusal. Text form unchanged; without ?format the contract is untouched.
The endpoint was previously missing from API_REFERENCE.md; it now has a
section documenting both forms, the allowUsageCommand gate, and the
self-service auth model (caller's own key, not requireManagementAuth).
Regression guards in tests/unit/usage-command-json-format.test.ts (4 tests:
json shape, text default preserved, structured 403, sanitized 401 with no
stack trace). Existing internal-usage-command suite still 12/12.
* chore(changelog): correct the fragment to the real PR number (#11190)
* feat(api): return every connection's snapshot under providers[] in om-usage json
Closes#11191. buildUsageCommandJson picked a single snapshot via selectUsageSnapshot, so a panel could only ever show one provider. The collector already had them all — the single-pick is a presentation choice for a terminal. The JSON form now also returns the full UsageSnapshot[] alongside the selected provider, so a UI can render Codex / Claude / OpenCode side by side. The text form is untouched.
---------
Co-authored-by: Xiangzhe <bakryun0718@proton.me>
* feat(api): structured ?format=json for the self-service usage endpoint
GET /api/usage/om-usage already let any key read its own usage — personal
daily/weekly USD limits and the provider quota snapshot — but only as
text/plain, which a UI cannot parse safely. OmniCopilot issue #8 asks exactly
for this surface.
Adds ?format=json, returning the ApiKeyUsageLimitStatus + UsageSnapshot the
text is rendered from. Text and JSON share the same collectors
(collectUsageSnapshots, getApiKeyUsageLimitStatus), so the two can never
disagree about a number. The response is a discriminated union: a key without
allowUsageCommand (403) or an invalid key (401) returns
{ allowed:false, error:{message} }, distinct from allowed:true with empty
sections — the state a panel must render as "nothing learned yet", not a
refusal. Text form unchanged; without ?format the contract is untouched.
The endpoint was previously missing from API_REFERENCE.md; it now has a
section documenting both forms, the allowUsageCommand gate, and the
self-service auth model (caller's own key, not requireManagementAuth).
Regression guards in tests/unit/usage-command-json-format.test.ts (4 tests:
json shape, text default preserved, structured 403, sanitized 401 with no
stack trace). Existing internal-usage-command suite still 12/12.
* chore(changelog): correct the fragment to the real PR number (#11190)
---------
Co-authored-by: Xiangzhe <bakryun0718@proton.me>
Validated on the combined batch board over release/v3.8.50 tip d91238b7: static gates clean, typecheck:core clean, focused tests green.
Operator-declared per-provider error rules via settings, consulted before the built-ins; the allowlist bypass is correct — declaring a rule is itself the opt-in, and no provider-specific rule is hardcoded. Thank you @maxmad64bis!
Validado no worktree combinado: mesmos gates + 36 testes focados verdes. Feature bem documentada e testada (tool calling completo para copilot-m365-web via SignalR, incluindo keepalives e detecção de erro silencioso). CI vermelho é o base-red já rastreado em #9985.
Validado no worktree combinado: mesmos gates + testes focados verdes. Extensão opt-in bem desenhada sobre #10909 (dimensão de uso real via call_logs). CI vermelho é o base-red já rastreado em #9985.
Validado no worktree combinado: typecheck:core, changelog-integrity, complexity, cognitive-complexity, file-size, lint e testes focados (egress-ip-lock-10880, egress-lock-allowlist-10880, proxy-logs-egress-lookup-10880) todos verdes. Otimização de resiliência bem fundamentada (cooldown de conexões compartilhando IP de egress após 429 do allowlist). CI vermelho é o base-red já rastreado em #9985. Obrigado!
Validado no worktree combinado: typecheck:core, changelog-integrity, complexity, cognitive-complexity, file-size, lint e testes focados (freeProviderRankings-filters) todos verdes. Feature aditiva bem documentada (campo reliability nos rankings). CI vermelho é o base-red já rastreado em #9985. Obrigado!
Reconciliado com a release (conflito aditivo em targetTimeoutRunner.ts — combina o warning G3 já mergeado com a resolução de effectiveTimeoutMs deste PR) e revalidado: 41/41 testes focados passando (upstream-timeout-connection-tier, combo-target-timeout-runner, provider-specific-data-schema). CI vermelho é o base-red já rastreado em #9985. Obrigado!
Validado no worktree combinado do lote: typecheck:core, lint, gates de qualidade e testes focados (opencode-go-catalog-alignment + opencode-go-effort-aliases-8353, incluindo os novos casos muse-spark-1.2-contributor-*) todos verdes. CI vermelho neste PR é o base-red já rastreado em #9985. Obrigado!
Validado no worktree combinado do lote (`.claude/worktrees/batch-round2-0821`): typecheck:core, lint, changelog-integrity, file-size, complexity e cognitive-complexity todos verdes; testes focados (71 casos citados na PR + suíte combo-builder-effort-variants/model-discovery-reasoning-levels) passando. CI vermelho neste PR é o base-red já rastreado em #9985. Obrigado!
Rescoped from #10606 — see PR body for the full rationale (combo-routing half made moot by #10162's advisory-only architecture, chatCore.ts hard-reject bypass retains real value).
Validated in an isolated worktree boarded onto origin/release/v3.8.50:
- 65/65 focused unit tests pass (chatcore-model-output-cap-wiring + feature-flags-settings).
- check-file-size, check-changelog-integrity: OK.
- typecheck:core: clean.
- check-complexity / check-cognitive-complexity: OK, both under baseline.
Co-authored-by: JxnLexn <10897478+JxnLexn@users.noreply.github.com>
Obrigado — PR muito bem documentado e verificado. Adiciona o gateway TabiToken (Anthropic-first, /v1/messages, x-api-key) e estende hcnsec de 1 para 4 protocolos (Chat, Responses, Anthropic Messages, Gemini). AlternateFormat ganha o hook urlBuilder opcional (necessário para o path model-scoped do Gemini), compartilhado com o provider gemini nativo em vez de duplicado.
Reconciliado nesta sessão contra o release tip atualizado (base drift real: 343→345 canônicos entre quando o PR foi criado e o merge, mais os PRs #10673/#10658 mergeados nesse meio-tempo). Conflitos em contagens de providers (docs, file-size baseline, teste de partição) resolvidos additivamente.
Validação (reconciliação a partir de origin/release/v3.8.50):
- typecheck:core limpo, complexity/cognitive-complexity dentro do baseline
- npm run check:provider-consistency — OK (266 REGISTRY entries, 346 providers canônicos, 0 exceções)
- 40/40 testes passando (newapi-gateway-providers, hcnsec-provider, providers-constants-split, alternate-formats)
Merged — reimplementation extracting the non-conflicting Recent Requests panel + excludeTests allowlist fix from #8450 (see PR body for the full scoping rationale, including why the topology UX rework was deliberately excluded — it contradicts the already-shipped #8428). typecheck/file-size/changelog/complexity/cognitive-complexity/i18n-coverage gates all clean, 2/2 unit + 1/1 vitest passing.
Merged — clean extraction from #10358's genuinely new content (see PR body for the rationale: an unrelated .planning/codebase/ scaffolding dump was dropped). typecheck/file-size/changelog/provider-consistency gates clean, 18/18 tests passing.
Obrigado — expõe onde o operador realmente olha (sweep periódico de saúde de proxy + resposta da API de egress) o sinal de compartilhamento anônimo de IP de egress entre contas de um mesmo rotation group, que já existia (analyzeEgressSharing) mas só era acessível via curl autenticado. Fecha #10677. Respeita a decisão de redação do #10348/#10539: apenas contagens por padrão, nenhum IP/identidade de conta a menos que PROXY_LOG_INCLUDE_IPS=true.
Validação (worktree combinado a partir de origin/release/v3.8.50, 0 conflitos):
- typecheck:core limpo, complexity/cognitive-complexity dentro do baseline
- tests/unit/proxy-egress-route-summary.test.ts + proxy-egress-summary.test.ts + proxy-health-egress-line.test.ts — 23/23 passando (agregado, formatter, linha do sweep com output real capturado, rota completa com auth de management)
Obrigado — bug real de contrato: o openapi.yaml já documentava patch em /api/combos/{id}, mas a rota nunca exportou PATCH, então um cliente gerado a partir do spec publicado recebia 405 do App Router antes de qualquer handler rodar. Fix mínimo (delegação de 4 linhas para PUT, mesmo padrão já usado em /api/providers/[id] e 25 outras rotas /api/**).
Validação (worktree combinado a partir de origin/release/v3.8.50, 0 conflitos):
- typecheck:core limpo, complexity/cognitive-complexity dentro do baseline
- tests/unit/combo-patch-verb.test.ts — 2/2 passando (falham antes com "comboRoute.PATCH is not a function")
- Suíte combo completa — mesmas 5 falhas herdadas de #9985, confirmadas DRIFT
Merged — validated together with a batch of related RaviTharuma PRs in one combined worktree (typecheck:core clean, complexity/file-size/changelog gates green, focused tests passing). Thanks for the contribution!
Merged — validated together with a batch of related RaviTharuma PRs in one combined worktree (typecheck:core clean, complexity/file-size/changelog gates green, focused tests passing). Thanks for the contribution!
Merged — validated together with a batch of related maxmad64bis PRs in one combined worktree (typecheck:core clean, complexity/cognitive-complexity/file-size/changelog gates green, focused tests passing). Thanks for the contribution!
Merged — validated together with a batch of related maxmad64bis PRs in one combined worktree (typecheck:core clean, complexity/cognitive-complexity/file-size/changelog gates green, focused tests passing). Thanks for the contribution!
Merged — validated together with a batch of related maxmad64bis PRs in one combined worktree (typecheck:core clean, complexity/cognitive-complexity/file-size/changelog gates green, focused tests passing). Thanks for the contribution!
Merged via merge-train (release/v3.8.50, batch1 2026-08-20) — static gates (typecheck/file-size/complexity/cognitive/changelog) green on the combined tree; test:unit reds observed in the boarded run were verified pre-existing on the pure release tip (unrelated flake), not caused by this PR. Thanks for the contribution!
Merged via merge-train (release/v3.8.50, batch1 2026-08-20) — static gates (typecheck/file-size/complexity/cognitive/changelog) green on the combined tree; test:unit reds observed in the boarded run were verified pre-existing on the pure release tip (unrelated flake), not caused by this PR. Thanks for the contribution!
Merged via merge-train (release/v3.8.50, batch1 2026-08-20) — static gates (typecheck/file-size/complexity/cognitive/changelog) green on the combined tree; test:unit reds observed in the boarded run were verified pre-existing on the pure release tip (unrelated flake), not caused by this PR. Thanks for the contribution!
Merged via merge-train (release/v3.8.50, batch1 2026-08-20) — static gates (typecheck/file-size/complexity/cognitive/changelog) green on the combined tree; test:unit reds observed in the boarded run were verified pre-existing on the pure release tip (unrelated flake), not caused by this PR. Thanks for the contribution!
* feat(docker): expose DASHBOARD_ALLOW_EMBED as a build argument
The dashboard's frame-ancestors policy is compiled into the route manifest at
build time, so the only way to get an embed-enabled image was to edit the
Dockerfile: Docker silently drops a --build-arg with no matching ARG, so
`docker build --build-arg DASHBOARD_ALLOW_EMBED=vscode` produced the default
image and no error.
Declared as ARG+ENV in the builder stage, mirroring OMNIROUTE_BASE_PATH, and
empty by default — the unframable default posture is unchanged. The runtime
stages deliberately do not carry it: the headers are already baked, so a
runtime value would advertise an effect it cannot have.
Guarded by tests/unit/dockerfile-dashboard-embed-arg-10273.test.ts, verified by
mutation (a bare ENV in place of the ARG fails 2 of the 3 assertions). Docs
updated across the guide, ENVIRONMENT.md and .env.example.
The guide also carries prettier normalization (emphasis markers, table
padding) applied by lint-staged on commit.
Refs #10273
* chore(changelog): correct the fragment to the real PR number (#10701)
---------
Co-authored-by: Xiangzhe <bakryun0718@proton.me>
* docs(guides): DASHBOARD_ALLOW_EMBED is build-time, not a runtime flag
The VS Code guide told operators to "start OmniRoute with
DASHBOARD_ALLOW_EMBED=vscode". Next.js compiles headers() into the route
manifest, so next.config.mjs reads the variable while the bundle is built —
exporting it in front of an already-built server does nothing, which is the
exact trap anyone on `npm install -g omniroute` or the Docker image falls into.
Documents the build-time nature, the working from-source recipe, and which
install paths can enable it at all. ENVIRONMENT.md and .env.example already
said build-time; this aligns the how-to with them and with the extension's own
fallback message.
* docs(changelog): announce the VS Code Copilot Chat integration
The release notes only mentioned OmniCopilot in passing, inside the DASHBOARD_ALLOW_EMBED bullet — a reader would never learn the extension exists. Adds the fragment that says it plainly, with both store links.
---------
Co-authored-by: Xiangzhe <bakryun0718@proton.me>
* feat(providers): add Cloudflare AI Playground as No Auth provider (closes#10389)
Reverse-engineered access to the free, anonymous Cloudflare AI Playground:
chat runs over a PartySocket WebSocket speaking Cloudflare's cf_agent RPC
protocol with zero credentials (no account, no API key, no cookies). The
WS upgrade is gated on a browser-grade TLS fingerprint, so the executor
drives a headless Chromium via Playwright and speaks the protocol from
inside the page context.
- registry entry: cloudflare-playground (alias cfp), authType none,
curated 20-model catalog (GLM 5.2, Kimi K2.7 Code, DeepSeek V4 Pro,
gpt-oss-120B, Llama 3.3 70B, Qwen2.5 Coder 32B, ...) captured from the
live getModels RPC (2026-08-15)
- executor: cf_agent frame stream -> OpenAI SSE translation, id-filtered
parser (RPC done:true frames cannot kill the stream), in-band upstream
errors mapped to HTTP 429/502, abort + timeout handling, clean errors
- noauth UI entry with reverse-engineered-endpoint notice
- tests: 12 unit tests using real captured frames (incl. the 3021
rate-limit error) + fake transport; ESLint clean; open-sse typecheck clean
* fix(providers): define __name helper in page context before evaluate
Bundlers with keepNames (esbuild/tsx, webpack) inject a __name() call into
serialized function bodies. page.evaluate(openPlaygroundSession) therefore
threw ReferenceError: __name is not defined in real browser sessions.
Define the helper on window before evaluating the session opener.
* fix(providers): sync docs counts, golden snapshots and add reasoning_content support for cloudflare-playground
* chore: remove ad-hoc cfp-shim debug script per review feedback
The standalone shim duplicated the executor's frame-parsing and transport
logic and is superseded by open-sse/executors/cloudflare-playground.ts.
Requested in PR #10442 review.
* feat(gemini-web): expose image generation through /v1/images/generations (closes#10466)
Adds a gemini-web image-generation path following the chatgpt-web precedent:
- imageRegistry: gemini-web provider entry (format gemini-web, cookie auth)
with the nano-banana-web model. The -web suffix keeps the bare
nano-banana id owned by adobe-firefly (operator decision 2026-07-31).
- gemini-web executor: new parseStreamResponseImages() extracts generated
image URLs from the StreamGenerate candidate extension block
(inner[4][0][12][7][0], url at entry[0][3][3] — string or list form),
dedupes cumulative frames, upgrades to =s2048, and deliberately skips
web-search thumbnails at [12][1]. Image mode (x_gemini_web_image_mode)
captures every StreamGenerate frame, resolves on first image, and gets
a 90s window; chat mode is byte-for-byte unchanged.
- handlers/imageGeneration/providers/geminiWeb.ts: drives the executor in
image mode with an explicit generation directive prompt (the web UI
otherwise answers with web-search images), caps n at 4, returns URLs or
b64_json (downloads the public googleusercontent asset), and surfaces
refusal text when no image was produced.
- Dispatch branch on format gemini-web in handleImageGeneration.
Tests: 21 new tests with fixtures built from the documented frame layout
(string/list url forms, cumulative-frame dedupe, web-image exclusion,
size-directive handling, refusal visibility, n-cap, b64_json, registry
wiring incl. the bare nano-banana → adobe-firefly regression guard).
Adjacent suites: gemini-web (6 files), chatgpt-web image, image handler,
route, registry, adobe-firefly, freepik, designer — all green.
ESLint clean on touched files (2 pre-existing any warnings unchanged);
tsc -p open-sse 0 errors.
* fix(media): close browser leak, surface timeout errors, and fall back accounts for gemini-web images
Addresses pre-merge review findings on #10494 (closes#10466):
- cloudflare-playground executor: close the launched browser on EVERY
non-success start() path, including the detected Cloudflare "Attention
Required" challenge branch (was leaking a Chromium process per blocked
request).
- cloudflare-playground executor: a streaming chat timeout now emits an
explicit timeout_error SSE chunk before [DONE] instead of silently
completing, so a client can no longer mistake an empty/partial timed-out
stream for a successful answer. Timeout duration is now injectable for
deterministic tests.
- gemini-web image handler + imageCredentialRetry: classify the underlying
GeminiWebExecutor's expired/blocked-session failure modes (400/500, per
its own Playwright timeout/catch-all branches) as retryable, so
executeImageWithCredentialFallback advances to the next eligible account
instead of only doing so on a plain 401.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* docs: regenerate provider counts after merging release/v3.8.50 (341 -> 342)
The previous merge commit resolved all 51 auto-generated-file conflicts by
taking release/v3.8.50's content, which still said 341 providers. Merging in
this branch's Cloudflare Playground provider brings the live catalog to 342,
so npm run check:docs-counts-sync now flags stale claims. Fix:
- docs/reference/PROVIDER_REFERENCE.md: regenerated via
`npm run gen:provider-reference`.
- README.md/AGENTS.md/llm.txt/package.json description: 341 -> 342.
- docs/diagrams/{readme-hero,promise-pillars,comparison-table,cli-terminal}.svg:
341 -> 342 in the embedded "NNN providers" text (targeted replace, matched
against the exact pattern check-docs-counts-sync.mjs validates).
check:docs-counts-sync and check:changelog-integrity are both clean after
this commit.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* docs(env): document CLOUDFLARE_PLAYGROUND_CHROME_PATH
Used by open-sse/executors/cloudflare-playground.ts but missing from
.env.example and docs/reference/ENVIRONMENT.md, caught by the
env-doc-sync gate when combined with other PRs in the release
merge-train.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: user.email <freakymustard67@gmail.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* feat(admission): per-target lane-aware probes for combo/fusion fan-out (#9654 Wave 2)
Combo and fusion fan out N targets without ever consulting the adaptive-admission
layer: the parent request holds one lease, but each fan-out target is dispatched
unconditionally. With virtual lanes enabled (OMNIROUTE_CHAT_VIRTUAL_LANES=1), a
connection whose lane queue is full now SKIPS additional fan-out targets instead
of piling more queued work onto an already-congested session.
Adds PerTargetAdmissionHook (admission/types.ts) + createPerTargetAdmissionHook
factory (chatAdmission.ts): strictly non-blocking (maxWaitMs 0 - skip, never
queue), a no-op when virtual lanes are off, keyed to the parent tenantKey, and
release-on-admit so the probe is a capacity gate, not a hold.
Threaded through every parallel fan-out path:
- priority/weighted executeTarget + round-robin skip chains (combo.ts)
- fusion panel before fan-out (fusion.ts), judge fallback prefers survivors
- chaos parallel panel (autoCombo/chaosEngine.ts)
- tryFusionDispatch / tryRuntimeUnitDispatch / buildBaseOptions (dispatchPrelude.ts)
- chat.ts primary + safety-net redirect call sites
Snapshot exposes virtualLanes so the no-op gate is cheap and honest.
Tests: tests/unit/combo-lane-awareness-9654.test.ts (10 tests) - factory
semantics, priority/RR skip, fusion panel drop + all-skipped 503, no-hook
backward-compat baseline.
* feat(flags): activation UX - env-wins adaptive virtual-lanes flag + env docs (#9654 Wave 2)
U7: make adaptive virtual admission lanes discoverable + activatable.
- New OMNIROUTE_CHAT_VIRTUAL_LANES feature flag (boolean/runtime/requiresRestart) in featureFlagDefinitions + en.json i18n key.
- lib/admissionVirtualLanes.ts: env-wins resolver (env > DB > default) + boot warm folding a DB-sourced override into the process-global runtime env via reloadAdaptiveAdmissionRuntime(options.env) - no process.env mutation, no open-sse changes. Env still wins; DB toggle gates at next boot.
- GET /api/settings/feature-flags special-cases the flag to report the gate true source (ccDiscoveryAliases precedent); flagPayload helper dedupes the payload shape.
- Wire the warm into instrumentation-node registerNodejs (non-fatal, DB-ready).
- Document the master switch in .env.example + ENVIRONMENT.md with the system-1/system-2 distinction; zero new env-doc-sync drift.
- 11 new tests (resolver precedence + warm); 60/60 across feature-flag suites; typecheck core clean; ESLint + doc gates green.
* feat(mcp): surface adaptive admission lane data in omniroute_get_health (#9654 Wave 2)
U8: make adaptive virtual-lane admission visible to agents via the MCP health tool. handleGetHealth now surfaces a curated adaptiveAdmission block from the health payload (which already carried the runtime snapshot but was dropping it): virtualLanes/pressure/utilization/laneCount/laneQueuedCount/laneQueuedCost, laneTenants capped at top-10 by queued cost, admitted/rejected/wouldReject counts, shutdown. Block omitted entirely when the health endpoint reports none.
isLaneFlagOn mirrors the runtime 1|true convention so a string serialization can never invert a boolean lane report. getHealthOutput schema extended with the matching optional shape; tool description updated.
4 new dispatch tests (full block, top-10 cap/order, omission, defensive coercion of string flags + malformed lane entries) - 22/22 in essentialTools.test.ts. README: Adaptive Admission Lane Data table + Skills & Tool Navigability audit (29/43 schema entries covered, 14 undocumented, tool_search keyword runtime discovery, full catalog in docs/frameworks/MCP-SERVER.md).
No new lint errors (4 pre-existing in server.ts), typecheck core clean, doc counts + fabricated-docs gates green.
* docs: add changelog entry for #9654 Wave 2 (#10039)
* fix(codeql): suppress js/insufficient-password-hash false positive in lane-key fingerprinting (#10039)
resolveSessionId sha256-hashes bearer/x-api-key/x-goog-api-key to derive a deterministic, non-reversible per-key lane-bucket ID for virtual admission lanes (#9654). This is not password storage or verification, so the rule is a false positive; suppress it inline (same house style as src/lib/sync/tokens.ts) to clear the codeqlAlerts ratchet (2 > baseline 1) that blocks #10039 and every PR against release/v3.8.50.
* docs(mcp): complete MCP server README tool reference (#10039)
The MCP server README covered only 29 of the 43 schema entries, listing the
remaining tools solely as a gap note with omniroute_tool_search as the runtime
fallback. Add tool-reference tables for the agent-skills trio, oneproxy trio,
web_fetch/web_search, tool_search, create_combo, set_routing_strategy,
pick_fastest_model, sync_pricing, and db_health_check so the README covers the
full schemas catalog, and fold the coverage note into the tool_search discovery
paragraph.
* fix(chat): drop unused correlationId from safety-net combo redirect (#10039)
handleComboChat's HandleComboChatOptions has no correlationId member and
the combo pipeline never consumes it; the property was copied from the
handleSingleModelChat options shape by accident and introduced a new
TS2353 under the open-sse workspace typecheck gate.
* fix(i18n): translate featureFlagChatVirtualLanesEnabledDescription into 42 locales (#10039)
en.json gained the flag description in this PR but the locale catalogs
were never mirrored, failing the pt-BR key-parity (#6695) and vi
completeness gates. Adds a real translation to every locale, keeping the
zh-CN/zh-TW glossary canonical terms (提供者/儀表板) and no ICU drift.
* chore(quality): ratchet open-sse-typecheck baseline down (#10039)
The Wave 2 admission refactor removed 66 baselined open-sse type errors;
re-freeze the baseline so the gate pins the new, tighter state.
* docs: resync provider reference to 341 and CLI tools to 34
The release branch gained an 11th no-auth provider (freeaiapikey registry
resync, #10233) and a 26th CLI Code tool without regenerating the
auto-generated docs, leaving every PR against release/v3.8.50 failing the
Docs Gates strict validator (code 341 vs doc 340, CLI 34 vs "33 tools").
Regenerate docs/reference/PROVIDER_REFERENCE.md and sync the provider/tool
counts across README.md, AGENTS.md, llm.txt plus 42 i18n mirrors,
package.json description, and the four diagram SVGs.
* fix(tests): align count expectations with live catalogs (pre-existing release drift)
Release/v3.8.50 currently fails five gates on its own tree; this PR inherits
them. Fix the stale expectations to match live code:
- feature-flags-settings: 48 -> 49 flags (Wave 2 adds OMNIROUTE_CHAT_VIRTUAL_LANES)
- cli-tools-schema / cli-catalog-counts: 33 -> 34 tools (zcode added; 26 code = 21 visible + 5 none)
- optional-transformers-dependency: onnxruntime-node ~1.24.3 -> ~1.27.0 (bump #10382)
- stryker.conf.json: register chatcore-header-drop-warn-dedupe-10315 test
- check-public-creds: freeze zcodeProtocol clientId false positive (client identifier, not a credential)
* fix(tests): follow release's onnxruntime-node revert to ~1.24.3
release/v3.8.50's #10543 pinned onnxruntime-node back to ~1.24.3 after
#10403's ~1.27.0 bump caused npm to nest a second native copy under
@huggingface/transformers and broke the Docker SONAME contract. This
PR's own drift-alignment commit (57b9c033) predates that revert and
still expected ~1.27.0; the 3-way merge did not flag it as a textual
conflict since only one side touched this exact line, but the merged
tree became internally inconsistent (package.json ~1.24.3 vs test
expecting ~1.27.0). Align the test with the now-canonical release
value.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* fix(quality): dedupe stryker.conf.json chatcore-header-drop-warn-dedupe entry
The 3-way merge applied both sides' insertion of the same test-file entry
at different positions, producing a duplicate with broken indentation.
Adopted release's clean version of the file.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: Brandon Bennett <brandonbennett@macbookair.myfiosgateway.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: Brandon Bennett <branben@users.noreply.github.com>
* feat(resilience): scope auto-disable banned accounts to subscriptions
Prepaid API keys should stay in the routing pool after a permanent-ban
signal; subscription/OAuth accounts can still be deactivated. Default
scope remains all so existing installs do not change.
* docs(security): document auto-disable scope and log skipped prepaid keys
Keep the operator ban-detection page aligned with the new setting and
reuse the shared scope enum in the settings schema and dashboard radios.
* chore(changelog): name the auto-disable scope fragment for #10617
* docs(settings): treat free login seats as auto-disable targets
The first-cut scope is still all vs login-style auth. Copy now states
that paid subscriptions and free accounts both disable, while prepaid
API keys stay in the pool until per-account overrides exist.
* i18n: backfill autoDisableBannedScope keys across all locales
npm run i18n:sync-ui — the 6 new autoDisableBannedScope* keys landed
in en.json and vi.json but not the other 40 locales (including
pt-BR), tripping the pt-BR no-drift regression test (#6695).
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: Ravi Tharuma <RaviTharuma@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* feat(providers): complete Jina AI via OmniRoute including Omni multimodal
Dashboard and env keys share one Jina credential pool, native v5 Omni
{text}/{image}/{content} docs pass through /v1/embeddings intact, and
classify/segment/search are proxied without a third unused Jina card.
* chore(changelog): name Jina complete-provider fragment for #10581
* feat(providers): make Gemini Embedding 2 multimodal work via OmniRoute
Route gemini-embedding-2 through embedContent/batchEmbedContents so N
OpenAI input items become N vectors, pass through native multimodal
parts, and use dashboard Gemini keys (GEMINI_API_KEY only as fallback).
* fix(providers): resolve rebase fallout for Jina/Gemini embeddings
- narrow the two new no-explicit-any violations introduced by this PR
(validateJinaFoundationProvider's params + catch, search.ts's
normalizeJinaSearchResponse data param)
- cast credentials to Record<string, unknown> at the two quota-preflight
call sites in src/sse/services/auth.ts so the new JinaEnvCredentials /
GeminiEnvCredentials union members type-check without loosening the
allRateLimited narrowing used elsewhere in the same function
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: Ravi Tharuma <RaviTharuma@users.noreply.github.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* feat(providers): optional AI Horde API key and live image catalog
Allow a registered Horde key on the no-auth connection and send it for
chat and image jobs. List only image models that currently have workers,
and generate through Horde's native async API.
# Conflicts:
# open-sse/config/imageRegistry.ts
# src/app/(dashboard)/dashboard/providers/[id]/ProviderDetailPageClient.tsx
# src/shared/constants/providers.ts
# src/sse/services/auth.ts
* fix(providers): validate AI Horde keys against find_user
The OpenAI-compatible /v1/models probe returns 200 for any Bearer token
on oai.aihorde.net, so Check always succeeded. Use Horde's /v2/find_user
lookup instead; an empty key still counts as the optional anonymous path.
* chore(changelog): name the AI Horde fragment for #10542
* fix(images): harden AI Horde optional-key selection and outbound fetches
- Optional-key selection now honors connection health (rate-limit cooldown
and terminal/unavailable test status) before handing a stored key back,
rotating to the next healthy key or falling back to the anonymous no-auth
path instead of using an unhealthy stored key.
- Route the Horde submit/check/status/cancel and catalog calls through the
repository's bounded outbound-fetch helper (timeout, no more bare fetch())
and route R2 image downloads through the established bounded remote-image
fetch (SSRF host guard, DNS-rebinding pin, streaming byte cap, redirect
limit) instead of an unbounded fetch().
- Extend the generation deadline to cover the full request lifecycle
(catalog freshness check, submit, polling, and image download), and add a
regression test proving that exceeding the deadline issues a DELETE
cancel to Horde's API rather than only timing out locally.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
---------
Co-authored-by: pqr <pqr@soraka.ititti.es>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* feat(cli): refuse ephemeral container auto-config writes
Detect containerized OmniRoute and block CLI/API config writes into
throwaway homes unless a bind mount or explicit opt-in is present, and
honor compose host-profile CLI_CONFIG_HOME mounts outside the container home.
Co-authored-by: Cursor <cursoragent@cursor.com>
* chore(changelog): name fragment for #10057
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: yansigit <yansigit@users.noreply.github.com>
Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
Implements the secure, opt-in Video Bridge for issue #9760, including bounded FFmpeg frame extraction, capability-aware routing, telemetry, settings UI, localization, documentation, and regression coverage.