Skip to content

feat(providers): Microsoft 365 Copilot (BizChat) individual provider [DRAFT] (#4042) - #4400

Closed
diegosouzapw wants to merge 27 commits into
release/v3.8.37from
feat/m365-individual-4042
Closed

diegosouzapw wants to merge 27 commits into
release/v3.8.37from
feat/m365-individual-4042

Conversation

@diegosouzapw

Copy link
Copy Markdown
Owner

⚠️ DRAFT — gated on a Rule #18 live round-trip. Do not merge until @skyzea1 confirms a live m365.cloud.microsoft/chat round-trip through this provider. Mocked frame tests are necessary but not sufficient for an upstream-WebSocket feature.

What

Adds copilot-m365-web, a web-session provider that speaks Microsoft Substrate BizChat over SignalR/WebSocket for the individual M365 path (m365.cloud.microsoft/chat → wss://substrate.office.com/m365Copilot/Chathub/...). Implements #4042 (individual). The enterprise tier (#3897) is deferred pending @Forcerecon's type:4 send + type:1/2/3 response frames.

Built entirely from @skyzea1's real, sanitized #4042 capture.

Design — testable core isolated from the gated transport

File Role Tested?
copilot-m365-frames.ts Pure SignalR framing: \x1e split/join, handshake/keepalive, type:4 builder, type:1/2/3 classification, accumulated→incremental delta ✅ 14 tests vs real fixtures
copilot-m365-connection.ts Pure URL/credential/prompt helpers; token redaction ✅ 9 tests
copilot-m365-web.ts WebSocket transport (modeled on copilot-web.ts): handshake → keepalive → send → decode → OpenAI SSE ⏳ live-validation gate

The opaque individual access_token is passed through verbatim (never parsed). It rides the WS query string per the protocol, with a redactWsUrl() guard so it is never logged. Errors route through sanitizeErrorMessage() (Hard Rule #12); abort/timeout handled.

Wiring

Registry entry + executors/index + providers/index + providers.ts metadata (m365 alias) + webSessionCredentials + file-size baseline (providers.ts 3242→3255, justified).

Validation

  • typecheck:core ✅ · typecheck:noimplicit:core ✅ · check:cycles ✅ · check:file-size ✅ · lint 0 errors
  • 23 unit tests pin the wire format + helpers against the real capture (frame encode/decode, handshake ack/error, token redaction, prompt flatten, end-to-end decode reconstructing the bot answer once).

⛔ Remaining before this can leave DRAFT (Rule #18)

  • Live round-trip with @skyzea1 on m365.cloud.microsoft/chat (paste the token + Chathub path, send a prompt, confirm streamed reply). Record the result here.
  • Confirm the generated chatsessionid/X-SessionId/ConversationId/traceId are accepted (vs. requiring a browser-bound binding).
  • Confirm optionsSets/sliceIds can be empty (left empty pending live tuning).
  • On green: add CHANGELOG + docs/frameworks web-session entry + regen PROVIDER_REFERENCE, then un-draft.

cc @skyzea1 — your capture drove this; we'll tag you to validate before it ships. Enterprise (#3897) tracked separately for @Forcerecon.

Refs #4042

diegosouzapw and others added 27 commits June 20, 2026 07:36
…itive) (#4386)

getMitmToolHosts returns string[], so .includes(host) is Array.prototype.includes
(exact membership). CodeQL's js/incomplete-url-substring-sanitization heuristic
misreads it as a String.includes() URL-substring sanitization check and raises a
HIGH alert. Switch to .some(h => h === host) — identical semantics, explicit intent,
no flagged pattern. Surfaced post-v3.8.30 (#4325) once the test landed on main.

Test-only change (no runtime behavior); the suite still passes and the CodeQL
re-scan on merge clears the alert.
Adds reasoning.summary=auto + reasoning.encrypted_content include for Codex. Thanks @xz-dev.
…dels (#4341)

NVIDIA NIM asymmetric embedding models (e.g. nvidia/nv-embedqa-e5-v5) reject
requests without an `input_type` ("query" | "passage") with 400 "'input_type'
parameter is required". The embedding registry now carries a model-level
default param for the asymmetric NVIDIA model, and the embeddings handler
injects a model's default params into the upstream body only when the client
omitted them, leaving a client-supplied value untouched.

Reported-by: hydraromania (decolua/9router#1378)

Co-authored-by: hydraromania <252583922+hydraromania@users.noreply.github.com>
…s].hooks (#4342)

Codex renamed the `codex_hooks` feature flag to `hooks`; recent Codex CLI
versions ignore the old key and warn. When OmniRoute rewrites an existing
config.toml (configure/reset Codex provider) it now renames
[features].codex_hooks -> [features].hooks, preserving the value and never
clobbering an already-present `hooks`, then drops the deprecated key. The
migration is a no-op when the flag is absent and runs on both the POST and
DELETE config paths.

Reported-by: Bian-Sh (decolua/9router#1327)

Co-authored-by: Bian-Sh <24520547+Bian-Sh@users.noreply.github.com>
…#4344)

The streaming response translator's same-format fast path returned
`[chunk]` unconditionally, so the end-of-stream null/flush signal
(chunk === null) propagated as a literal `[null]`. Downstream this surfaced
as an empty `data: null` SSE event between chunks and crashed strict clients
(e.g. Factory Droid BYOK on /v1/responses). The fast path now returns `[]`
for the null flush while still passing real chunks through unchanged.

Reported-by: thaitryhand (decolua/9router#1052)

Co-authored-by: thaitryhand <248103256+thaitryhand@users.noreply.github.com>
…h (Mistral 422) (#4350)

Strict OpenAI-compatible upstreams (e.g. mistral/codestral-latest) reject
client-only assistant echo fields sent back as input with 422
extra_forbidden (the report hit messages[].assistant.reasoning_content via
Codex /responses). Only reasoning_content was stripped on the OpenAI target
path; the sibling fields reasoning / refusal / annotations / cache_control
leaked through. They are now all dropped on the non-reasoner OpenAI target
path. `audio` is intentionally preserved (OpenAI audio models reference a
prior assistant audio response by id; Mistral never emits audio).

Reported-by: xxy9468615 (decolua/9router#1649)

Co-authored-by: xxy9468615 <63351664+xxy9468615@users.noreply.github.com>
…#4343)

* fix(cli): honor TAILSCALE_AUTHKEY for non-interactive tailscale login (port from 9router#1263)

startTailscaleLogin built `tailscale up` without ever reading
process.env.TAILSCALE_AUTHKEY, so a pre-authenticated / headless daemon
waited for an interactive auth URL and timed out (~15s). When
TAILSCALE_AUTHKEY is set it is now passed via `--auth-key=` (an argv element
to spawn(binary, args) — no shell interpolation, Hard Rule #13); when unset,
behavior is unchanged. The arg builder is extracted into a pure exported
`tailscaleUpArgs()` for testing.

Reported-by: ipeterpetrus (decolua/9router#1263)
Co-authored-by: ipeterpetrus <93033698+ipeterpetrus@users.noreply.github.com>

* chore(quality): rebaseline tailscaleTunnel.ts file-size to 1202 (#1263 +13)

---------

Co-authored-by: ipeterpetrus <93033698+ipeterpetrus@users.noreply.github.com>
…ponse (#4351)

* fix(dashboard): OAuth modal surfaces real error on non-JSON responses (port from 9router#1318)

The OAuth connect/reauth modal called `await res.json()` unconditionally, so
a non-JSON error response (e.g. a plain-text 500 page from a build/OAuth
endpoint) threw `Unexpected token 'I'...` and hid the real failure. New
shared helpers parseResponseBody / getErrorMessage (src/shared/utils/api.ts)
read the body safely (JSON when JSON, raw text otherwise) and produce a clean
message either way; every modal fetch site now uses them.

Reported-by: DNNYF (decolua/9router#1318)
Co-authored-by: DNNYF <74033321+DNNYF@users.noreply.github.com>

* fix(dashboard): type OAuth modal response body as Record<string, unknown> (t11 any-budget)

Switch the parseResponseBody casts from Record<string, any> to
Record<string, unknown> so OAuthModal.tsx stays within its t11 explicit-any
budget. getErrorMessage already takes unknown; the success paths typecheck
clean under strict:false. No runtime change.

---------

Co-authored-by: DNNYF <74033321+DNNYF@users.noreply.github.com>
… content parts (#4345)

* fix(translator): accept AI SDK-style { type: image, image: "data:..." } parts (port from 9router#1330)

Several OpenAI-input translators only recognized images shaped as
`image_url.url` (or an object with `.source`/`.url`), so an AI SDK-style
content part where `image` is a bare data-URL STRING was silently dropped
before reaching a vision provider (OpenCode is one affected client; the gap
is generic). The OpenAI->Claude, OpenAI->Kiro and OpenAI->Gemini/Antigravity
translators now parse a string `image` data URL into each provider's native
image shape (Claude base64 source, Kiro images[].source.bytes, Gemini
inlineData).

Reported-by: mugnimaestra (decolua/9router#1330)
Co-authored-by: mugnimaestra <13349159+mugnimaestra@users.noreply.github.com>

* chore(quality): freeze openai-to-kiro.ts file-size at 807 (#1330 +9, over 800 cap)

---------

Co-authored-by: mugnimaestra <13349159+mugnimaestra@users.noreply.github.com>
…4352)

* fix(dashboard): show a disabled connection's last error in the row (port from 9router#1447)

The provider card's error badge counts a disabled connection (isActive ===
false) that has an error — its effective status is still
error/expired/unavailable — but the connection row hid the lastError text for
disabled rows, so the operator saw the count without the cause. The row's
error-visibility decision is extracted into shouldShowConnectionLastError()
and now shows the error whenever there is one, regardless of the active
toggle.

Reported-by: ntdung6868 (decolua/9router#1447)
Co-authored-by: ntdung6868 <103993527+ntdung6868@users.noreply.github.com>

* chore(quality): rebaseline ConnectionRow.tsx file-size to 942 (#1447 +1 import)

---------

Co-authored-by: ntdung6868 <103993527+ntdung6868@users.noreply.github.com>
…4347)

* fix(providers): bound OAuth connection-test probe with a timeout (port from 9router#1449)

The OAuth path of "Test Connection One-by-One" called bare fetch() with no
AbortController/signal, so a provider probe that accepted the socket but never
responded wedged the test queue forever. Both the initial probe and the
post-refresh retry are now bounded with AbortSignal.timeout(30s) — matching the
API-key path's existing budget — and a timed-out probe resolves as a failure
with a clear "Test timed out after 30s" message in the route's normal error shape.

Reported-by: ntdung6868 (decolua/9router#1449)
Co-authored-by: ntdung6868 <103993527+ntdung6868@users.noreply.github.com>

* chore(quality): rebaseline providers test route file-size to 887 (#1449 + sibling #1444 growth)

---------

Co-authored-by: ntdung6868 <103993527+ntdung6868@users.noreply.github.com>
… token (#4353)

A Codex connection whose OAuth refresh is fully healthy but whose ChatGPT
account has been deactivated by the provider gets a 401 from the upstream
API. The connection test labeled that the same as a bad credential
("Token invalid or revoked" -> upstream_auth_error), so an operator could not
tell a deactivated account from a revoked token. The test now reads the
401/403 body and, when it indicates account deactivation, classifies it as
account_deactivated (which the dashboard already renders as "Account
Deactivated"); a plain auth 401 is unchanged.

Reported-by: ntdung6868 (decolua/9router#1444)

Co-authored-by: ntdung6868 <103993527+ntdung6868@users.noreply.github.com>
…oved (#4348)

* fix(db): cascade-delete orphaned model aliases when a provider is removed (port from 9router#1409)

Deleting a custom provider removed its connections and node but left the
imported model-alias rows (key=<alias>, value="<providerId>/<model>") behind,
so re-importing the same provider was blocked by stale "already exists" aliases.
Add a deleteModelAliasesForProvider(providerId) DB helper that drops every alias
whose stored value begins with "<providerId>/", and call it from the provider-node
DELETE handler so a fresh import is unblocked.

Reported-by: nguyenvanhuy0612 (decolua/9router#1409)
Co-authored-by: nguyenvanhuy0612 <57367674+nguyenvanhuy0612@users.noreply.github.com>

* chore(quality): rebaseline models.ts file-size to 1221 (#1409 + sibling #1294 growth)

---------

Co-authored-by: nguyenvanhuy0612 <57367674+nguyenvanhuy0612@users.noreply.github.com>
…stom model (#4349)

The POST /api/provider-models handler read the rest of the body but never
the two token-limit fields, and addCustomModel() had no parameter for them,
so the form values were dropped on write while the DB layer and /v1/models
catalog already round-trip inputTokenLimit/outputTokenLimit. Accept the two
optional limits in the schema, forward them through the handler, and persist
them in addCustomModel(). TDD: failing-then-passing unit test.

Reported-by: codename-zen (decolua/9router#1294)

Co-authored-by: codename-zen <263238141+codename-zen@users.noreply.github.com>
One-time reconciliation of the docs with every user-facing feature shipped since
v3.8.20 (we had never done a dedicated pass, so debt had accumulated):

- README: new '✨ What's New' section (curated v3.8.20→v3.8.30 highlights).
- New guides: CLI-INTEGRATIONS (all setup-*/launch commands), MITM-TPROXY-DECRYPT
  (transparent-decrypt epic), CONTEXT_EDITING (delegated Anthropic clear_tool_uses).
- Refreshed: AUTO-COMBO (auto/<category>:<tier> + Arena-ELO), API_REFERENCE
  (x-omniroute-no-memory), MEMORY (int8 quantization + off-by-default), RESILIENCE
  (model-lockout success-decay), RTK, AGENTBRIDGE, TRAFFIC_INSPECTOR, GUARDRAILS,
  CLOUD_AGENT, ENVIRONMENT, SETUP_GUIDE, CLI-TOOLS, MCP-SERVER.
- Regenerated PROVIDER_REFERENCE (231 providers); synced the count in README/CLAUDE/AGENTS.
- Allowlisted external-tool env vars (OPENAI_API_BASE, PROMPTFOO_PROVIDER_KEY) and the
  STREAM_RECOVERY config-object name in the docs-accuracy gates.

All claims source-verified; check:docs-all (sync/counts/env/links/fabricated) passes.
Going forward this runs every release via generate-release step 6b.
…(native Claude) (#4389)

Forced tool_choice now strips the adaptive thinking injection to avoid Anthropic 400. Thanks @NomenAK.
…ter#344) (#4373)

OpenAI-style `image_url` parts with an `http://` or `https://` URL reached
`convertOpenAIContentToParts` and were dropped with only a `console.warn`,
because Gemini's `inlineData` requires base64 (the helper is synchronous and
cannot fetch+encode upstream assets). Gemini's `Part` schema, however, natively
accepts `fileData: { fileUri }` for remote URIs — the model fetches the asset
itself.

The helper now emits a `fileData` part (`mimeType: "image/*"`, inferred upstream
on fetch) for HTTP/HTTPS URLs instead of silently dropping them. Vision requests
that pass a URL — not a data: URI — now reach Gemini intact.

No behavioral change for:
- `data:` URIs → still emitted as `inlineData` with the parsed media type.
- Unsupported schemes (e.g. `ftp:`) → still skipped (Gemini would reject them).

The openai-to-claude side already passed HTTP/HTTPS URLs through as
`source: { type: "url", url }` (lines 573–578) — the upstream PR's Claude-side
change was already covered.

Regression test: tests/unit/gemini-helper-http-image-url-port344.test.ts
(4 cases: https URL, http URL, data: URI no-regression, unsupported-scheme guard).


Inspired-by: decolua/9router#344

Co-authored-by: Ibrahim Ryan <ryan@nuevanext.com>
…g Claude Code requests (port from 9router#663) (#4374)

Claude-Code-compatible providers force the executor-level `stream` flag on
via `upstreamStream = stream || isClaudeCodeCompatible`
(open-sse/handlers/chatCore.ts), but the outgoing body keeps the caller's
original `stream: false`. The shared `stream && targetFormat === "openai"`
branch in DefaultExecutor.transformRequest then injected
`stream_options: { include_usage: true }` onto a body that still said
`stream: false`, and qwen upstream rejected the request with
`400 "'stream_options' only set this when you set stream: true"`. The same
rejection surfaced when the body carried `thinking` / `enable_thinking`.

The qwen branch now skips the injection (and strips any client-sent
`stream_options`) when the body explicitly says `stream: false` or
requests thinking, leaving regular qwen streaming requests with the
include_usage injection intact. Other providers are unaffected.

Adds a TDD regression with 4 cases covering both opt-out paths and the
normal-streaming positive control.


Inspired-by: decolua/9router#663

Co-authored-by: anuragg-saxenaa <anuragg.saxenaa@gmail.com>
…llowlist (port from 9router#998) (#4372)

The OAuth callback at `/callback` previously fell back to
`window.opener.postMessage({ code, state, ... }, "*")` whenever the opener
was cross-origin. The fallback was intended to support remote-OmniRoute +
local-loopback callbacks (where opener and callback live on different
origins), but the same code path also delivers the OAuth code/state to any
hostile opener that pops the well-known callback URL — letting that
attacker complete the OAuth flow as the user.

Replace the wildcard fallback with iteration over a fixed allowlist:
`window.location.origin` (same-origin parent — the popup-mode dashboard)
plus Codex's fixed loopback helper (`http://localhost:1455` and the IPv4
literal `http://127.0.0.1:1455`). The browser drops `postMessage` to any
opener whose actual origin is not in `targetOrigin`, so the message reaches
only known parents and is silently dropped for any other. The same-origin
fallback path is unchanged — methods 2 (`BroadcastChannel`) and 3
(`localStorage` storage event) still cover same-origin openers that COOP
severed.

The `openerSameOrigin` probe stays in place to drive the auto-close vs
manual-copy UI decision (no behavior change for the success path).

Adds a regression test (`tests/unit/ui/oauth-callback-postmessage-scope.test.tsx`)
that mounts the page with a stubbed cross-origin opener and asserts no
`postMessage` call ever uses `"*"` and every call lands on an allowlisted
origin. The test failed against the pre-fix code (red), passes after the
fix (green) — TDD per CLAUDE.md hard rule #18.

Partial port of upstream decolua/9router#998: the upstream PR also
re-enabled TLS verification on a DNS-bypass fetch in `open-sse/utils/proxyFetch.js`;
that part is N/A here because OmniRoute's `proxyFetch.ts` never disabled
TLS verification (no `rejectUnauthorized: false` anywhere in the file).


Inspired-by: decolua/9router#998

Co-authored-by: aeonframework <aeon@aeonframework.dev>
…4365)

Combo per-target timeout inherited the full FETCH_TIMEOUT_MS (600s) when a
combo did not set its own targetTimeoutMs, so a single hung/slow target stalled
the whole combo for up to 10 minutes before falling through to the next model.

Introduce DEFAULT_COMBO_TARGET_TIMEOUT_MS (120s) as the unset-default in
resolveComboTargetTimeoutMs (new 3rd arg) and wire it in phaseComboSetup. The
upstream ceiling (600s) and per-combo opt-out (targetTimeoutMs, up to the
ceiling) are preserved; single non-combo requests are unchanged. For streaming
requests this only bounds time-to-first-headers, so token generation is not cut
short.

TDD: failing-then-passing unit test in tests/unit/combo-config.test.ts.
…ispatchers (#4362)

Primeiro incremento da de-dup dos 2 dispatchers de combo (handleComboChat +
handleRoundRobinCombo). O bloco de pre-check #1731/#1731v2 (skip de target já
exhausted no provider/connection) era BYTE-IDÊNTICO nos dois (mesmas condições,
mesmas mensagens), diferindo só na tag de log e no control-flow.

- comboPredicates.ts: getExhaustedTargetSkipReason(target, exhaustedProviders,
  exhaustedConnections) — predicate PURO que retorna a mensagem de skip (ou null);
  cada dispatcher mantém seu próprio log-tag + control-flow (return null / continue)
  + fallbackCount. No mutate do stryker (cobertura de mutação).
- combo.ts: −20 linhas (os 2 blocos viram 1 chamada cada).
- 7 testes de caracterização travam condições + strings exatas.

Comportamento preservado: 376/376 testes combo (357 caracterização + 7 novos),
integração sse-correctness 5/5, typecheck 0, complexity neutro (1895), file-size
encolhe. Próximo incremento: de-dup do error-handling/exhausted-tracking (handleTargetError).
…ss both dispatchers (#4366)

Segundo incremento da de-dup dos 2 dispatchers (handleTargetError). Após cada erro
de target, ambos rodavam um bloco quase-idêntico que marca o provider exhausted
(#1731), a conexão connection-errored (#1731v2) ou o provider transiently rate-limited.

- combo/targetExhaustion.ts: applyComboTargetExhaustion(target, opts) — atualiza os
  3 Sets de exhaustion e retorna providerExhausted. As MUTAÇÕES de Set (que dirigem o
  skip de targets, lidas por getExhaustedTargetSkipReason) são BYTE-IDÊNTICAS nos dois;
  as diferenças reais viram parâmetros: tag, allAccountsRateLimited (termo extra do RR,
  false no handleComboChat), exhaustedLogLevel (info no handleComboChat, debug no RR).
  Connection-level extraído p/ markConnectionLevelExhaustion (privado, <15 complexity).
- combo.ts: −73 linhas; 4 imports órfãos removidos.
- 7 testes de caracterização travam as mutações + o return.

ÚNICA mudança de comportamento: o WORDING das mensagens de log do RR ganha o sufixo
'on remaining targets' (cosmético; mesmo #code, mesmas mutações, mesmos níveis de log).
376/376 combo (caracterização preservada), integração sse 5/5, typecheck 0, complexity
neutro (1895), file-size encolhe.
…omposition start) (#4371)

Primeiro incremento da decomposição do chatCore.ts (5127 LOC, hot-path mais quente).
O guard de memória do topo do handleChatCore (rejeita 503 quando o heap V8 passa o
threshold de shed) vira um leaf testável, co-locado com o threshold em heapPressure.ts.

- heapPressure.ts: checkHeapPressureGuard(heapUsedMb, thresholdMb) — retorna o result
  503 pronto ou null. Byte-idêntico ao guard inline (mesmo check, mesma 503, mesmo warn).
  A figura de heap fica em telemetria INTERNA, nunca no response do cliente (Hard Rule #12).
- chatCore.ts: o bloco inline (~22 ln) vira 3 linhas; import órfão de HEAP_PRESSURE_THRESHOLD_MB
  trocado por checkHeapPressureGuard.
- 3 testes novos (incl. assert Rule #12: o MB medido não vaza no payload).

complexity-baseline 1895->1896: drift de base pós-#4338 (medido com minhas mudanças
stashed = 1896); esta mudança é complexity-NEUTRA (helper complexity 2, handleChatCore só
perde código). 190/190 chatcore tests, typecheck 0, file-size encolhe.
en-only i18n, fetch-start-timeout hardening, EngineConfigPage icon fix, CI build-artifact-reuse overhaul. Memory production hunk dropped as a no-op (tests kept). Thanks @JxnLexn.
…estore green) (#4396)

The combo-dispatch cases in combo-stream-readiness-fallback.test.ts deliberately
fail `glm` (zombie streams / repeated 504s), which legitimately trips the
per-provider circuit breaker. That OPEN state is a module-level singleton, so it
leaked into the next test and combo.ts then SKIPPED `glm/*` targets entirely
("Skipping … circuit breaker OPEN"). That made "combo does not retry stream
readiness timeouts on the same model" never attempt glm/zombie — expected
['glm/zombie','openai/gpt-5.4-mini'] but got ['openai/gpt-5.4-mini'].

This was a pre-existing red on release/v3.8.31 (present at the cycle-open tip),
order-dependent: the test passes in isolation, fails after the preceding cases.
Add a test.beforeEach(resetAllCircuitBreakers) so each scenario starts from a
clean breaker slate. Test-isolation only — the breaker behavior is correct and
no production code or assertion changes. Full combo suite: 390/390 green.
…der [DRAFT] (#4042)

Adds copilot-m365-web, a web-session provider that speaks Microsoft Substrate
BizChat over SignalR/WebSocket for the individual M365 path
(m365.cloud.microsoft/chat → wss://substrate.office.com/m365Copilot/Chathub/...).

Built from @skyzea1's real, sanitized #4042 frame capture:
- copilot-m365-frames.ts — pure, transport-free SignalR framing: \x1e split/join,
  handshake + keepalive frames, type:4 chat-invocation builder, type:1/2/3
  classification, accumulated-text → incremental-delta extraction.
- copilot-m365-connection.ts — pure URL/credential/prompt helpers (no executor
  runtime); the opaque individual access_token is passed through verbatim, the
  Chathub path (<user-oid>@<tenant-id>) is pasted alongside it, and the token
  rides the WS query string with a redactWsUrl() guard so it is never logged.
- copilot-m365-web.ts — the WebSocket transport (modeled on copilot-web.ts):
  handshake → keepalive → type:4 send → decode type:1/2/3 → OpenAI SSE. Errors
  route through sanitizeErrorMessage(); abort/timeout are handled.
- Wiring: registry entry + executors/index + providers/index + providers.ts
  metadata + webSessionCredentials + file-size baseline.

Tests (necessary layer): 23 unit tests pin the wire format and helpers against
the real capture (frame encode/decode, handshake, redaction, prompt flatten).

DRAFT — NOT for merge until the Rule #18 live round-trip with @skyzea1 confirms
the per-tier query params + generated session/trace ids against a live socket.
The enterprise tier (#3897) is deferred pending @Forcerecon's send/response frames.

Co-authored-by: skyzea1 <skyzea1@users.noreply.github.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.31 to release/v3.8.32 June 20, 2026 18:31
@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.32 to release/v3.8.33 June 21, 2026 14:03
@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.33 to release/v3.8.34 June 22, 2026 07:40
diegosouzapw added a commit that referenced this pull request Jun 22, 2026
diegosouzapw added a commit that referenced this pull request Jun 23, 2026
* chore(release): open v3.8.34 development cycle

* chore(quality): release-green pre-flight validator + nightly signal (C+D) (#4622)

C — scripts/quality/validate-release-green.mjs (npm run check:release-green):
reproduces the release-equivalent validation (typecheck, eslint, db-rules,
public-creds, full unit, vitest, ratchets, optional --with-build package-artifact)
against the current working tree and classifies each red as HARD (real defect,
exit 1) vs DRIFT (ratchet — reported, never affects exit / never blocks). Pure
helpers exported + orchestration behind a direct-run guard; unit-tested.

D — .github/workflows/nightly-release-green.yml: runs C on the active release
branch nightly (and on workflow_dispatch) and opens/updates a single tracking
issue on HARD failures. Never a required check, never touches a contributor PR.

Closes the gap where the full gate (ci.yml) only ran on the release PR, so reds
accrued silently on release/** and surfaced in 40-min layers at release time.
Non-blocking by construction; drift is the maintainer's to rebaseline at release.

Co-authored-by: Diego Rodrigues de Sa e Souza <diego.souza@cdwasolutions.com.br>

* fix(providers): show revealed connection API keys (#4583)

Integrated into release/v3.8.34

* fix(resilience): respect upstream retry hint toggle (#4585)

Integrated into release/v3.8.34

* feat(settings): expose stream recovery feature flags (#4586)

Integrated into release/v3.8.34

* fix(logs): make active request stale sweep configurable (#4599)

Integrated into release/v3.8.34

* fix(plugin): auto-prefix providerId with 'opencode-' for OC 1.17.8+ native gate (#4527)

Integrated into release/v3.8.34 (supersedes #4445)

* fix(models): treat unknown output caps as unset (#4584)

Integrated into release/v3.8.34

* fix(executors): strip temperature for GitHub Copilot gpt-5.4 family (#4564)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(oauth): update Qwen OAuth URLs from chat.qwen.ai to qwen.ai (#4561)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(api/settings): prevent cached /api/settings responses (port from 9router#951) (#4566)

Integrated into release/v3.8.34 (rebuilt onto tip)

* feat(audio): MiniMax T2A v2 TTS dispatch in audioSpeech (port #1043) (#4553)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(dashboard): surface manual config CTA when Open Claw CLI auto-detect fails (#4562)

Integrated into release/v3.8.34 (rebuilt onto tip)

* feat(providers): optional model ID for custom API-key validation (#4555)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(cli): align data dir and env loading with runtime (#4607)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(quota): expose Bailian quota windows (#4610)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix: retain provider cooldowns for configured max window (#4588)

Integrated into release/v3.8.34 (rebuilt — bundled commits stripped)

* fix: reject invalid provider cooldown bounds (#4589)

Integrated into release/v3.8.34 (rebuilt — bundled commits stripped)

* fix: preserve production combo metrics on shadow eviction (#4590)

Integrated into release/v3.8.34 (rebuilt — bundled commits stripped)

* fix(stream): estimate input tokens when upstream reports prompt_tokens=0 (#4615)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(catalog): shorten no-thinking gateway prefix to no-think/ (#4525)

Integrated into release/v3.8.34 (rebuilt — kept only the prefix rename, dropped stale-base reverts)

* fix(relay): apply IP rate limit to bifrost sidecar (#4593)

Integrated into release/v3.8.34 (rebuilt onto tip; merge before #4612)

* fix(bifrost): finalize SSE relay usage after stream (#4612)

Integrated into release/v3.8.34 (rebuilt + reconciled with #4593)

* feat(compression): per-request `x-omniroute-compression` header (Phase 3) (#4645)

* docs(compression): Phase 3 per-request header design spec

Approved brainstorming output for the x-omniroute-compression header:
header-first precedence, name-first combo matching (Decision A), explicit
value bypasses auto-trigger (Decision B), DerivedPlan.source, and the
X-OmniRoute-Compression response header.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(compression): Phase 3 per-request header implementation plan

4-task TDD plan (resolver header-first + source, parser, chatCore wiring +
response header, docs/file-size) with full code and exact commands.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(compression): header-first resolver + plan source (Phase 3 core)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(compression): resolveCompressionHeader parser (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(compression): wire x-omniroute-compression header + response header (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(compression): extract plan-resolution leaf (planResolution.ts) under size cap (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(compression): document x-omniroute-compression header (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(compression): harden named-combo map + trim engine: header id (Phase 3 review)

Addresses gemini-code-assist review on #4645:
- Extract buildNamedComboLookup (pure) so a blank/whitespace/null combo name
  contributes only its id key (no '' key, no throw that disables all combos).
- Trim the engine:<id> header value so 'engine: rtk' resolves.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <diego.souza@cdwasolutions.com.br>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* fix: exclude exhausted connections from auto scoring (#4592)

Integrated into release/v3.8.34 (rebuilt + opt-in gate fix)

* fix(dashboard): memoize compatible provider groups (#4613)

Integrated into release/v3.8.34 (rebuilt + test added)

* fix(dashboard): isolate quota widget refresh clock (#4611)

Integrated into release/v3.8.34 (rebuilt + jsdom test)

* fix(dashboard): gate topology side effects behind widget visibility (#4606)

Integrated into release/v3.8.34 (rebuilt + jsdom test)

* fix(dashboard): keep play_arrow spinning on provider Test All buttons (#4563)

Integrated into release/v3.8.34 (rebuilt onto tip; UI-cosmetic per owner)

* fix(db): schedule retention cleanup + fix cleanup table/column names (extracted from #4428) (#4691)

Integrated into release/v3.8.34 (cleanup core extracted from #4428, credit @oyi77)

* fix(telemetry): back off live-WS event forwarding when the sidecar is unreachable (#4604) (#4687)

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* fix(api): serve GET /v1/models/{model} as JSON, not the HTML dashboard (#4674) (#4677)

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* feat(opencode): add go deepseek reasoning variants (#4647)

Integrated into release/v3.8.34

* fix(executors): robust deepseek-web tool-call parsing and agentic context retention (#4644)

Integrated into release/v3.8.34

* fix(cli): authenticate `omniroute logs` and honor active context (#4638)

Integrated into release/v3.8.34 (authored by Rahul Sharma, AI co-author trailer stripped per project policy)

* fix(proxy): apply pipelining:0 + connections cap to the direct dispatcher (#4580) (#4684)

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* fix(executors): Firecrawl web_fetch 500 with include_metadata=true (#4692)

Integrated into release/v3.8.34

* fix(routing): include all noAuth models in auto-combos + add reka-flash + best-free template (#4621)

Integrated into release/v3.8.34 (dead getFirstRegistryModelId dropped, rebuilt onto tip)

* fix(dashboard): gate home topology live-WS networking (#4596) (#4618)

Integrated into release/v3.8.34 (adapted onto #4606's extracted topology section: default-hidden flip + enabled gate on useLiveDashboard)

* fix(cli): align `omniroute` env loading with the runtime data dir (#4597) (#4619)

Integrated into release/v3.8.34 (data-dir.mjs refactor reconciled with #4607; loadEnvFile aligned to getDefaultDataDir)

* chore(quality): reconcile file-size baseline for #4644 (deepseek-web.ts 1117->1125) (#4695)

file-size reconcile for #4644

* Support quota scraping for OpenCode Go and Ollama Cloud (#4642)

Integrated into release/v3.8.34 (Ollama Cloud + OpenCode Go dashboard quota scraping; rebuilt onto tip, gates green: typecheck/public-creds/file-size/lint/docs-sync + 31 tests)

* feat(executors): land M365 Copilot pure framing + connection helpers (#4042) (#4696)

Land M365 pure modules ahead of draft #4400

* deps: bump production + development groups; migrate js-yaml to v5 ESM (#4697)

Incorporates Dependabot #4667 + #4668 + js-yaml v5 ESM migration into release/v3.8.34

* fix: noAuth provider validation + kimi executor routing (#4699)

Integrated into release/v3.8.34 (noAuth in NOAUTH_PROVIDERS dynamic check + remove misrouted kimi web alias; 9 tests)

* refactor(imageGeneration): extract 8 provider families to co-located files (#4609)

Integrated into release/v3.8.34 (extraction completed: added missing imports/exports per module, main imports handlers locally; 145 image-gen tests pass, typecheck/cycles/file-size green)

* chore(release): v3.8.34 — finalize changelog, rebaseline drift, fix release-green reds

- Finalize CHANGELOG [3.8.34] (43 bullets, full contributor attribution) + seed i18n mirrors
- Rebaseline inherited cycle drift surfaced by release-green pre-flight: eslint warnings
  3900->3907, cognitive-complexity 797->801 (release-finalize touches no prod code; all
  drift is from this cycle's contributor merges)
- fix(providers): keep reka-flash-3 as the Reka provider default. #4621 inserted reka-flash
  at the head of the model list, silently changing the default from reka-flash-3 (the
  free-tier model) to reka-flash; reorder so reka-flash-3 stays default, reka-flash retained.
- test: align provider-models-config / provider-models-route / web-cookie-providers-new with
  #4621 (reka-flash now in the Reka catalog) and #4699 (the `kimi` API-key provider correctly
  falls through to DefaultExecutor instead of KimiWebExecutor)
- chore(quality): allowlist the COMPRESSION_GUIDE doc name in check-fabricated-docs
  (false-positive env-var match; docs/compression/COMPRESSION_GUIDE.md exists)

* fix(release-green): resolve release-PR full-CI reds for v3.8.34

Surfaced only on the release PR (these gates don't run on PR->release fast-gates):

- fix(quota): complete HTML-comment sanitization in opencodeOllamaUsage SSR reset-time
  parsing — strip any <!--...--> generically instead of the two literal React hydration
  markers, so no partial "<!--" can survive (CodeQL js/incomplete-multi-character-
  sanitization, HIGH, introduced by #4642). Regression test added.
- test(codex): correct the Codex-fingerprint body key order assertion to match the
  canonical bodyFieldOrder (prompt_cache_key precedes include); #4584 flipped the two
  and integration tests don't run on fast-gates so it never executed until the release PR.
- chore(quality): rebaseline inherited cycle drift surfaced by full CI —
  zizmorFindings 152->155 (+3 unpinned-uses in nightly-release-green.yml from #4622,
  same @vn convention as ci.yml) and openapiCoverage.pct 38.4->37.8 (-0.6, contributor
  routes added faster than openapi docs). Release-finalize touches no prod routes.

* fix(release-green): complete CodeQL sanitization + rebaseline complexity drift

- fix(quota): handle unterminated HTML comments in opencodeOllamaUsage SSR reset-time
  parsing — the `(?:-->|$)` arm consumes a trailing "<!--" with no closing "-->", so no
  partial "<!--" can survive (CodeQL js/incomplete-multi-character-sanitization persisted
  with the plain <!--...--> form because an unclosed comment could still leave "<!--").
- chore(quality): rebaseline cyclomatic complexity 1915->1916 (+1) — inherited v3.8.34
  cycle drift (contributor feature branches); check:complexity does not run on PR->release
  fast-gates so it surfaced only on the release PR. Release-finalize adds 0 complexity
  (measured 1916 with/without the regex tweak). dead-code/cognitive/type-coverage/
  compression-budget/codeql ratchets all pass.

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <diego.souza@cdwasolutions.com.br>
Co-authored-by: Randi <55005611+rdself@users.noreply.github.com>
Co-authored-by: Hernan Javier Ardila Sanchez <hjasgr@gmail.com>
Co-authored-by: KooshaPari <42529354+KooshaPari@users.noreply.github.com>
Co-authored-by: Abhishek Divekar <adivekar@utexas.edu>
Co-authored-by: Rahul sharma <sharmaR0810@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>
Co-authored-by: Ronald Estacion <DevEstacion@users.noreply.github.com>
Co-authored-by: Igor <60442260+BugsBag@users.noreply.github.com>
Co-authored-by: Oonishi <275808243+ponkcore@users.noreply.github.com>
Co-authored-by: Paijo <14921983+oyi77@users.noreply.github.com>
Co-authored-by: Jan Leon <Jan.gaschler@gmail.com>
@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.34 to release/v3.8.35 June 23, 2026 06:51
@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.35 to release/v3.8.36 June 23, 2026 21:35
@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.36 to release/v3.8.37 June 25, 2026 22:01
@diegosouzapw

Copy link
Copy Markdown
Owner Author

Fechando o DRAFT: a camada de helpers (copilot-m365-frames.ts, copilot-m365-connection.ts + testes) já está no release/v3.8.37. Falta apenas o executor/transport copilot-m365-web.ts + wiring, que segue bloqueado em validação live (Rule #18) com @skyzea1 contra um socket BizChat real. Reabrir como follow-up de #4042 quando a validação live estiver disponível.

@skyzea1

skyzea1 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Follow-up PR opened with all credentials/account-specific values redacted: #5287

Validation summary:

  • Live m365.cloud.microsoft/chat round-trip completed on 2026-06-29.
  • Credentials, user/tenant path, account identifiers, and location-specific fields: REDACTED.
  • Observed redacted Chathub flow: wss://substrate.office.com/m365Copilot/Chathub/REDACTED?...access_token=REDACTED.
  • Fresh non-browser replay with newly generated IDs returned pong after including current non-secret variants and optionsSets.
  • Empty option flags completed without assistant text, so feat(providers): add live-validated Microsoft 365 Copilot individual provider [wating autor] #5287 includes validated defaults.
  • Focused M365 tests pass: 23/23.

HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
* chore(release): open v3.8.34 development cycle

* chore(quality): release-green pre-flight validator + nightly signal (C+D) (diegosouzapw#4622)

C — scripts/quality/validate-release-green.mjs (npm run check:release-green):
reproduces the release-equivalent validation (typecheck, eslint, db-rules,
public-creds, full unit, vitest, ratchets, optional --with-build package-artifact)
against the current working tree and classifies each red as HARD (real defect,
exit 1) vs DRIFT (ratchet — reported, never affects exit / never blocks). Pure
helpers exported + orchestration behind a direct-run guard; unit-tested.

D — .github/workflows/nightly-release-green.yml: runs C on the active release
branch nightly (and on workflow_dispatch) and opens/updates a single tracking
issue on HARD failures. Never a required check, never touches a contributor PR.

Closes the gap where the full gate (ci.yml) only ran on the release PR, so reds
accrued silently on release/** and surfaced in 40-min layers at release time.
Non-blocking by construction; drift is the maintainer's to rebaseline at release.

Co-authored-by: Diego Rodrigues de Sa e Souza <diego.souza@cdwasolutions.com.br>

* fix(providers): show revealed connection API keys (diegosouzapw#4583)

Integrated into release/v3.8.34

* fix(resilience): respect upstream retry hint toggle (diegosouzapw#4585)

Integrated into release/v3.8.34

* feat(settings): expose stream recovery feature flags (diegosouzapw#4586)

Integrated into release/v3.8.34

* fix(logs): make active request stale sweep configurable (diegosouzapw#4599)

Integrated into release/v3.8.34

* fix(plugin): auto-prefix providerId with 'opencode-' for OC 1.17.8+ native gate (diegosouzapw#4527)

Integrated into release/v3.8.34 (supersedes diegosouzapw#4445)

* fix(models): treat unknown output caps as unset (diegosouzapw#4584)

Integrated into release/v3.8.34

* fix(executors): strip temperature for GitHub Copilot gpt-5.4 family (diegosouzapw#4564)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(oauth): update Qwen OAuth URLs from chat.qwen.ai to qwen.ai (diegosouzapw#4561)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(api/settings): prevent cached /api/settings responses (port from 9router#951) (diegosouzapw#4566)

Integrated into release/v3.8.34 (rebuilt onto tip)

* feat(audio): MiniMax T2A v2 TTS dispatch in audioSpeech (port diegosouzapw#1043) (diegosouzapw#4553)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(dashboard): surface manual config CTA when Open Claw CLI auto-detect fails (diegosouzapw#4562)

Integrated into release/v3.8.34 (rebuilt onto tip)

* feat(providers): optional model ID for custom API-key validation (diegosouzapw#4555)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(cli): align data dir and env loading with runtime (diegosouzapw#4607)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(quota): expose Bailian quota windows (diegosouzapw#4610)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix: retain provider cooldowns for configured max window (diegosouzapw#4588)

Integrated into release/v3.8.34 (rebuilt — bundled commits stripped)

* fix: reject invalid provider cooldown bounds (diegosouzapw#4589)

Integrated into release/v3.8.34 (rebuilt — bundled commits stripped)

* fix: preserve production combo metrics on shadow eviction (diegosouzapw#4590)

Integrated into release/v3.8.34 (rebuilt — bundled commits stripped)

* fix(stream): estimate input tokens when upstream reports prompt_tokens=0 (diegosouzapw#4615)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(catalog): shorten no-thinking gateway prefix to no-think/ (diegosouzapw#4525)

Integrated into release/v3.8.34 (rebuilt — kept only the prefix rename, dropped stale-base reverts)

* fix(relay): apply IP rate limit to bifrost sidecar (diegosouzapw#4593)

Integrated into release/v3.8.34 (rebuilt onto tip; merge before diegosouzapw#4612)

* fix(bifrost): finalize SSE relay usage after stream (diegosouzapw#4612)

Integrated into release/v3.8.34 (rebuilt + reconciled with diegosouzapw#4593)

* feat(compression): per-request `x-omniroute-compression` header (Phase 3) (diegosouzapw#4645)

* docs(compression): Phase 3 per-request header design spec

Approved brainstorming output for the x-omniroute-compression header:
header-first precedence, name-first combo matching (Decision A), explicit
value bypasses auto-trigger (Decision B), DerivedPlan.source, and the
X-OmniRoute-Compression response header.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(compression): Phase 3 per-request header implementation plan

4-task TDD plan (resolver header-first + source, parser, chatCore wiring +
response header, docs/file-size) with full code and exact commands.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(compression): header-first resolver + plan source (Phase 3 core)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(compression): resolveCompressionHeader parser (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(compression): wire x-omniroute-compression header + response header (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(compression): extract plan-resolution leaf (planResolution.ts) under size cap (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(compression): document x-omniroute-compression header (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(compression): harden named-combo map + trim engine: header id (Phase 3 review)

Addresses gemini-code-assist review on diegosouzapw#4645:
- Extract buildNamedComboLookup (pure) so a blank/whitespace/null combo name
  contributes only its id key (no '' key, no throw that disables all combos).
- Trim the engine:<id> header value so 'engine: rtk' resolves.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <diego.souza@cdwasolutions.com.br>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* fix: exclude exhausted connections from auto scoring (diegosouzapw#4592)

Integrated into release/v3.8.34 (rebuilt + opt-in gate fix)

* fix(dashboard): memoize compatible provider groups (diegosouzapw#4613)

Integrated into release/v3.8.34 (rebuilt + test added)

* fix(dashboard): isolate quota widget refresh clock (diegosouzapw#4611)

Integrated into release/v3.8.34 (rebuilt + jsdom test)

* fix(dashboard): gate topology side effects behind widget visibility (diegosouzapw#4606)

Integrated into release/v3.8.34 (rebuilt + jsdom test)

* fix(dashboard): keep play_arrow spinning on provider Test All buttons (diegosouzapw#4563)

Integrated into release/v3.8.34 (rebuilt onto tip; UI-cosmetic per owner)

* fix(db): schedule retention cleanup + fix cleanup table/column names (extracted from diegosouzapw#4428) (diegosouzapw#4691)

Integrated into release/v3.8.34 (cleanup core extracted from diegosouzapw#4428, credit @oyi77)

* fix(telemetry): back off live-WS event forwarding when the sidecar is unreachable (diegosouzapw#4604) (diegosouzapw#4687)

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* fix(api): serve GET /v1/models/{model} as JSON, not the HTML dashboard (diegosouzapw#4674) (diegosouzapw#4677)

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* feat(opencode): add go deepseek reasoning variants (diegosouzapw#4647)

Integrated into release/v3.8.34

* fix(executors): robust deepseek-web tool-call parsing and agentic context retention (diegosouzapw#4644)

Integrated into release/v3.8.34

* fix(cli): authenticate `omniroute logs` and honor active context (diegosouzapw#4638)

Integrated into release/v3.8.34 (authored by Rahul Sharma, AI co-author trailer stripped per project policy)

* fix(proxy): apply pipelining:0 + connections cap to the direct dispatcher (diegosouzapw#4580) (diegosouzapw#4684)

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* fix(executors): Firecrawl web_fetch 500 with include_metadata=true (diegosouzapw#4692)

Integrated into release/v3.8.34

* fix(routing): include all noAuth models in auto-combos + add reka-flash + best-free template (diegosouzapw#4621)

Integrated into release/v3.8.34 (dead getFirstRegistryModelId dropped, rebuilt onto tip)

* fix(dashboard): gate home topology live-WS networking (diegosouzapw#4596) (diegosouzapw#4618)

Integrated into release/v3.8.34 (adapted onto diegosouzapw#4606's extracted topology section: default-hidden flip + enabled gate on useLiveDashboard)

* fix(cli): align `omniroute` env loading with the runtime data dir (diegosouzapw#4597) (diegosouzapw#4619)

Integrated into release/v3.8.34 (data-dir.mjs refactor reconciled with diegosouzapw#4607; loadEnvFile aligned to getDefaultDataDir)

* chore(quality): reconcile file-size baseline for diegosouzapw#4644 (deepseek-web.ts 1117->1125) (diegosouzapw#4695)

file-size reconcile for diegosouzapw#4644

* Support quota scraping for OpenCode Go and Ollama Cloud (diegosouzapw#4642)

Integrated into release/v3.8.34 (Ollama Cloud + OpenCode Go dashboard quota scraping; rebuilt onto tip, gates green: typecheck/public-creds/file-size/lint/docs-sync + 31 tests)

* feat(executors): land M365 Copilot pure framing + connection helpers (diegosouzapw#4042) (diegosouzapw#4696)

Land M365 pure modules ahead of draft diegosouzapw#4400

* deps: bump production + development groups; migrate js-yaml to v5 ESM (diegosouzapw#4697)

Incorporates Dependabot diegosouzapw#4667 + diegosouzapw#4668 + js-yaml v5 ESM migration into release/v3.8.34

* fix: noAuth provider validation + kimi executor routing (diegosouzapw#4699)

Integrated into release/v3.8.34 (noAuth in NOAUTH_PROVIDERS dynamic check + remove misrouted kimi web alias; 9 tests)

* refactor(imageGeneration): extract 8 provider families to co-located files (diegosouzapw#4609)

Integrated into release/v3.8.34 (extraction completed: added missing imports/exports per module, main imports handlers locally; 145 image-gen tests pass, typecheck/cycles/file-size green)

* chore(release): v3.8.34 — finalize changelog, rebaseline drift, fix release-green reds

- Finalize CHANGELOG [3.8.34] (43 bullets, full contributor attribution) + seed i18n mirrors
- Rebaseline inherited cycle drift surfaced by release-green pre-flight: eslint warnings
  3900->3907, cognitive-complexity 797->801 (release-finalize touches no prod code; all
  drift is from this cycle's contributor merges)
- fix(providers): keep reka-flash-3 as the Reka provider default. diegosouzapw#4621 inserted reka-flash
  at the head of the model list, silently changing the default from reka-flash-3 (the
  free-tier model) to reka-flash; reorder so reka-flash-3 stays default, reka-flash retained.
- test: align provider-models-config / provider-models-route / web-cookie-providers-new with
  diegosouzapw#4621 (reka-flash now in the Reka catalog) and diegosouzapw#4699 (the `kimi` API-key provider correctly
  falls through to DefaultExecutor instead of KimiWebExecutor)
- chore(quality): allowlist the COMPRESSION_GUIDE doc name in check-fabricated-docs
  (false-positive env-var match; docs/compression/COMPRESSION_GUIDE.md exists)

* fix(release-green): resolve release-PR full-CI reds for v3.8.34

Surfaced only on the release PR (these gates don't run on PR->release fast-gates):

- fix(quota): complete HTML-comment sanitization in opencodeOllamaUsage SSR reset-time
  parsing — strip any <!--...--> generically instead of the two literal React hydration
  markers, so no partial "<!--" can survive (CodeQL js/incomplete-multi-character-
  sanitization, HIGH, introduced by diegosouzapw#4642). Regression test added.
- test(codex): correct the Codex-fingerprint body key order assertion to match the
  canonical bodyFieldOrder (prompt_cache_key precedes include); diegosouzapw#4584 flipped the two
  and integration tests don't run on fast-gates so it never executed until the release PR.
- chore(quality): rebaseline inherited cycle drift surfaced by full CI —
  zizmorFindings 152->155 (+3 unpinned-uses in nightly-release-green.yml from diegosouzapw#4622,
  same @vn convention as ci.yml) and openapiCoverage.pct 38.4->37.8 (-0.6, contributor
  routes added faster than openapi docs). Release-finalize touches no prod routes.

* fix(release-green): complete CodeQL sanitization + rebaseline complexity drift

- fix(quota): handle unterminated HTML comments in opencodeOllamaUsage SSR reset-time
  parsing — the `(?:-->|$)` arm consumes a trailing "<!--" with no closing "-->", so no
  partial "<!--" can survive (CodeQL js/incomplete-multi-character-sanitization persisted
  with the plain <!--...--> form because an unclosed comment could still leave "<!--").
- chore(quality): rebaseline cyclomatic complexity 1915->1916 (+1) — inherited v3.8.34
  cycle drift (contributor feature branches); check:complexity does not run on PR->release
  fast-gates so it surfaced only on the release PR. Release-finalize adds 0 complexity
  (measured 1916 with/without the regex tweak). dead-code/cognitive/type-coverage/
  compression-budget/codeql ratchets all pass.

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <diego.souza@cdwasolutions.com.br>
Co-authored-by: Randi <55005611+rdself@users.noreply.github.com>
Co-authored-by: Hernan Javier Ardila Sanchez <hjasgr@gmail.com>
Co-authored-by: KooshaPari <42529354+KooshaPari@users.noreply.github.com>
Co-authored-by: Abhishek Divekar <adivekar@utexas.edu>
Co-authored-by: Rahul sharma <sharmaR0810@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>
Co-authored-by: Ronald Estacion <DevEstacion@users.noreply.github.com>
Co-authored-by: Igor <60442260+BugsBag@users.noreply.github.com>
Co-authored-by: Oonishi <275808243+ponkcore@users.noreply.github.com>
Co-authored-by: Paijo <14921983+oyi77@users.noreply.github.com>
Co-authored-by: Jan Leon <Jan.gaschler@gmail.com>
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
* chore(release): open v3.8.34 development cycle

* chore(quality): release-green pre-flight validator + nightly signal (C+D) (diegosouzapw#4622)

C — scripts/quality/validate-release-green.mjs (npm run check:release-green):
reproduces the release-equivalent validation (typecheck, eslint, db-rules,
public-creds, full unit, vitest, ratchets, optional --with-build package-artifact)
against the current working tree and classifies each red as HARD (real defect,
exit 1) vs DRIFT (ratchet — reported, never affects exit / never blocks). Pure
helpers exported + orchestration behind a direct-run guard; unit-tested.

D — .github/workflows/nightly-release-green.yml: runs C on the active release
branch nightly (and on workflow_dispatch) and opens/updates a single tracking
issue on HARD failures. Never a required check, never touches a contributor PR.

Closes the gap where the full gate (ci.yml) only ran on the release PR, so reds
accrued silently on release/** and surfaced in 40-min layers at release time.
Non-blocking by construction; drift is the maintainer's to rebaseline at release.

Co-authored-by: Diego Rodrigues de Sa e Souza <diego.souza@cdwasolutions.com.br>

* fix(providers): show revealed connection API keys (diegosouzapw#4583)

Integrated into release/v3.8.34

* fix(resilience): respect upstream retry hint toggle (diegosouzapw#4585)

Integrated into release/v3.8.34

* feat(settings): expose stream recovery feature flags (diegosouzapw#4586)

Integrated into release/v3.8.34

* fix(logs): make active request stale sweep configurable (diegosouzapw#4599)

Integrated into release/v3.8.34

* fix(plugin): auto-prefix providerId with 'opencode-' for OC 1.17.8+ native gate (diegosouzapw#4527)

Integrated into release/v3.8.34 (supersedes diegosouzapw#4445)

* fix(models): treat unknown output caps as unset (diegosouzapw#4584)

Integrated into release/v3.8.34

* fix(executors): strip temperature for GitHub Copilot gpt-5.4 family (diegosouzapw#4564)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(oauth): update Qwen OAuth URLs from chat.qwen.ai to qwen.ai (diegosouzapw#4561)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(api/settings): prevent cached /api/settings responses (port from 9router#951) (diegosouzapw#4566)

Integrated into release/v3.8.34 (rebuilt onto tip)

* feat(audio): MiniMax T2A v2 TTS dispatch in audioSpeech (port diegosouzapw#1043) (diegosouzapw#4553)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(dashboard): surface manual config CTA when Open Claw CLI auto-detect fails (diegosouzapw#4562)

Integrated into release/v3.8.34 (rebuilt onto tip)

* feat(providers): optional model ID for custom API-key validation (diegosouzapw#4555)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(cli): align data dir and env loading with runtime (diegosouzapw#4607)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(quota): expose Bailian quota windows (diegosouzapw#4610)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix: retain provider cooldowns for configured max window (diegosouzapw#4588)

Integrated into release/v3.8.34 (rebuilt — bundled commits stripped)

* fix: reject invalid provider cooldown bounds (diegosouzapw#4589)

Integrated into release/v3.8.34 (rebuilt — bundled commits stripped)

* fix: preserve production combo metrics on shadow eviction (diegosouzapw#4590)

Integrated into release/v3.8.34 (rebuilt — bundled commits stripped)

* fix(stream): estimate input tokens when upstream reports prompt_tokens=0 (diegosouzapw#4615)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(catalog): shorten no-thinking gateway prefix to no-think/ (diegosouzapw#4525)

Integrated into release/v3.8.34 (rebuilt — kept only the prefix rename, dropped stale-base reverts)

* fix(relay): apply IP rate limit to bifrost sidecar (diegosouzapw#4593)

Integrated into release/v3.8.34 (rebuilt onto tip; merge before diegosouzapw#4612)

* fix(bifrost): finalize SSE relay usage after stream (diegosouzapw#4612)

Integrated into release/v3.8.34 (rebuilt + reconciled with diegosouzapw#4593)

* feat(compression): per-request `x-omniroute-compression` header (Phase 3) (diegosouzapw#4645)

* docs(compression): Phase 3 per-request header design spec

Approved brainstorming output for the x-omniroute-compression header:
header-first precedence, name-first combo matching (Decision A), explicit
value bypasses auto-trigger (Decision B), DerivedPlan.source, and the
X-OmniRoute-Compression response header.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(compression): Phase 3 per-request header implementation plan

4-task TDD plan (resolver header-first + source, parser, chatCore wiring +
response header, docs/file-size) with full code and exact commands.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(compression): header-first resolver + plan source (Phase 3 core)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(compression): resolveCompressionHeader parser (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(compression): wire x-omniroute-compression header + response header (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(compression): extract plan-resolution leaf (planResolution.ts) under size cap (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(compression): document x-omniroute-compression header (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(compression): harden named-combo map + trim engine: header id (Phase 3 review)

Addresses gemini-code-assist review on diegosouzapw#4645:
- Extract buildNamedComboLookup (pure) so a blank/whitespace/null combo name
  contributes only its id key (no '' key, no throw that disables all combos).
- Trim the engine:<id> header value so 'engine: rtk' resolves.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <diego.souza@cdwasolutions.com.br>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* fix: exclude exhausted connections from auto scoring (diegosouzapw#4592)

Integrated into release/v3.8.34 (rebuilt + opt-in gate fix)

* fix(dashboard): memoize compatible provider groups (diegosouzapw#4613)

Integrated into release/v3.8.34 (rebuilt + test added)

* fix(dashboard): isolate quota widget refresh clock (diegosouzapw#4611)

Integrated into release/v3.8.34 (rebuilt + jsdom test)

* fix(dashboard): gate topology side effects behind widget visibility (diegosouzapw#4606)

Integrated into release/v3.8.34 (rebuilt + jsdom test)

* fix(dashboard): keep play_arrow spinning on provider Test All buttons (diegosouzapw#4563)

Integrated into release/v3.8.34 (rebuilt onto tip; UI-cosmetic per owner)

* fix(db): schedule retention cleanup + fix cleanup table/column names (extracted from diegosouzapw#4428) (diegosouzapw#4691)

Integrated into release/v3.8.34 (cleanup core extracted from diegosouzapw#4428, credit @oyi77)

* fix(telemetry): back off live-WS event forwarding when the sidecar is unreachable (diegosouzapw#4604) (diegosouzapw#4687)

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* fix(api): serve GET /v1/models/{model} as JSON, not the HTML dashboard (diegosouzapw#4674) (diegosouzapw#4677)

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* feat(opencode): add go deepseek reasoning variants (diegosouzapw#4647)

Integrated into release/v3.8.34

* fix(executors): robust deepseek-web tool-call parsing and agentic context retention (diegosouzapw#4644)

Integrated into release/v3.8.34

* fix(cli): authenticate `omniroute logs` and honor active context (diegosouzapw#4638)

Integrated into release/v3.8.34 (authored by Rahul Sharma, AI co-author trailer stripped per project policy)

* fix(proxy): apply pipelining:0 + connections cap to the direct dispatcher (diegosouzapw#4580) (diegosouzapw#4684)

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* fix(executors): Firecrawl web_fetch 500 with include_metadata=true (diegosouzapw#4692)

Integrated into release/v3.8.34

* fix(routing): include all noAuth models in auto-combos + add reka-flash + best-free template (diegosouzapw#4621)

Integrated into release/v3.8.34 (dead getFirstRegistryModelId dropped, rebuilt onto tip)

* fix(dashboard): gate home topology live-WS networking (diegosouzapw#4596) (diegosouzapw#4618)

Integrated into release/v3.8.34 (adapted onto diegosouzapw#4606's extracted topology section: default-hidden flip + enabled gate on useLiveDashboard)

* fix(cli): align `omniroute` env loading with the runtime data dir (diegosouzapw#4597) (diegosouzapw#4619)

Integrated into release/v3.8.34 (data-dir.mjs refactor reconciled with diegosouzapw#4607; loadEnvFile aligned to getDefaultDataDir)

* chore(quality): reconcile file-size baseline for diegosouzapw#4644 (deepseek-web.ts 1117->1125) (diegosouzapw#4695)

file-size reconcile for diegosouzapw#4644

* Support quota scraping for OpenCode Go and Ollama Cloud (diegosouzapw#4642)

Integrated into release/v3.8.34 (Ollama Cloud + OpenCode Go dashboard quota scraping; rebuilt onto tip, gates green: typecheck/public-creds/file-size/lint/docs-sync + 31 tests)

* feat(executors): land M365 Copilot pure framing + connection helpers (diegosouzapw#4042) (diegosouzapw#4696)

Land M365 pure modules ahead of draft diegosouzapw#4400

* deps: bump production + development groups; migrate js-yaml to v5 ESM (diegosouzapw#4697)

Incorporates Dependabot diegosouzapw#4667 + diegosouzapw#4668 + js-yaml v5 ESM migration into release/v3.8.34

* fix: noAuth provider validation + kimi executor routing (diegosouzapw#4699)

Integrated into release/v3.8.34 (noAuth in NOAUTH_PROVIDERS dynamic check + remove misrouted kimi web alias; 9 tests)

* refactor(imageGeneration): extract 8 provider families to co-located files (diegosouzapw#4609)

Integrated into release/v3.8.34 (extraction completed: added missing imports/exports per module, main imports handlers locally; 145 image-gen tests pass, typecheck/cycles/file-size green)

* chore(release): v3.8.34 — finalize changelog, rebaseline drift, fix release-green reds

- Finalize CHANGELOG [3.8.34] (43 bullets, full contributor attribution) + seed i18n mirrors
- Rebaseline inherited cycle drift surfaced by release-green pre-flight: eslint warnings
  3900->3907, cognitive-complexity 797->801 (release-finalize touches no prod code; all
  drift is from this cycle's contributor merges)
- fix(providers): keep reka-flash-3 as the Reka provider default. diegosouzapw#4621 inserted reka-flash
  at the head of the model list, silently changing the default from reka-flash-3 (the
  free-tier model) to reka-flash; reorder so reka-flash-3 stays default, reka-flash retained.
- test: align provider-models-config / provider-models-route / web-cookie-providers-new with
  diegosouzapw#4621 (reka-flash now in the Reka catalog) and diegosouzapw#4699 (the `kimi` API-key provider correctly
  falls through to DefaultExecutor instead of KimiWebExecutor)
- chore(quality): allowlist the COMPRESSION_GUIDE doc name in check-fabricated-docs
  (false-positive env-var match; docs/compression/COMPRESSION_GUIDE.md exists)

* fix(release-green): resolve release-PR full-CI reds for v3.8.34

Surfaced only on the release PR (these gates don't run on PR->release fast-gates):

- fix(quota): complete HTML-comment sanitization in opencodeOllamaUsage SSR reset-time
  parsing — strip any <!--...--> generically instead of the two literal React hydration
  markers, so no partial "<!--" can survive (CodeQL js/incomplete-multi-character-
  sanitization, HIGH, introduced by diegosouzapw#4642). Regression test added.
- test(codex): correct the Codex-fingerprint body key order assertion to match the
  canonical bodyFieldOrder (prompt_cache_key precedes include); diegosouzapw#4584 flipped the two
  and integration tests don't run on fast-gates so it never executed until the release PR.
- chore(quality): rebaseline inherited cycle drift surfaced by full CI —
  zizmorFindings 152->155 (+3 unpinned-uses in nightly-release-green.yml from diegosouzapw#4622,
  same @vn convention as ci.yml) and openapiCoverage.pct 38.4->37.8 (-0.6, contributor
  routes added faster than openapi docs). Release-finalize touches no prod routes.

* fix(release-green): complete CodeQL sanitization + rebaseline complexity drift

- fix(quota): handle unterminated HTML comments in opencodeOllamaUsage SSR reset-time
  parsing — the `(?:-->|$)` arm consumes a trailing "<!--" with no closing "-->", so no
  partial "<!--" can survive (CodeQL js/incomplete-multi-character-sanitization persisted
  with the plain <!--...--> form because an unclosed comment could still leave "<!--").
- chore(quality): rebaseline cyclomatic complexity 1915->1916 (+1) — inherited v3.8.34
  cycle drift (contributor feature branches); check:complexity does not run on PR->release
  fast-gates so it surfaced only on the release PR. Release-finalize adds 0 complexity
  (measured 1916 with/without the regex tweak). dead-code/cognitive/type-coverage/
  compression-budget/codeql ratchets all pass.

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <diego.souza@cdwasolutions.com.br>
Co-authored-by: Randi <55005611+rdself@users.noreply.github.com>
Co-authored-by: Hernan Javier Ardila Sanchez <hjasgr@gmail.com>
Co-authored-by: KooshaPari <42529354+KooshaPari@users.noreply.github.com>
Co-authored-by: Abhishek Divekar <adivekar@utexas.edu>
Co-authored-by: Rahul sharma <sharmaR0810@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>
Co-authored-by: Ronald Estacion <DevEstacion@users.noreply.github.com>
Co-authored-by: Igor <60442260+BugsBag@users.noreply.github.com>
Co-authored-by: Oonishi <275808243+ponkcore@users.noreply.github.com>
Co-authored-by: Paijo <14921983+oyi77@users.noreply.github.com>
Co-authored-by: Jan Leon <Jan.gaschler@gmail.com>
tkgo11 pushed a commit to tkgo11/OmniRoute that referenced this pull request Sep 23, 2026
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
* chore(release): open v3.8.34 development cycle

* chore(quality): release-green pre-flight validator + nightly signal (C+D) (diegosouzapw#4622)

C — scripts/quality/validate-release-green.mjs (npm run check:release-green):
reproduces the release-equivalent validation (typecheck, eslint, db-rules,
public-creds, full unit, vitest, ratchets, optional --with-build package-artifact)
against the current working tree and classifies each red as HARD (real defect,
exit 1) vs DRIFT (ratchet — reported, never affects exit / never blocks). Pure
helpers exported + orchestration behind a direct-run guard; unit-tested.

D — .github/workflows/nightly-release-green.yml: runs C on the active release
branch nightly (and on workflow_dispatch) and opens/updates a single tracking
issue on HARD failures. Never a required check, never touches a contributor PR.

Closes the gap where the full gate (ci.yml) only ran on the release PR, so reds
accrued silently on release/** and surfaced in 40-min layers at release time.
Non-blocking by construction; drift is the maintainer's to rebaseline at release.

Co-authored-by: Diego Rodrigues de Sa e Souza <diego.souza@cdwasolutions.com.br>

* fix(providers): show revealed connection API keys (diegosouzapw#4583)

Integrated into release/v3.8.34

* fix(resilience): respect upstream retry hint toggle (diegosouzapw#4585)

Integrated into release/v3.8.34

* feat(settings): expose stream recovery feature flags (diegosouzapw#4586)

Integrated into release/v3.8.34

* fix(logs): make active request stale sweep configurable (diegosouzapw#4599)

Integrated into release/v3.8.34

* fix(plugin): auto-prefix providerId with 'opencode-' for OC 1.17.8+ native gate (diegosouzapw#4527)

Integrated into release/v3.8.34 (supersedes diegosouzapw#4445)

* fix(models): treat unknown output caps as unset (diegosouzapw#4584)

Integrated into release/v3.8.34

* fix(executors): strip temperature for GitHub Copilot gpt-5.4 family (diegosouzapw#4564)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(oauth): update Qwen OAuth URLs from chat.qwen.ai to qwen.ai (diegosouzapw#4561)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(api/settings): prevent cached /api/settings responses (port from 9router#951) (diegosouzapw#4566)

Integrated into release/v3.8.34 (rebuilt onto tip)

* feat(audio): MiniMax T2A v2 TTS dispatch in audioSpeech (port diegosouzapw#1043) (diegosouzapw#4553)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(dashboard): surface manual config CTA when Open Claw CLI auto-detect fails (diegosouzapw#4562)

Integrated into release/v3.8.34 (rebuilt onto tip)

* feat(providers): optional model ID for custom API-key validation (diegosouzapw#4555)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(cli): align data dir and env loading with runtime (diegosouzapw#4607)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(quota): expose Bailian quota windows (diegosouzapw#4610)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix: retain provider cooldowns for configured max window (diegosouzapw#4588)

Integrated into release/v3.8.34 (rebuilt — bundled commits stripped)

* fix: reject invalid provider cooldown bounds (diegosouzapw#4589)

Integrated into release/v3.8.34 (rebuilt — bundled commits stripped)

* fix: preserve production combo metrics on shadow eviction (diegosouzapw#4590)

Integrated into release/v3.8.34 (rebuilt — bundled commits stripped)

* fix(stream): estimate input tokens when upstream reports prompt_tokens=0 (diegosouzapw#4615)

Integrated into release/v3.8.34 (rebuilt onto tip)

* fix(catalog): shorten no-thinking gateway prefix to no-think/ (diegosouzapw#4525)

Integrated into release/v3.8.34 (rebuilt — kept only the prefix rename, dropped stale-base reverts)

* fix(relay): apply IP rate limit to bifrost sidecar (diegosouzapw#4593)

Integrated into release/v3.8.34 (rebuilt onto tip; merge before diegosouzapw#4612)

* fix(bifrost): finalize SSE relay usage after stream (diegosouzapw#4612)

Integrated into release/v3.8.34 (rebuilt + reconciled with diegosouzapw#4593)

* feat(compression): per-request `x-omniroute-compression` header (Phase 3) (diegosouzapw#4645)

* docs(compression): Phase 3 per-request header design spec

Approved brainstorming output for the x-omniroute-compression header:
header-first precedence, name-first combo matching (Decision A), explicit
value bypasses auto-trigger (Decision B), DerivedPlan.source, and the
X-OmniRoute-Compression response header.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(compression): Phase 3 per-request header implementation plan

4-task TDD plan (resolver header-first + source, parser, chatCore wiring +
response header, docs/file-size) with full code and exact commands.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(compression): header-first resolver + plan source (Phase 3 core)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(compression): resolveCompressionHeader parser (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(compression): wire x-omniroute-compression header + response header (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(compression): extract plan-resolution leaf (planResolution.ts) under size cap (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(compression): document x-omniroute-compression header (Phase 3)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(compression): harden named-combo map + trim engine: header id (Phase 3 review)

Addresses gemini-code-assist review on diegosouzapw#4645:
- Extract buildNamedComboLookup (pure) so a blank/whitespace/null combo name
  contributes only its id key (no '' key, no throw that disables all combos).
- Trim the engine:<id> header value so 'engine: rtk' resolves.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <diego.souza@cdwasolutions.com.br>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* fix: exclude exhausted connections from auto scoring (diegosouzapw#4592)

Integrated into release/v3.8.34 (rebuilt + opt-in gate fix)

* fix(dashboard): memoize compatible provider groups (diegosouzapw#4613)

Integrated into release/v3.8.34 (rebuilt + test added)

* fix(dashboard): isolate quota widget refresh clock (diegosouzapw#4611)

Integrated into release/v3.8.34 (rebuilt + jsdom test)

* fix(dashboard): gate topology side effects behind widget visibility (diegosouzapw#4606)

Integrated into release/v3.8.34 (rebuilt + jsdom test)

* fix(dashboard): keep play_arrow spinning on provider Test All buttons (diegosouzapw#4563)

Integrated into release/v3.8.34 (rebuilt onto tip; UI-cosmetic per owner)

* fix(db): schedule retention cleanup + fix cleanup table/column names (extracted from diegosouzapw#4428) (diegosouzapw#4691)

Integrated into release/v3.8.34 (cleanup core extracted from diegosouzapw#4428, credit @oyi77)

* fix(telemetry): back off live-WS event forwarding when the sidecar is unreachable (diegosouzapw#4604) (diegosouzapw#4687)

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* fix(api): serve GET /v1/models/{model} as JSON, not the HTML dashboard (diegosouzapw#4674) (diegosouzapw#4677)

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* feat(opencode): add go deepseek reasoning variants (diegosouzapw#4647)

Integrated into release/v3.8.34

* fix(executors): robust deepseek-web tool-call parsing and agentic context retention (diegosouzapw#4644)

Integrated into release/v3.8.34

* fix(cli): authenticate `omniroute logs` and honor active context (diegosouzapw#4638)

Integrated into release/v3.8.34 (authored by Rahul Sharma, AI co-author trailer stripped per project policy)

* fix(proxy): apply pipelining:0 + connections cap to the direct dispatcher (diegosouzapw#4580) (diegosouzapw#4684)

Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>

* fix(executors): Firecrawl web_fetch 500 with include_metadata=true (diegosouzapw#4692)

Integrated into release/v3.8.34

* fix(routing): include all noAuth models in auto-combos + add reka-flash + best-free template (diegosouzapw#4621)

Integrated into release/v3.8.34 (dead getFirstRegistryModelId dropped, rebuilt onto tip)

* fix(dashboard): gate home topology live-WS networking (diegosouzapw#4596) (diegosouzapw#4618)

Integrated into release/v3.8.34 (adapted onto diegosouzapw#4606's extracted topology section: default-hidden flip + enabled gate on useLiveDashboard)

* fix(cli): align `omniroute` env loading with the runtime data dir (diegosouzapw#4597) (diegosouzapw#4619)

Integrated into release/v3.8.34 (data-dir.mjs refactor reconciled with diegosouzapw#4607; loadEnvFile aligned to getDefaultDataDir)

* chore(quality): reconcile file-size baseline for diegosouzapw#4644 (deepseek-web.ts 1117->1125) (diegosouzapw#4695)

file-size reconcile for diegosouzapw#4644

* Support quota scraping for OpenCode Go and Ollama Cloud (diegosouzapw#4642)

Integrated into release/v3.8.34 (Ollama Cloud + OpenCode Go dashboard quota scraping; rebuilt onto tip, gates green: typecheck/public-creds/file-size/lint/docs-sync + 31 tests)

* feat(executors): land M365 Copilot pure framing + connection helpers (diegosouzapw#4042) (diegosouzapw#4696)

Land M365 pure modules ahead of draft diegosouzapw#4400

* deps: bump production + development groups; migrate js-yaml to v5 ESM (diegosouzapw#4697)

Incorporates Dependabot diegosouzapw#4667 + diegosouzapw#4668 + js-yaml v5 ESM migration into release/v3.8.34

* fix: noAuth provider validation + kimi executor routing (diegosouzapw#4699)

Integrated into release/v3.8.34 (noAuth in NOAUTH_PROVIDERS dynamic check + remove misrouted kimi web alias; 9 tests)

* refactor(imageGeneration): extract 8 provider families to co-located files (diegosouzapw#4609)

Integrated into release/v3.8.34 (extraction completed: added missing imports/exports per module, main imports handlers locally; 145 image-gen tests pass, typecheck/cycles/file-size green)

* chore(release): v3.8.34 — finalize changelog, rebaseline drift, fix release-green reds

- Finalize CHANGELOG [3.8.34] (43 bullets, full contributor attribution) + seed i18n mirrors
- Rebaseline inherited cycle drift surfaced by release-green pre-flight: eslint warnings
  3900->3907, cognitive-complexity 797->801 (release-finalize touches no prod code; all
  drift is from this cycle's contributor merges)
- fix(providers): keep reka-flash-3 as the Reka provider default. diegosouzapw#4621 inserted reka-flash
  at the head of the model list, silently changing the default from reka-flash-3 (the
  free-tier model) to reka-flash; reorder so reka-flash-3 stays default, reka-flash retained.
- test: align provider-models-config / provider-models-route / web-cookie-providers-new with
  diegosouzapw#4621 (reka-flash now in the Reka catalog) and diegosouzapw#4699 (the `kimi` API-key provider correctly
  falls through to DefaultExecutor instead of KimiWebExecutor)
- chore(quality): allowlist the COMPRESSION_GUIDE doc name in check-fabricated-docs
  (false-positive env-var match; docs/compression/COMPRESSION_GUIDE.md exists)

* fix(release-green): resolve release-PR full-CI reds for v3.8.34

Surfaced only on the release PR (these gates don't run on PR->release fast-gates):

- fix(quota): complete HTML-comment sanitization in opencodeOllamaUsage SSR reset-time
  parsing — strip any <!--...--> generically instead of the two literal React hydration
  markers, so no partial "<!--" can survive (CodeQL js/incomplete-multi-character-
  sanitization, HIGH, introduced by diegosouzapw#4642). Regression test added.
- test(codex): correct the Codex-fingerprint body key order assertion to match the
  canonical bodyFieldOrder (prompt_cache_key precedes include); diegosouzapw#4584 flipped the two
  and integration tests don't run on fast-gates so it never executed until the release PR.
- chore(quality): rebaseline inherited cycle drift surfaced by full CI —
  zizmorFindings 152->155 (+3 unpinned-uses in nightly-release-green.yml from diegosouzapw#4622,
  same @vn convention as ci.yml) and openapiCoverage.pct 38.4->37.8 (-0.6, contributor
  routes added faster than openapi docs). Release-finalize touches no prod routes.

* fix(release-green): complete CodeQL sanitization + rebaseline complexity drift

- fix(quota): handle unterminated HTML comments in opencodeOllamaUsage SSR reset-time
  parsing — the `(?:-->|$)` arm consumes a trailing "<!--" with no closing "-->", so no
  partial "<!--" can survive (CodeQL js/incomplete-multi-character-sanitization persisted
  with the plain <!--...--> form because an unclosed comment could still leave "<!--").
- chore(quality): rebaseline cyclomatic complexity 1915->1916 (+1) — inherited v3.8.34
  cycle drift (contributor feature branches); check:complexity does not run on PR->release
  fast-gates so it surfaced only on the release PR. Release-finalize adds 0 complexity
  (measured 1916 with/without the regex tweak). dead-code/cognitive/type-coverage/
  compression-budget/codeql ratchets all pass.

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <diego.souza@cdwasolutions.com.br>
Co-authored-by: Randi <55005611+rdself@users.noreply.github.com>
Co-authored-by: Hernan Javier Ardila Sanchez <hjasgr@gmail.com>
Co-authored-by: KooshaPari <42529354+KooshaPari@users.noreply.github.com>
Co-authored-by: Abhishek Divekar <adivekar@utexas.edu>
Co-authored-by: Rahul sharma <sharmaR0810@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <souzamiriamrodrigues790@gmail.com>
Co-authored-by: Ronald Estacion <DevEstacion@users.noreply.github.com>
Co-authored-by: Igor <60442260+BugsBag@users.noreply.github.com>
Co-authored-by: Oonishi <275808243+ponkcore@users.noreply.github.com>
Co-authored-by: Paijo <14921983+oyi77@users.noreply.github.com>
Co-authored-by: Jan Leon <Jan.gaschler@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants