Skip to content

Release v3.8.29 - #4126

Merged
diegosouzapw merged 121 commits into
mainfrom
release/v3.8.29
Jun 19, 2026
Merged

diegosouzapw merged 121 commits into
mainfrom
release/v3.8.29

Conversation

@diegosouzapw

@diegosouzapw diegosouzapw commented Jun 18, 2026 •

Copy link
Copy Markdown
Collaborator

[3.8.29] — 2026-06-19

✨ New Features

  • feat(cloud-agent): Cursor Cloud Agent via the official API-key REST API (no IDE-OAuth ban risk) — adds a cursor-cloud cloud agent that drives Cursor's Background / Cloud Agents through the official REST API (api.cursor.com) authenticated with a user or service-account API key — the safer, first-party alternative to re-using the Cursor IDE's OAuth session (the existing cursor provider, which carries a ban-risk warning). Implemented as a plain REST adapter mirroring the Devin/Jules agents (createTask/getStatus/sendMessage/listSources), so it does not pull in the @cursor/sdk package and its per-platform native binaries (Cursor's SDK is itself a thin wrapper over this REST API). Cursor's UPPERCASE status enums (CREATING/RUNNING/FINISHED/ERROR) are mapped explicitly to the shared CloudAgentStatus, and baseUrl is overridable per-credential. Credentials are stored encrypted via the existing cloud_agent_credentials table; no schema change. (#4227 — thanks @MRDGH2821)
  • feat(routing): OpenRouter-style auto/<category>:<tier> combos — auto-routing now understands suffixed combos that separate the category (what kind of route) from the tier (how to optimize): auto/coding:fast, auto/coding:cheap (alias :floor), auto/coding:free, auto/coding:pro, auto/coding:reliable, plus the new category roots auto/reasoning, auto/vision, auto/multimodal. The tier picks the scoring weights — :fast → ship-fast, :cheap/:floor → cost-saver, :reliable → a new reliability-first pack (circuit-breaker health + latency stability) — while :free/:pro filter the candidate pool by model tier (classifyTier: free-tier vs. premium models). The category filters the pool by capability (vision/multimodal → vision-capable models, reasoning → reasoning/thinking models). Any valid auto/<category>:<tier> resolves on demand; a curated set is advertised in /v1/models and the dashboard. Filtering is fail-open — if a constraint matches no connected models the full pool is used so routing never breaks. All composition lives in the new open-sse/services/autoCombo/suffixComposition.ts; the core combo scorer (combo.ts) is untouched. Second slice of [Feature] Enhanced auto/* combos #4235 (premium account-tier weighting is a later follow-up). (#4235 — thanks @MRDGH2821)
  • feat(routing): advertise the auto/cheap, auto/offline, auto/smart combos (catalog ↔ README sync) — the README lists auto/cheap (cheapest-per-token first), auto/offline (most quota/rate-limit headroom first) and auto/smart (quality-first + 10% exploration), and they already resolved at request time via parseAutoPrefix → createVirtualAutoCombo. But they were missing from AUTO_TEMPLATE_VARIANTS, so /v1/models and the dashboard combos list (which iterate that catalog) never showed them — the catalog drifted from the docs (visible in the issue's screenshots). Added the three entries so they're advertised everywhere alongside the other built-in auto/* combos. First slice of [Feature] Enhanced auto/* combos #4235 (OpenRouter-style auto/<category>:<tier> suffixes + new categories follow). (#4235 — thanks @MRDGH2821)
  • feat(cli): remote mode — drive a remote OmniRoute with scoped access tokens — a new CLI mode that connects to a remote OmniRoute instance using scoped access tokens, so a local CLI can drive a server you don't own a session on. (#4256)
  • feat(api): cost-telemetry parity — X-OmniRoute-* headers on every endpoint + a non-token cost engine — every endpoint now emits the X-OmniRoute-* cost/usage headers, backed by a cost engine that also prices non-token (media/request-based) usage. (#4247)
  • feat(api): register Kimi K2.7 Code models (kimi-k2.7-code + -highspeed) — the new Moonshot thinking-only coding models are registered (fixed sampling; temperature/top_p marked unsupported). (#4183)
  • feat(catalog): add kimi-k2.7-code to the kmca catalog + qwen-web models discovery — surfaces the new Kimi coding model in the kmca catalog and wires qwen-web into model discovery. (#4185)
  • feat(api): expand the zai provider catalog with GLM-5.2 / GLM-4.7 — adds the real GLM-5.2, GLM-4.7 and GLM-4.7-flash model ids to the Anthropic-direct zai provider. (#4201)
  • feat(api): no-thinking gateway model IDs (FCC port, Fase 8.1) — gateway model id variants that force thinking off, ported from free-claude-code. (#4145)
  • feat(sse): mid-stream continuation for truncated streams (FCC port, Task 4.4) — when a stream is cut short, OmniRoute can transparently continue it, ported from free-claude-code. (#4147)
  • feat(sse): per-provider sliding-window rate-limit fallback (FCC port, Fase 8.2) — a per-provider sliding-window rate limiter as a fallback path, ported from free-claude-code. (#4146)
  • feat(sse): transparent stream recovery (FCC port, Fase 4, opt-in) — opt-in transparent recovery of interrupted upstream streams, ported from free-claude-code. (#4131)
  • feat(search): free DuckDuckGo web search as a last-resort provider (FCC port, Fase 6) — adds a no-key DuckDuckGo web-search provider used as a last resort, ported from free-claude-code. (#4136)
  • feat(logging): credential-redaction safety net in the pino logger (FCC port, Fase 8.3) — a logger-level redaction pass that scrubs credentials from log output, ported from free-claude-code. (#4140)
  • feat(memory): opt-in Qdrant scalar int8 quantization (F4.4 Q1) — opt-in int8 scalar quantization for Qdrant-backed memory vectors. (#4187)
  • feat(memory): opt-in sqlite-vec int8 vector quantization (F4.4 Q2) — opt-in int8 quantization for the sqlite-vec memory backend. (#4190)
  • feat(deploy): keep optional deps on update (--include=optional) — the in-place update path now passes --include=optional so native/optional packages aren't dropped on update. (#4260)
  • feat(dashboard): unified visual identity — grid, primitives, tables, form controls (design phases 1-4) — a sweeping design pass aligning the dashboard with the site: grid wallpaper, button/card/input primitives, theme-aware tables and form controls. (#4122)
  • feat(dashboard): grid wallpaper on all standalone screens + fluid 4K layout — the identity grid now backs every standalone screen and the layout scales fluidly to 4K. (#4158)
  • feat(dashboard): make the identity grid visible + unify the focus ring on accent — design follow-up making the grid actually visible and standardizing focus rings on the accent color. (#4141)
  • feat(dashboard): import only free models + free-model list controls — the model-import page can import just the free models, with controls to manage the free-model list. (#4176 — thanks @felipesartori)
  • feat(dashboard): compact grid layout for no-auth provider accounts — a denser grid layout for provider accounts when auth is disabled. (#4137 — thanks @felipesartori)
  • feat(dashboard): derive media serviceKinds from the registries (surface MiniMax + the media catalog) — /media-providers/[kind] now derives its service kinds from the registries instead of a hand-maintained list, surfacing ~48 previously-invisible media providers (incl. MiniMax TTS/video/music). (#4212)
  • feat(traffic-inspector): live (in-flight) request filter (Gap 5) — the Traffic Inspector can filter to in-flight requests as they happen. (#4130)
  • feat(agent-bridge): maintenance & diagnostics dashboard controls — adds maintenance and diagnostics controls for the Agent Bridge to the dashboard. (#4127)
  • feat(mitm): TPROXY IP_TRANSPARENT native addon + conditional loader (Epic A) — a native IP_TRANSPARENT addon with a conditional loader, the foundation for TPROXY capture. (#4148)
  • feat(mitm): Fase 3 Epic A spike — TPROXY command builder — a transactional builder for the iptables/TPROXY command set. (#4139)
  • feat(mitm): TPROXY setup layer — transactional apply/revert (Epic A) — applies and reverts the TPROXY routing setup transactionally. (#4144)
  • feat(mitm): add setSocketMark to the TPROXY addon (anti-loop primitive) — exposes setSocketMark so OmniRoute's own egress can be marked and skipped (anti-loop). (#4160)
  • feat(mitm): TPROXY capture-mode listener + connectMarked (Epic A) — the capture-mode listener plus a marked-connect primitive. (#4169)
  • feat(mitm): dynamic per-SNI cert authority for TPROXY (TLS decrypt 1/N) — a per-SNI on-the-fly certificate authority, the first slice of TLS decrypt. (#4173)
  • feat(mitm): TLS-terminating capture for TPROXY (decrypt 2/N) — terminates TLS to capture decrypted traffic. (#4179)
  • feat(mitm): wire the TLS decrypt engine into TPROXY capture mode (decrypt 3/N) — connects the decrypt engine to the capture-mode pipeline. (#4200)
  • feat(mitm): TPROXY capture-mode manager (decrypt 4a/N) — a manager coordinating the TPROXY capture lifecycle. (#4208)
  • feat(mitm): local-only route + trust-store installer for TPROXY decrypt (4b/N) — a loopback-only management route plus a CA trust-store installer for the decrypt CA. (#4211)
  • feat(dashboard): TPROXY decrypt capture toggle in the Traffic Inspector (4c/N) — a UI toggle to enable/disable decrypted capture. (#4216)
  • feat(compression): replace the headroom tabular encoder with a vendored GCF — swaps the tabular encoder for a vendored GCF implementation. (#4167 — thanks @blackwell-systems)
  • feat(compression): live per-engine streaming via compression.step (F3.3) — streams per-engine compression progress through a compression.step event. (#4217)
  • feat(compression): show an engine node for single-engine runs in the studio — the Compression Studio now renders an engine node even when only one engine runs. (#4210)
  • feat(compression): expose the WaterfallInspector via a Canvas/Waterfall toggle — adds a Canvas/Waterfall view toggle that surfaces the WaterfallInspector. (#4238)
  • feat(compression): make mcpAccessibility config reachable via a settings sub-route — exposes the mcpAccessibility config under a dedicated settings sub-route. (#4237)
  • feat(compression): runnable A/B benchmark CLI (F2.4) — a CLI to run A/B compression benchmarks. (#4220)
  • feat(compression): add a transcript loader to the replay harness — the replay harness can now load real transcripts. (#4246)
  • feat(compression): wire MCP tool-cardinality reduction (F4.3, opt-in) — opt-in reduction of MCP tool-set cardinality to shrink prompts. (#4221)
  • feat(compression): wire RTK comment-stripping config + honor preserveDocstrings — RTK comment-stripping is now configurable and honors a preserveDocstrings flag. (#4242)
  • feat(compression): honor the per-filter RTK deduplicate flag — RTK filters now respect a per-filter deduplicate flag. (#4231)
  • feat(compression): honor the registry enabled flag in the stacked loop — the stacked compression loop now skips engines disabled in the registry. (#4244)
  • feat(compression): persist RTK grouping config (unlock R5 enableGrouping) — persists the RTK grouping configuration, unlocking the R5 enableGrouping rule. (#4207)
  • feat(compression): wire ultra's modelPath/slmFallbackToAggressive to the LLMLingua SLM tier — connects the ultra tier's small-language-model knobs to the LLMLingua SLM path. (#4257)
  • feat(quality): Onda 2 mutation-gate tooling — radiography classifier (T1) + mutationScore ratchet (T3) — new mutation-testing tooling: a survivor-radiography classifier and a mutationScore ratchet. (#4234)
  • feat(ci): wire the F2.4 compression budget-gate ratchet — adds a CI ratchet that gates compression budget regressions. (#4232)

🐛 Fixed

  • fix(providers): qwen-web model discovery now lists the live catalog instead of nothing — the qwen-web cookie provider had no entry in PROVIDER_MODELS_CONFIG, so its model-discovery page returned an empty/stale local catalog (the OAuth fallback at the top of the route only fires for provider === "qwen", leaving qwen-web to fall through to the no-config branch). Added a qwen-web entry that fetches the public https://chat.qwen.ai/api/v2/models endpoint (no auth header) and parses the { data: { data: [{ id, name, owned_by }] } } shape (with a flatter { data: [] } fallback). This is Problem deps: bump eslint from 9.39.2 to 10.0.0 in the development group #3 of fix(qwen-web): validator false-positive + empty stream with valid token #3931 (diagnosed by @thezukiru); Problem [WIP] Add FastAPI OpenAI-compatible LLM gateway with routing #1 — validator bare-token false-positive — shipped earlier in fix(qwen-web): cookie validation false-positive - check response body for user object #3958, and Problem build(deps): bump actions/github-script from 7 to 8 #2 — empty stream from Qwen WAF bot-detection on the streaming endpoint — remains a separate upstream/stealth concern. (#3931 — thanks @thezukiru)
  • fix(providers): ZenMux model discovery now lists the live catalog (incl. the free models) instead of the stale 9-entry hardcoded list — adding a ZenMux key validated fine, but the connection then showed API unavailable — using local catalog and was missing the free models ZenMux advertises (z-ai/glm-5.2-free, moonshotai/kimi-k2.7-code-free). Root cause: zenmux carries a correct modelsUrl in the registry, but — like llm7/byteplus before [BUG] LLM7 GET /models does not work #3976 — it was not classified by any live-fetch branch of the model-import route (not openai-compatible-*, not self-hosted, not in NAMED_OPENAI_STYLE_PROVIDERS), so the route never probed the upstream /models and fell through to the registry's hardcoded models[]. Added zenmux to NAMED_OPENAI_STYLE_PROVIDERS, so the route probes https://zenmux.ai/api/v1/models (the /chat/completions-stripped <baseUrl>/models candidate) and serves the live list, falling back to the local catalog only when the upstream fetch fails — import never breaks. (#4202 — thanks @mikmaneggahommie)
  • fix(providers): Vercel AI Gateway "import models" now loads the live catalog instead of nothing — adding a Vercel AI Gateway key worked, but clicking import on the models page loaded nothing usable (manually adding the same models worked). Same class as [BUG] Zenmux dont work #4202 (zenmux) / [BUG] LLM7 GET /models does not work #3976 (llm7/byteplus): vercel-ai-gateway carries a real baseUrl (https://ai-gateway.vercel.sh/v1/chat/completions, format openai) in the registry, but was not classified by any live-fetch branch of the model-import route (not openai-compatible-*, not self-hosted, not in NAMED_OPENAI_STYLE_PROVIDERS), so the route never probed the upstream /models and fell through to the registry's tiny 5-entry hardcoded models[]. Added vercel-ai-gateway to NAMED_OPENAI_STYLE_PROVIDERS, so the route probes https://ai-gateway.vercel.sh/v1/models (the /chat/completions-stripped <baseUrl>/models candidate) and serves the live list, falling back to the local catalog only when the upstream fetch fails — import never breaks. (#4249 — thanks @FerLuisxd)
  • fix(sse): clear error when the request queue drops a job (no more fake-upstream "This job timed out after Nms") — under concurrent load, requests that exceed the per-connection rate-limit queue budget (resilienceSettings.requestQueue.maxWaitMs) were dropped by Bottleneck with its raw This job timed out after <maxWaitMs> ms. message. That string is indistinguishable from an upstream gateway timeout, so the 502 body and call-log last_error looked like a provider outage across unrelated providers (TI:0|TO:0) — an operator spent ~3h misdiagnosing local queue saturation as upstream failures. withRateLimit now rewrites that specific Bottleneck error into a clear, OmniRoute-owned message that names the knob (requestQueue.maxWaitMs, tunable in Settings → Resilience), explicitly disclaims an upstream timeout, preserves the original as cause, and tags code: "RATE_LIMIT_QUEUE_TIMEOUT". Behavior is unchanged — the job is still dropped so combo falls back to the next target. (#4165 — thanks @KooshaPari)
  • fix(api): advertise the built-in auto/* combos in /v1/models — OmniRoute ships a zero-setup auto/* catalog (auto/best-coding, auto/pro-reasoning, …, 16 variants) that the dashboard advertises and that resolve on demand, but the /v1/models listing only emitted persisted DB combos + provider models. Clients that build their model picker from /v1/models (e.g. Hermes Agent) never saw any auto/* option. The catalog now emits every AUTO_TEMPLATE_VARIANTS id (as owned_by: "combo") at the top of the list, deduped against persisted combos. (Showing each auto/*'s dynamically-selected members is a separate enhancement.) (#4164 — thanks @MRDGH2821)
  • fix(sse): restore MCP / third-party tool names on the native Claude path (MCP dispatch broken in Claude Code) — since 3.8.27, every MCP tool call routed through OmniRoute to a native Claude OAuth provider failed client-side with Error: No such tool available: <PascalCaseName>: tool schemas arrived fine but the streamed tool_use.name reached Claude Code in its cloaked form (e.g. McpN8nMcpSearchWorkflows instead of the registered mcp__n8n-mcp__search_workflows). The native-Claude tool-name cloak stashes its per-request alias→original map as a non-enumerable _toolNameMap on the request body; the request-inspector capture added in 3.8.27 rebuilds the captured body from its serialized form (JSON.parse(JSON.stringify(...))), which drops non-enumerable properties, so finalBody._toolNameMap was empty and the response-side un-cloak silently fell back to the static built-in map — never restoring dynamic MCP / snake_case names. Built-in tools (Bash/Read/…) were unaffected (static map); cross-format paths were unaffected (they attach the map enumerably). The provider-request capture now re-attaches the per-request map (kept non-enumerable, so it still never re-serializes upstream) when the captured copy lost it, restoring MCP tool dispatch. (#4091 — thanks @pedrotecinf, @NakHalal)
  • fix(dashboard): Logs auto-refresh self-heals in embedded/proxied hosts that pin or mis-fire visibility — a follow-up to [BUG] request log still do not auto refresh #4054: the Request Logger still froze auto-refresh on some hosts (reported on 3.8.28 Docker, works on 3.8.24). [BUG] request log still do not auto refresh #4054 made the initial visibility fail-open, but the pause is event-driven — a host that fires a one-shot visibilitychange → hidden and then keeps reporting "hidden" (or recovers without firing the event again) left the cached visibility flag stuck false, so the interval ticked but never polled (only the manual Refresh button worked). The poll tick now also re-checks the live document.visibilityState, and a window focus listener re-arms polling (a focused window is a reliable signal the page is actively viewed). A genuinely backgrounded browser tab still pauses (it reports "hidden" and never receives focus), preserving the perf(logs): fix browser freeze and network saturation on /dashboard/logs #3109 network-saturation optimization. (#4133 — thanks @tjengbudi)
  • fix(capabilities): unify vision model-id detection into one shared source — three code paths kept independent, drifting vision-model lists, so the same model id could get up to three different verdicts. Two concrete bugs: lite compression's gate was missing pixtral / llava / qwen-vl / glm-4v / kimi-vl / mistral-medium-3, so it stripped images for those real vision models and blinded them (same class as fix(sse): route image requests only to confirmed-vision combo targets #4071 / [BUG] Nvidia NIM via Omniroute fails to process image inputs #4012); and the /v1/models list was too broad, flagging text models (gemma, bare kimi like kimi-k2) as vision. All three (modelCapabilities routing fallback, /v1/models listing, lite image-strip gate) now delegate to a single conservative source src/shared/constants/visionModels.ts, which also restores glm-4v / gemini-3 coverage and keeps the is mini max 3 blind on opencode provider #3328 MiniMax M3 carve-out. (#4072 — thanks @diego-anselmo)
  • fix(sse): surface mid-stream Gemini errors instead of returning a truncated 200 — when an upstream Gemini SSE stream emitted some partial content and then a JSON error object ({"error":{"code":503,"message":"…high demand…","status":"UNAVAILABLE"}}) instead of a candidates payload, OmniRoute silently dropped it: the gemini→openai translator's no-candidate branch only handled promptFeedback (content-filter) and returned null for anything else, so the stream simply ended and the client got HTTP 200 with a truncated body and finish_reason: "stop" — masking the failure and skipping combo fallback. geminiToOpenAIResponse now detects an error object (optionally wrapped in response), records it as state.upstreamError (preserving the real status — 503/UNAVAILABLE, or 429 for RESOURCE_EXHAUSTED), and lets stream.ts error the stream out through the existing onFailure/buildErrorBody/controller.error path — the same mechanism the openai-responses translator already uses. (#4177 — thanks @hartmark)
  • fix(capabilities): resolve models.dev-synced vision metadata for Mistral -latest aliases — root cause behind the fix(sse): route image requests only to confirmed-vision combo targets #4071 heuristic: getResolvedModelCapabilities("mistral/pixtral-12b-latest").supportsVision resolved null (vision came only from the fix(sse): route image requests only to confirmed-vision combo targets #4071 model-id heuristic, with attachment still null) even though models.dev exposes the model as multimodal. Confirmed against the live models.dev API: it catalogs Pixtral 12B under the short id pixtral-12b (with attachment: true, modalities.input: ["text","image"]), while requests use the Mistral API alias pixtral-12b-latest. The synced lookup tried the exact / raw / static-spec-canonical ids — all of which miss the short form — so it fell through to the heuristic. getSyncedCapabilityForResolved now adds a last-resort fallback that retries with a trailing -latest stripped, so synced metadata (attachment / image modalities) wins for these aliases; models whose -latest id is stored verbatim (e.g. pixtral-large-latest) keep resolving directly. Note: the models.dev sync is currently manual-only (Settings → models.dev) with no scheduled refresh, so a fresh instance still relies on the fix(sse): route image requests only to confirmed-vision combo targets #4071 heuristic until that sync runs — a periodic-refresh cadence is left as a separate follow-up. (#4073 — thanks @diego-anselmo)
  • fix(sse): map Xiaomi MiMo reasoning control to its native thinking:{type} shape — MiMo (api.xiaomimimo.com) controls chain-of-thought only via top-level thinking:{type:"enabled"|"disabled"} and does not understand OpenAI's reasoning_effort/reasoning, while its request validator is strict (400 Param Incorrect). OmniRoute's OpenAI path carried reasoning intent as reasoning_effort, and the claude→openai translator can leave a Claude-shaped thinking:{type, budget_tokens} — so the client's on/off choice was silently dropped and budget_tokens/reasoning_effort rode along as extra params the validator can reject. New open-sse/services/mimoThinking.ts::normalizeMimoThinking (wired in chatCore for provider==="xiaomi-mimo") reduces any thinking object to just {type} (disabled stays; enabled/adaptive/other → enabled) and drops reasoning_effort/reasoning. It deliberately does not synthesize thinking from a bare reasoning_effort — mimo-v2-omni is non-thinking, so that could turn a silently-ignored param into a hard error. (#4224)
  • fix(capabilities): Xiaomi MiMo *-pro chat models are text-only (no vision) — only mimo-v2.5 and mimo-v2-omni accept images per Xiaomi's docs; mimo-v2.5-pro/mimo-v2-pro are text-only, but modelSpecs marked them vision-capable and models.dev mislabels them (hermes-agent#18884). Since resolveVisionCapability lets a synced attachment:true win first, an image request could be routed to a blind model (the fix(sse): route image requests only to confirmed-vision combo targets #4071 failure mode). Corrected the specs and added a hard override in resolveVisionCapability (checked before the synced branch, anchored so mimo-v2.5-pro never matches the multimodal mimo-v2.5) that beats the wrong synced attachment. Also registered the missing native mimo-v2-pro chat model and the missing mimo-v2-tts speech model. (#4224)
  • fix(sse): Claude Opus 4.7+/Fable 5 use adaptive thinking only (no more manual-budget 400s) — Opus 4.7 and later (Opus 4.7/4.8, Fable 5) removed manual extended thinking: thinking.type:"enabled" or any thinking.budget_tokens now returns 400 ("Any request that tries to set a fixed thinking budget gets a 400" — Anthropic migration guide). Reasoning is adaptive-only, steered by output_config.effort. OmniRoute's OpenAI→Claude translator mapped reasoning_effort low/medium/high to a manual thinking:{type:"enabled", budget_tokens}, so those requests hard-400'd on the most-used provider (and a Claude-native passthrough client sending the legacy shape did too). A new adaptiveThinkingOnly model flag now drives two fixes: the translator maps reasoning_effort of every level to {type:"adaptive"} + output_config.effort (preserving the requested level, never a budget) for these models, and a normalizeClaudeAdaptiveThinking catch-all at the existing post-translation thinking-normalization chokepoint collapses any residual manual thinking (passthrough legacy shape, per-model defaults) to {type:"adaptive"}, keyed on the resolved upstream model so it covers every routing mode. Pre-4.7 models (Opus 4.6/4.5, Sonnet, Haiku) keep manual budgets unchanged. (#4230)
  • fix(providers): strip non-default temperature/top_p/top_k for Claude Opus 4.7+/Fable 5 (fixed sampling → no 400) — Opus 4.7 and later reject non-default temperature/top_p/top_k with a 400 (sampling is fixed; reasoning moved to output_config.effort). The translator forwarded client-supplied temperature/top_p unconditionally and the Claude registry models carried no unsupportedParams, so a plain OpenAI-format request with temperature: 0.7 to claude-opus-4-8 hard-400'd. Added unsupportedParams: ["temperature","top_p","top_k"] to the Opus 4.7+/Fable 5 ids in both the claude (dashed claude-opus-4-8) and anthropic (dotted claude-opus-4.7) registries, so they're stripped at the existing getUnsupportedParams dispatch chokepoint. Pre-4.7 Claude models still accept sampling params. (#4230)
  • fix(providers): conditionally strip temperature/top_p for GPT-5 reasoning on the openai Chat Completions path (no 400 when an effort is active) — GPT-5 reasoning models reject non-default temperature/top_p with a 400 whenever a reasoning effort is active, yet accept them again under reasoning_effort:"none" (the GPT-5.1+ default, i.e. non-reasoning mode). On the openai provider only o3 carried REASONING_UNSUPPORTED; gpt-5.5/gpt-5.4/gpt-5.4-mini/gpt-5.4-nano carried no sampling guard, so a temperature + active-effort request hard-400'd. A static unsupportedParams list can't express the none-mode carve-out (it would over-strip the legitimate case), so the new gpt5SamplingGuard drops temperature/top_p only when the resolved effort is active — wired at the existing getUnsupportedParams chokepoint and scoped to the openai Chat Completions surface (the codex Responses path is already covered by the CodexExecutor allowlist; other providers are untouched). (#4245)
  • fix(codex): stop silently dropping GPT-5 output verbosity (verbosity / text.verbosity) — the GPT-5 series added an output-verbosity control: verbosity (low/medium/high) on Chat Completions, nested as text.verbosity on the Responses API. The CodexExecutor gates translated requests through an allowlist that had no text entry, so for the codex provider the hint was dropped before reaching upstream (the openai Chat path already forwarded it). normalizeCodexVerbosity now folds whichever shape arrived into a single validated text:{verbosity} before the allowlist (which now permits text), and the OpenAI Chat↔Responses request translators map verbosity across formats so the hint survives a format crossing for non-codex Responses backends too. Invalid/absent verbosity collapses to no text (status quo). (#4245)
  • fix(sse): map reasoning_effort to DeepSeek V4's native {high, max} vocabulary — DeepSeek V4 only understands high/max reasoning levels, so other reasoning_effort values are mapped onto its native vocabulary instead of being rejected. (#4219)
  • fix(glm): default max_tokens and an extended timeout for GLM-5.2+ thinking — GLM-5.2+ thinking responses are slow and need headroom, so OmniRoute now sets a sensible default max_tokens and a longer timeout for them. (#4255 — thanks @dhaern)
  • fix(antigravity): default includeThoughts for modern Gemini models — modern Gemini models on the Antigravity path now default to including thoughts so reasoning isn't silently dropped. (#4180 — thanks @dhaern)
  • fix(provider-registry): add correct contextLength to [provider removed at its operator's request] models — fills in accurate context-window sizes for [provider removed at its operator's request]'s models. (#4184 — thanks @herjarsa)
  • fix(models): expose combo model token limits — /v1/models now reports token limits for combo models. (#4189 — thanks @megamen32)
  • fix(combo): keep the passthrough quota fallback scoped — prevents the passthrough quota fallback from leaking across unrelated targets. (#4194 — thanks @Svetznaniy33)
  • fix(combo): opt proactive-fallback compression into the TV1 bail-out (no silent target drop) — proactive-fallback compression now participates in the TV1 bail-out so a target is never silently dropped. (#4228)
  • fix(compression): show engine preview output — the Compression Studio preview now renders the engine's output. (#4128 — thanks @megamen32)
  • fix(compression): harden engines against I/O failures and misconfig (F5.3) — compression engines degrade gracefully on I/O errors and bad configuration instead of throwing. (#4198)
  • fix(compression): harden RTK raw-output redaction + ReDoS guard for custom filters (F5.3) — broadens RTK raw-output redaction and adds a ReDoS guard for user-supplied filter patterns. (#4203)
  • fix(compression): bound mcpAccessibility maxTextChars on the live read path — the live read path now clamps maxTextChars so a small value can't make tools disappear. (#4206)
  • fix(dashboard): data tables paint an opaque surface so the grid doesn't bleed through — data tables now render on an opaque surface, fixing the grid wallpaper showing through. (#4233)
  • fix(dashboard): make the provider card hover visible (was ~1% opacity) — the provider-card hover state was effectively invisible; it now has a visible surface. (#4214)
  • fix(vscode): sanitize implicit editor context — redacts sensitive filenames/keywords from the implicit VS Code editor context before it's sent upstream. (#4124 — thanks @zhiru)
  • fix(build): raise the Node heap for the local next build to stop OOM/stall — bumps the build-time heap so the local production build no longer OOMs or stalls. (#4171)
  • fix(mitm): TPROXY OUTPUT-based recipe for local traffic (validated e2e on VPS) — switches the TPROXY rules to an OUTPUT-chain recipe so locally-originated traffic is captured; validated end-to-end on the VPS. (#4156)
  • fix(mitm): forward anti-loop — put the bypass-marked socket on the Agent (decrypt 4d) — places the bypass-marked socket on the HTTP Agent so OmniRoute's own forwarded traffic never re-enters the capture loop; VPS-validated. (#4229)
  • fix(free-tiers): retire dead-tier hasFree, round the headline to ~1.6B, regenerate the per-provider table — drops dead free tiers from the headline math and regenerates the per-provider free-tier table. (#4142)
  • fix(free-tiers): retire 4 re-verified-dead free tiers, flag iflytek/sparkdesk ToS, clarify monsterapi one-time — removes four confirmed-dead free tiers and annotates ToS/one-time caveats. (#4152)

🧪 Tests

  • test(sse): guard the Antigravity _toolNameMap cloak map through the request-capture round-trip — follow-up to v3.8.27: MCP tool dispatch broken in Claude Code — tool schemas appear but every call returns "No such tool available" (works on 3.8.24) #4091: the generic capture fix in createPreparedRequestLogger().body() (fix(sse): restore MCP/third-party tool names on native Claude path (#4091) #4153) re-attaches the non-enumerable _toolNameMap that the request-inspector drops when it rebuilds the upstream body via JSON.parse(JSON.stringify(...)), but the only regression test covered the native-Claude OAuth cloak (PascalCase aliases). The Antigravity cloak differs — cloakAntigravityToolPayload suffixes custom tools with _ide (workspace_read → workspace_read_ide), leaves native tools untouched, and returns the reverse map separately — so a refactor of providerRequestLogging.ts or the executor could silently re-break Antigravity tool dispatch without tripping the Claude test. Adds a dedicated regression test driving the real cloakAntigravityToolPayload through the capture round-trip and asserting the _ide reverse map survives, stays non-enumerable (never re-serializes upstream), and that all-native traffic produces no spurious map (verified failing with the fix(sse): restore MCP/third-party tool names on native Claude path (#4091) #4153 re-attach removed). No production change. (#4181 — thanks @hertznsk)
  • test(chatcore): dedicated unit tests for 6 leaves + wire into stryker mutate (QG v2 Fase 9 T5 Fase 3) — adds focused unit tests for 6 chatCore leaf helpers and enrolls them in mutation testing. (#4218)
  • test(chatcore): telemetry / memory-skills / semantic-cache tests + wire 2 into stryker (QG v2 Fase 9 T5 Fase 3) — new tests for the telemetry, memory-skills and semantic-cache leaves, two of which are added to the mutation set. (#4222)
  • test+ci(chatcore): semanticCache HIT-path fixture (15/15 mutate) + 350min budget headroom — closes the semantic-cache HIT path to a full 15/15 mutation score and gives the nightly auth/accountFallback batches more budget headroom. (#4225)
  • test(compression): close F5.1 coverage gaps (replay reducer, live accumulator, StatusDot) — fills the remaining F5.1 compression coverage gaps. (#4192)
  • test(db,sse): de-flake db-backup + chatcore streaming timing assertions — stabilizes two timing-sensitive tests (fire-and-forget backup completion + a streaming race). (#4132)
  • test: align stale integration tests surfaced post-v3.8.28 on main — realigns integration tests that drifted after the v3.8.28 merge. (#4129)

📝 Maintenance

  • refactor(sse): split chatCore.ts pure helpers into chatCore/ modules (−561 LOC) — extracts pure helpers out of the chatCore god-file into dedicated modules (Onda 3). (#4159)
  • refactor(chatcore): extract passthrough/header/telemetry helpers (QG v2 Fase 9 T5 C2-C3-C5) — further chatCore decomposition. (#4188)
  • refactor(chatcore): extract combo/proxy context cache + semaphore helpers (QG v2 Fase 9 T5 C6-C7) — continues the chatCore split. (#4193)
  • refactor(combo): god-file split pilot — types + validateQuality + predicates (QG v2 Fase 9 T5 D1-D3) — first slice of the combo.ts decomposition. (#4162)
  • refactor(combo): god-file split part 2 — shadow + sorters + structure (QG v2 Fase 9 T5 D4-D6) — continues the combo.ts split. (#4175)
  • refactor(combo): god-file split part 3 — auto strategy (QG v2 Fase 9 T5 D8) — extracts the auto strategy from combo.ts. (#4186)
  • refactor(combo): extract round-robin sticky state to combo/rrState.ts (D7a) — moves round-robin sticky state into its own module. (#4196)
  • refactor(combo): extract the reset-aware quota block to combo/quotaStrategies.ts (D7b) — moves the reset-aware quota strategies into their own module. (#4204)
  • refactor(compression): remove vestigial SLM seam + dead deprecated alias — drops dead compression code. (#4253)
  • chore(compression): remove vestigial reconstructCcr/SessionDedup round-trip helpers — removes unused round-trip helpers. (#4226)
  • chore(compression): remove dead exports + fix stale llmlingua docs — prunes dead exports and corrects stale LLMLingua docs. (#4223)
  • chore(build): build + ship the TPROXY native addon in the standalone (prebuilds 4e) — bundles the native TPROXY addon prebuilds into the standalone build. (#4236)
  • chore(ci): add quota + 6 covered chatCore leaves to stryker mutate (QG v2 Fase 9 T5 Fase 3 follow-up) — enrolls more covered leaves into mutation testing. (#4209)
  • chore(ci): re-add 8 combo split leaves to stryker mutate + expand nightly batch-matrix 3→5 (QG v2 Fase 9 T5 Fase 3) — restores mutation coverage for the split combo leaves and widens the nightly matrix. (#4205)
  • chore(quality): close v3.8.28 cycle gate drift (re-baseline + nightly-mutation scope) — reconciles quality-gate baselines after the v3.8.28 cycle. (#4135)
  • ci(mutation): split nightly into 3 parallel batches to fit the 180min budget (QG v2 Fase 9 T0) — parallelizes the nightly mutation run. (#4150)
  • ci(mutation): restore cold-seed timeout headroom (a/b lost in test+ci(chatcore): semanticCache HIT fixture (15/15 mutate) + 350min budget headroom for auth/accountFallback batches #4225 squash) + extend to c/d/g/h — restores and extends per-batch cold-seed timeouts. (#4258)
  • ci(docs): harden the fabricated-docs checker + enforce --strict (QG v2 Fase 9 T9) — tightens the anti-hallucination docs checker. (#4149)
  • ci: derive the oasdiff base-ref from the package version + flag the mutation-toolchain regression — fixes the OpenAPI-diff base-ref and surfaces a mutation-toolchain regression. (#4134)
  • docs(ci): correct the mutation-gate note (no regression — stryker -c is --concurrency); record Task 12 GO — corrects a misread of the stryker flag and records the spike GO. (#4138)
  • docs(api): document the /api/v1/ws chat WebSocket endpoint in openapi.yaml — adds the WebSocket chat endpoint to the OpenAPI spec. (#4215)
  • docs(readme): expand Acknowledgments into a themed, star-counted credits hall — reworks the README acknowledgments section. (#4195)
  • style(dashboard): shrink the identity grid cell 46px → 32px (~30% smaller) — tightens the identity grid density. (#4143)

🔧 Dependencies

  • deps: bump the production group with 5 updates — routine production-dependency bumps. (#4121)
  • chore(deps): bump github/codeql-action from 3 to 4 — CI action update. (#4120)
  • chore(deps): bump actions/setup-python from 5 to 6 — CI action update. (#4119)

🙌 Contributors

Thanks to everyone whose work landed in v3.8.29:

Contributor PRs / Issues
@MRDGH2821 #4227 (Cursor Cloud Agent), #4235 (auto/<category>:<tier> combos), #4164 (auto/* in /v1/models)
@thezukiru #3931 (qwen-web discovery)
@mikmaneggahommie #4202 (ZenMux discovery)
@FerLuisxd #4249 (Vercel AI Gateway import)
@KooshaPari #4165 (queue-drop error clarity)
@pedrotecinf / @NakHalal #4091 (MCP tool-name restore)
@tjengbudi #4133 (logs auto-refresh self-heal)
@diego-anselmo #4072, #4073 (vision capability)
@hartmark #4177 (mid-stream Gemini errors)
@hertznsk #4181 (Antigravity tool-map test)
@felipesartori #4176, #4137 (dashboard free-models + grid)
@blackwell-systems #4167 (vendored GCF encoder)
@dhaern #4180 (Antigravity includeThoughts), #4255 (GLM-5.2+ timeout)
@herjarsa #4184 ([provider removed at its operator's request] contextLength)
@megamen32 #4189 (combo token limits), #4128 (compression preview)
@Svetznaniy33 #4194 (scoped quota fallback)
@zhiru #4124 (VS Code context sanitizer)
@diegosouzapw maintainer

Quality Gate (release prep, run locally on release/v3.8.29)

  • lint: 0 errors (3816 pre-existing warnings)
  • typecheck:core: pass
  • check:cycles: pass
  • check:docs-all: pass (incl. env-doc-sync, fabricated-docs --strict, i18n 41 mirrors)
  • test:unit: pass (exit 0)
  • test:vitest: 188/188 pass
  • npm audit (prod, high+): 0 high/critical (2 moderate dompurify transitive via monaco-editor — breaking upgrade, deferred)

Range: v3.8.28..release/v3.8.29 — 115 commits, all covered (119 changelog bullets).

@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!

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@github-actions

github-actions Bot commented Jun 18, 2026 •

Copy link
Copy Markdown
Contributor

CI Coverage Report

  • Coverage job: skipped
  • PR test policy: success

Coverage artifact was not available for this run.

dependabot Bot and others added 15 commits June 17, 2026 21:36
Integrated into release/v3.8.29 with review fixes (narrowed text-scan redaction + documented OMNIROUTE_VSCODE_SANITIZE_CONTEXT + regression tests). Co-authored-by: diegosouzapw
)

Two integration tests were red on `main` after the v3.8.28 release merged.
Integration tests do not gate PR->release, so these only surfaced on
push->main once the cycle's changes landed:

- v1-contracts-behavior count_tokens expected 3 (the old ceil(chars/4)
  heuristic). #4087 switched the estimator to real tiktoken (countTextTokens):
  "abcd" => 1, "12345678" => 3, total 4. Assertion updated to the verified
  tiktoken total.

- combo-routing-e2e round-robin tests assumed one-request-per-target rotation,
  but stickyRoundRobinLimit defaults to 3 and sticky batching has applied to
  combos since v3.8.26 (#3846). Both tests now drive enough requests to observe
  the batched rotation: round-robin cycles openai x3 -> claude x3 -> gemini x3;
  the strategy-update test proves round-robin took over by reaching claude on
  the 4th post-update request (a target priority would never select).

Test-only; no production behavior change. Verified locally: both files green.
…-toolchain regression (#4134)

Quality-Gate v2 Fase 9 maintenance (two findings from the Onda 0-1 follow-up):

- check-openapi-breaking.mjs: DEFAULT_BASE_REF was hard-coded "origin/release/
  v3.8.27" and drifted into the v3.8.29 cycle — LOCAL runs of the oasdiff
  breaking-change gate diffed the PR spec against the wrong release (CI passes
  BASE_REF=${{ github.base_ref }} and was unaffected). Derive it from
  package.json via releaseBranchForVersion() so it tracks every release bump
  automatically; literal fallback bumped to v3.8.29. +3 TDD cases.

- docs/ops/MUTATION_GATE_STRYKER_REGRESSION.md: NEW toolchain regression —
  `npx stryker run` now fails at config validation under Stryker 9.6.1 + ajv
  8.18.0 with a false "concurrency must match pattern" (reproduced with the
  UNMODIFIED stryker.conf.json, and with concurrency removed). The project
  config is valid — a standalone ajv 8.18.0 (Stryker's own dep) accepts it — so
  it's an OptionsValidator regression, not our config. This is NOT a re-opening
  of the Task 12 spike (perTest/killedBy was settled GO in v3.8.27; the nightly
  ran as recently as v3.8.28, timing out on budget). The nightly now can't even
  start; clearing this (a dependency pin needing a non-shared reinstall) is the
  prerequisite to producing scores again. Doc records evidence + fix direction.
…ns (#4132)

Two unit tests flaked under CI parallelism (reproduced locally under CPU
contention, both RED → GREEN after the fix):

- db-backup-extended "creates manual backups": waited only for the backup
  FILE to exist, but backupDbFile() fires db.backup() fire-and-forget and
  better-sqlite3 creates the destination at copy START → listDbBackups()
  read a partial backup as connectionCount 0 != 12. Now waits for the real
  completion condition (backup contains the seeded rows); 30s ceiling only
  bounds the failure case, green path returns sub-second.

- chatcore-translation-paths "streaming without buffering": raced the
  invocation against a fixed 1000ms budget; a starved event loop made the
  legitimate (non-buffering) early return exceed 1s -> false "blocked".
  Widened the ceiling to 10s (matches the file's existing waitFor pattern);
  the buffering-regression detection is unchanged.

Repro: concurrent copies under CPU burners -> both RED; after fix both
GREEN at realistic (8+8 copies) and extreme (12+12 copies + 14 burners)
contention. Test-only change; no production code touched.

(The pre-commit prettier --write also normalized one pre-existing
non-conforming region in chatcore-translation-paths.test.ts.)
…-concurrency); record Task 12 GO (#4138)

The MUTATION_GATE_STRYKER_REGRESSION.md note shipped in #4134 was WRONG: there is
no Stryker 9.6.1 OptionsValidator regression. The false "concurrency must match
pattern" failure was operator error — `stryker -c <file>` sets --concurrency, not
the config file (which is the positional arg), so concurrency became the string
"stryker.conf.json". `npx stryker run` (auto-discovery) validates and runs fine:
it instruments 15488 mutants across the 8 modules.

Renamed -> MUTATION_GATE_SPIKE_VERDICT.md and rewritten with:
- the corrected record + the `-c` CLI gotcha;
- the real Task 12 per-test spike verdict (GO, Plan A): a scoped run on
  open-sse/utils/error.ts killed 86/422 mutants, ALL 86 with a populated
  `killedBy` resolving to a test file -> per-test attribution works (per-file
  granularity, as expected for the tap-runner). Onda 2 can use killedBy directly.
- the standing Onda-2 blocker is budget (god-files), not tooling.
…-mutation scope) (#4135)

* chore(quality): re-baseline v3.8.28 cycle drift (eslint/openapi/i18n)

The post-release push->main Quality Ratchet (run 27725117464) failed on 3
metrics that drifted during the v3.8.28 cycle from legitimate feature merges:
eslintWarnings 3769->3779, openapiCoverage.pct 38.3->37.6, i18nUiCoverage.pct
80.1->79.1. Reproduced locally on release/v3.8.29 (9f14c12) — identical to CI.

None is hand-cleanable without gaming or unavailable infra:
- eslint +10: no-explicit-any is warn-level and allowed in tests (the drift is
  test `any`), plus 4 react-hooks/exhaustive-deps in RequestLoggerV2.tsx (a
  refresh-sensitive component — touching hook deps without UI tests is risky).
- openapi -0.7: the drop is from new INTERNAL routes (/api/tools/agent-bridge/*,
  LOCAL_ONLY) — documenting them in the public spec would game the metric.
- i18n -1.0: 37/41 locales need ~3000 translations via `npm run i18n:run`, which
  requires OMNIROUTE_TRANSLATION_API_KEY (not available locally).

Re-baselined to the real measured values per the documented v3.8.26 precedent
(_eslint_rebaseline_2026_06_16_v3826_forward_merge). Tighten at cycle end:
eslint/openapi via --require-tighten; i18n via i18n:run with creds.

* ci(mutation): scope nightly to 6 modules to fit the 180min budget

The full 8-module Stryker run timed out at the 180min nightly cap (run
27705123780: 16:47:33 -> 19:47:48 = exactly 180min; the prior 120min scheduled
run also timed out). #4078's DATA_DIR isolation made concurrency=4 safe but not
sufficient: the tap-runner re-spawns a node process per test file per mutant, so
spawn cost dominates and the two god-files chatCore.ts (5874 LOC) + combo.ts
(5282 LOC) — ~2/3 of the ~15k mutants — do not fit.

Removed both god-files from stryker.conf.json `mutate`. The 6 smaller modules fit
the budget and produce real mutation scores now; the god-files regain coverage
after the Onda 3 split into smaller units. Updated the nightly job name/comments
(8->6 modules). Removing entries from `mutate` does not affect the dry-run
baseline (it runs tap.testFiles, unchanged), so the all-green baseline is preserved.
…4137)

Integrated into release/v3.8.29 (moved component test into tests/unit/ui/; check:test-discovery green). Co-authored-by: diegosouzapw
… port, Fase 6) (#4136)

Free DuckDuckGo web search as last-resort provider (FCC port, Fase 6). Integrado em release/v3.8.29: conflito de file-size-baseline.json resolvido (união dos rebaselines duckduckgo_free + stream_recovery) e teste de contagem de providers atualizado 12->13.
Comment on lines +39 to +41
return text
.replace(/&nbsp;/gi, " ")
.replace(/&amp;/gi, "&")
}

function stripTags(html: string): string {
return decodeEntities(html.replace(/<[^>]+>/g, "")).replace(/\s+/g, " ").trim();
});

assert.equal(result.success, true);
assert.ok(capturedUrl.includes("lite.duckduckgo.com"), "must hit the DDG lite endpoint");
test("handleSearch fails over to duckduckgo-free when the primary provider errors", async () => {
const originalFetch = globalThis.fetch;
globalThis.fetch = (async (url: string | URL) => {
if (String(url).includes("lite.duckduckgo.com")) {
…form controls (design phases 1-4) (#4122)

Unified visual identity (design phases 1-4): grid, primitives, tables, form controls. Integrado em release/v3.8.29: clsx + tailwind-merge adicionados à dependency-allowlist (já declarados no package.json, consumidos por src/shared/utils/cn.ts) para o check:deps anti-slopsquatting passar.
Fase 3 spike — TPROXY command builder (pure, execFile-safe {bin,args[]} per Rule #13) + ProxyBridge capture-source decision. Integrado em release/v3.8.29.
…#4140)

Credential-redaction safety net (FCC port, Fase 8.3): defense-in-depth pino logMethod hook, ReDoS-bounded patterns, behavior-preserving. Integrado em release/v3.8.29.
…ent (C6) (#4141)

Grid wallpaper opacity tuned up so it's actually visible on the dense
dashboard: light 0.045->0.07, dark 0.035->0.06 (the site's 0.045/0.035
read as invisible behind the cards/chrome that cover most of the viewport).

Focus-ring reconcile (design.md C6): the form controls (Input, Select,
Textarea, Toggle, Checkbox) now focus on the accent (violet) ring to match
the global --focus-ring, instead of the red ring-primary that collided with
the red error state. Error rings stay red.

Guard test updated (grid opacity + new C6 assertion). Build verified:
--grid-line compiles to #12 / #ffffff0f and focus:ring-accent/30 +
focus:border-accent/50 utilities are generated.
…4144)

TPROXY setup layer — transactional apply/revert (Epic A). execFile runner (Rule #13, args array, no shell) over the VPS-validated command builder (#4139); apply rolls back on mid-way failure, revert idempotent. Integrado em release/v3.8.29.
…nerate per-provider table (#4142)

Follow-ups from the 2026-06-17 free-tier refresh (#4089) that did NOT land in the
original merge — orphan commit ccc13c2 was pushed after the PR had already merged,
so these three follow-ups never shipped. Re-applied onto release/v3.8.29.

- providers.ts: hasFree flipped to false for confirmed-dead free tiers
  (phind x2, kluster, glhf, chutes) so onboarding stops advertising a free tier
  that no longer exists. Deliberately NOT flipped: gitlawb (dedicated test guards
  hasFree:true), aimlapi/theoldllm (medium-confidence research) — flipping risks a
  qwen-web-style false removal.
- New test tests/unit/discontinued-providers-2026.test.ts guards both the flips and
  the intentional keeps.
- Headline rounded ~1.5B -> ~1.6B in README (hero/badge/intro/bullet), FREE_TIERS
  honest-headline sentence, and FREE-TIERS-GUIDE total. The TL;DR table + live card +
  SVG keep the precise computed ~1.54B.
- FREE_TIERS per-provider table regenerated from the per-model catalog (pool-deduped,
  2026-06-17): the old inflated rate-limit rows (sparkdesk 2.59B / tencent 2.07B /
  siliconflow 1.73B) are gone — uncapped providers now show 'uncapped*'.
…r) (#4143)

Owner found the 46px graph-paper cells a touch large for the dashboard
layout; tightening --grid-size to 32px (a ~30% reduction). Mirrors the
matching change on the marketing site so the two stay identical.

Guard test + design.md updated. Build verified: --grid-size compiles to 32px.
No-thinking gateway model IDs (FCC port, Fase 8.1): synthetic claude-3-omniroute-no-thinking/<provider>/<model> catalog id that resolves to the real model with reasoning suppressed. Integrado em release/v3.8.29.
… Fase 8.2) (#4146)

Per-provider sliding-window rate-limit fallback (FCC port, Fase 8.2): opt-in (empty map = no-op), burst-free sliding window as a floor for header-less providers; Bottleneck still applies. Integrado em release/v3.8.29 (conflito de file-size-baseline resolvido por união com #4145).
…se 9 T9) (#4149)

Harden fabricated-docs checker (precision: env helpers/code-identifiers/api-prefixes/env-contract/tutorial-placeholders) + enforce --strict (QG v2 Fase 9 T9). Inclui testes anti-over-suppression + correção de refs stale de docs. Integrado em release/v3.8.29.
diegosouzapw and others added 23 commits June 19, 2026 00:01
…(prebuilds 4e) (#4236)

Integrated into release/v3.8.29
…(T1) + mutationScore ratchet (T3) (#4234)

Integrated into release/v3.8.29
…strip + verbosity passthrough (#4245)

Integrated into release/v3.8.29 (baseline reconciled)
…endpoints + motor de custo não-token (#4247)

Integrated into release/v3.8.29 (baseline reconciled: chatCore 5111, combo 2605)
…ias (#4253)

Integrated into release/v3.8.29 — remove vestigial SLM seam (createSLMStub/SLMInterface) + dead estimateTokensForStats alias. Validated: ultra.test.ts 39/39 green, zero code callers of the removed symbols.
… (#4250)

Integrated into release/v3.8.29 — Cursor Cloud Agent (cursor-cloud) via official api.cursor.com REST API key, 4th cloud agent mirroring Devin/Jules.

Pre-merge work done on the PR branch (fix-in-place):
- Wired cursor-cloud into the dashboard UI (CLOUD_AGENTS dropdown), health PROVIDER_NAMES, and lobeProviderIcons — it was API-usable but not selectable in the UI and rendered with the Jules fallback.
- Fixed cloud-agent-health-api.test.ts which asserted exactly 3 agents (the PR added a 4th) -> updated count/order + added cursor-cloud coverage.
- file-size baseline: page.tsx 913->922.

FOLLOW-UP (Rule #18): the REST endpoint paths/field names follow Cursor's documented Cloud Agents v0 API but still need a live validation run against a real Cursor API key. The integration is additive/opt-in and baseUrl is overridable per-credential, so any path/version correction needs no code change. Thanks @MRDGH2821 for the issue (#4227).
…the llmlingua SLM tier (#4257)

Wire ultra's modelPath/slmFallbackToAggressive to the llmlingua SLM tier. Follow-up to #4253. Integrated into release/v3.8.29.
…tokens (#4256)

Remote mode: drive a remote OmniRoute via scoped CLI access tokens (read⊂write⊂admin). Includes the check:db-rules allowlist fix (535a5b6). Live VPS end-to-end (password→token→remote command) is a documented follow-up. Integrated into release/v3.8.29.
…ng (#4255)

GLM-5.2+ thinking: default max_tokens=131072 when omitted + extend GLM_TIMEOUT_MS to 50min (aligns Z.AI API_TIMEOUT_MS). Regression test added (Rule #18). Thanks @dhaern. Integrated into release/v3.8.29.
…) + extend to c/d/g/h (#4258)

Restore cold-seed timeout headroom in nightly-mutation (per-batch timeout: a/b/c/d=350, g/h=240, rest=180). A cold Stryker run must complete once to seed stryker-incremental.json; a job cancelled at the cap never seeds. Integrated into release/v3.8.29.
Keep optional deps on update: add --include=optional to the CLI update, auto-updater, and source-update scripts so optionalDependencies (better-sqlite3, keytar, tls-client, llmlingua SLM stack) survive an omit=optional config. Test-guarded (RED→GREEN). Integrated into release/v3.8.29.
…ease

Full quality gate (test:unit + test:vitest + check:docs-all) caught drift from
cycle PRs that the PR→release fast-gates do not run. Each fix aligns to the
already-merged code (no behavior change):

- test(cloud-agent): expect 4 registered agents incl. cursor-cloud (#4250)
- test(db-rules): add accessTokens to INTENTIONALLY_INTERNAL audited set (#4256)
- test(glm): GLM/GLM-CN coding timeout 900000 -> 3000000 (50min) (#4255)
- fix(i18n): add connect/tokens/configure CLI locale sections to pt-BR.json (#4256)
- docs(env): document OMNIROUTE_CONTEXT in .env.example + ENVIRONMENT.md (#4256)
- fix(ci): fabricated-docs checker now indexes arg-bearing .command("x <a>")
  forms (false-negative flagged a real `omniroute connect`); +2 regression tests
… test-masking allowlist)

Release-PR (→main) quality gates fired on cumulative cycle drift the PR→release
fast-gates don't run:

- eslintWarnings ratchet 3779 -> 3816: +37 `any` (warn-level) warnings from 115
  cycle commits in open-sse/ and tests/. Release reconciliation adds 0 warnings
  (scripts/check/*.mjs are eslint-ignored; new fabricated-docs test uses no any).
  Same precedent as the v3.8.28 cycle-close rebaseline. Documented in baseline.
- test-masking allowlist += 5 verified-legitimate net-assert reductions from merged
  refactors: #4129 (combo-routing-e2e alignment), #4226 (ccr-marker/session-dedup
  helper removal), #4253 (ultra SLM-seam removal), #4132 (db-backup de-flake).
  Each reduction removed/restructured asserts for removed code — not weakening.
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
2 Security Hotspots
0.0% Coverage on New Code (required ≥ 80%)
D Security Rating on New Code (required ≥ A)
D Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

… cycle improvements

Require-tighten (blocking) flagged 2 metrics that IMPROVED this cycle (CI-measured
on PR #4126): coverage.auth.lines 69->90 (CI 92.6; ~2pt anti-flake floor) and
openapiCoverage.pct 37.6->38.4. Legitimate improvements locked into the baseline.
@diegosouzapw
diegosouzapw merged commit 3c9883b into main Jun 19, 2026
8 of 9 checks passed
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
OmniRoute v3.8.29 — 115 commits since v3.8.28. Full CHANGELOG + 41 i18n mirrors. All content quality gates green (build, unit 8/8, vitest 188/188, PR test policy, quality gates extended, docs sync, quality ratchet). Remaining red CI checks are pre-existing release flakes (coverage-shard/integration/node-compat teardown), a new transitive undici advisory in electron devDeps, and a workflow-level CodeQL fail (0 open alerts). VPS-validated by the operator.
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
OmniRoute v3.8.29 — 115 commits since v3.8.28. Full CHANGELOG + 41 i18n mirrors. All content quality gates green (build, unit 8/8, vitest 188/188, PR test policy, quality gates extended, docs sync, quality ratchet). Remaining red CI checks are pre-existing release flakes (coverage-shard/integration/node-compat teardown), a new transitive undici advisory in electron devDeps, and a workflow-level CodeQL fail (0 open alerts). VPS-validated by the operator.
tkgo11 pushed a commit to tkgo11/OmniRoute that referenced this pull request Sep 23, 2026
… cycle improvements

Require-tighten (blocking) flagged 2 metrics that IMPROVED this cycle (CI-measured
on PR cheaper-inference#4126): coverage.auth.lines 69->90 (CI 92.6; ~2pt anti-flake floor) and
openapiCoverage.pct 37.6->38.4. Legitimate improvements locked into the baseline.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
OmniRoute v3.8.29 — 115 commits since v3.8.28. Full CHANGELOG + 41 i18n mirrors. All content quality gates green (build, unit 8/8, vitest 188/188, PR test policy, quality gates extended, docs sync, quality ratchet). Remaining red CI checks are pre-existing release flakes (coverage-shard/integration/node-compat teardown), a new transitive undici advisory in electron devDeps, and a workflow-level CodeQL fail (0 open alerts). VPS-validated by the operator.
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.

9 participants