✨ New Features
-
compression (pipeline): add an honest default-on inflation guard to the stacked compression pipeline (T02 / Headroom H1). If the fully-stacked engines produce a body that did not actually shrink — its token count is
>=the original — the compressed body is discarded and the verbatim original request is sent upstream instead, with apipeline-inflation-guardwarning recorded in the compression stats. This is safe by construction (the only fallback is the unmodified original, always a valid payload) and complements the existing opt-in per-step TV1 bail-out, which governs step-to-step advancement rather than the final output. Newopen-sse/services/compression/pipelineGuards.ts; wired at the singlefinalizeStackedResultchoke point shared by the sync and async stacked paths. Regression guards (incl. an inflating-engine integration test) intests/unit/compression-pipeline-inflation-guard.test.ts. -
compression (caveman): complete the German, French, and Japanese rule packs with the
dedup(repeated-context collapsing) andultra(abbreviation / terse) categories they were missing — these three languages previously shipped onlycontext/filler/structural, whileen/es/id/pt-BRhad all five. So a de/fr/ja conversation compressed at higher intensities now collapses repeated boilerplate ("wie bereits besprochen" → "Siehe oben.", "comme mentionné précédemment" → "Voir ci-dessus.", "前述のとおり" → "(上記参照)") and abbreviates dense technical vocabulary (Datenbank→DB,Authentifizierung→Auth;base de données→BD,authentification→auth;データベース→DB,アプリケーション→app). Patterns mirror the existingespack and stay ReDoS-safe (bounded literal alternations; the CJK pack uses no\bsince Japanese has no word boundaries). Regression guard:tests/unit/caveman-packs-de-fr-ja.test.ts(packs load + validate + shrink a representative sample). gaps v3.8.42 — T05/C2. -
compression (caveman): add a Chinese (zh / wenyan 文言) input-side rule pack — the counterpart of the existing output-side
terse-cjkstyle. Newrules/zh/{dedup,filler,ultra}.jsoncollapse repeated context ("如前所述" → "见上。"), drop pleasantries/hedging ("请帮我…/谢谢/我觉得"), strip sentence-final modal particles ("吗/呢/吧"), and abbreviate dense technical terms ("数据库"→"DB", "应用程序"→"app"). Chinese is now auto-detected:detectCompressionLanguagedistinguishes zh from ja by Han-without-kana (kana is Japanese-exclusive, so a Han-heavy Japanese sentence still resolves toja), andzhis listed inlistSupportedCompressionLanguages. Patterns are ReDoS-safe (bounded literal alternations, no\bsince CJK has no word boundaries). Regression guard:tests/unit/caveman-packs-zh-wenyan.test.ts(packs load + validate + shrink; zh/ja/non-CJK detection). gaps v3.8.42 — T05/C6. -
compression (RTK): add Gradle and .NET CLI (
dotnet) to the RTK tool-output filter catalog. Tool output forgradle/gradlewanddotnet build|test|restore|publishis now recognized (both by command and by output content) and compressed: Gradle daemon/welcome banners and no-op> Task … UP-TO-DATE/SKIPPED/FROM-CACHElines are dropped whileBUILD SUCCESSFUL/FAILED, "What went wrong", and stack traces are preserved; the .NET build banner, copyright, andDetermining projects to restore/Restored …chatter are dropped whileBuild succeeded/FAILED,error CS####/warning CS####, and test summaries are preserved. New builtin filtersengines/rtk/filters/{gradle,dotnet}.json(with inline tests run by the catalog gate) plusgradle/dotnetentries in the command detector. Regression guard:tests/unit/rtk-gradle-dotnet-filters.test.ts. gaps v3.8.42 — T07/R9.
🔧 Bug Fixes
-
providers (chatgpt-web): fix
502 ChatGPT sentinel failed: Digest method not supportedon the Electron desktop app, which made everychatgpt-web/*request fail. The sentinel proof-of-work hashed with nativecreateHash("sha3-512"), but Electron's Node is built against BoringSSL, which does not implement the SHA-3 family (electron/electron#30530), so the digest threw at construction — the provider was unusable on the desktop build (works under plain Node/OpenSSL). The PoW now hashes through a new runtime-portable helper (open-sse/utils/sha3-512.ts) that prefers the native digest and transparently falls back to a dependency-free pure-JS Keccak-f[1600] when native SHA-3 is absent. The fallback is validated bit-for-bit against nativecreateHash("sha3-512")(300 random inputs) and the published FIPS-202 known-answer vectors. Regression guards intests/unit/chatgpt-web-sha3-boringssl-5531.test.ts. (#5531) -
providers (bytez): fix Bytez key validation ("Provider validation endpoint not supported") and the chat base URL, verified live with a real key. Bytez is OpenAI-compatible at
…/models/v2/openai/v1, but the registry stored the bare…/models/v2base, so the validation chat-probe hit…/models/v2/chat/completions→404→ the misleading "endpoint not supported". Two parts: (1) the registrybaseUrlnow carries the full OpenAI-compat chat path (…/models/v2/openai/v1/chat/completions); (2) key validation no longer uses a chat probe — a Bytez account only serves models explicitly added to its catalog, so even valid keys 404 on any model id. A dedicatedvalidateBytezProviderinstead probes the auth-onlyGET …/models/v2/list/tasksendpoint (200⇒ valid,401/403⇒ invalid), which is independent of catalog provisioning. Regression guard:tests/unit/bytez-validation-5422.test.ts. (#5422) -
dashboard (provider add): two provider-add UX fixes. (1) #5420 — the "Import Models" button now stays hidden for tool-only providers (web search / web fetch), not just
*-searchids:firecrawlandjina-reader(declaredserviceKinds: ["webFetch"]) previously showed an Import button that hit the400 "does not support models listing"route. A new capability check (providerLacksModelListingover the resolved serviceKinds) gates the section without ever hiding an LLM/media provider. (2) #5426 — Coze key validation no longer leaks the raw upstream envelope ({code,msg,logId,from}) into the UI; the Coze-shaped error becomes a friendlyCoze rejected the key: <msg> (code <n>)message (scoped toprovider === "coze"so no other provider is affected). Regression guards:tests/unit/model-listing-capability-5420.test.ts,tests/unit/coze-validation-error-5426.test.ts. (#5420, #5426) -
providers (friendliai, novita): fix two provider registry endpoints that rejected valid keys (verified live with real keys). FriendliAI pointed at
…/dedicated/v1/chat/completions, which403 Forbiddens a serverlessflp_*token — switched to…/serverless/v1/chat/completions(+ a serverlessmodelsUrl). Novita pointed at the legacy…/v3/…base with a typo'd model idai-ai/llama-3.1-8b-instruct(both404) — switched to the OpenAI-compatible…/openai/v1/…base + the validmeta-llama/llama-3.1-8b-instructid. Regression guard:tests/unit/provider-endpoints-friendliai-novita.test.ts. (#5430, #5455) -
providers (muse-spark): align the Muse Spark Web (Meta AI) cookie copy with the live cookie name. The default session cookie migrated from the retired
abra_sesstoecto_1_sess(META_AI_DEFAULT_COOKIE), but the provider form hint and one 401 auth-failure message still told users to pasteabra_sess— a cookie that no longer exists. Both strings now nameecto_1_sess. Regression guard:tests/unit/muse-spark-cookie-copy-5449.test.ts. (#5449) -
dashboard (provider add): fix three rough edges in the Add-API-Key / model-import flow reported across the provider-catalog audit. (1) The Validation Model and Account ID form fields shipped untranslated i18n stub copy (
"Validation Model Id Label","Account Id Placeholder", …) that surfaced verbatim in the modal — replaced with real labels/placeholders/hints inen.json. (2) Model import silently fell back to the cached/local catalog: the route already returned awarning("API unavailable — using local catalog"), butuseModelImportHandlersonly readmodels/errorand dropped it, so the user got local models with no indication — the warning is now surfaced as an import log line (new pure helperextractImportWarning). (3) The required connection-name field defaulted to"", which let browser autofill inject garbage (e.g.wiw) — it now defaults to"main". Regression guard:tests/unit/provider-add-ux-i18n-import-warning.test.ts. (#5421, #5428, #5429, #5431, #5435) -
services (installer): fix
spawn EINVALwhen installing an embedded service (9Router / CLIProxy) on Windows + Node.js 24+. Node 24 stopped lettingchild_process.execFile()run.cmdbatch files without a shell (nodejs/node#52554), and npm on Windows isnpm.cmd, sorunNpm()threwEINVALthe moment a user clicked Install.runNpmnow enablesshellon win32 only. To keep Hard Rule #13 intact under a shell — where the shell, notexecFile, parses argv — the install--prefix(aDATA_DIRpath that can legitimately contain spaces, e.g.C:\Users\John Doe\.omniroute\…) is now passed via thenpm_config_prefixenvironment variable instead of an argv path, and the user-supplied installversionis constrained to a dist-tag/semver shape (SERVICE_VERSION_PATTERN) at the route boundary so it can never carry shell metacharacters. With the prefix in the environment and the version validated, every remaining argv entry is a static flag. Regression guards:tests/unit/services/installers/runNpm-shell-5379.test.ts(+ existingninerouter.test.tsaligned to npm'snpm_config_prefixenv). (#5379) -
cli (serve): restore
dist/tls-options.mjsto the npm tarball — the opt-in native HTTPS/TLS sidecar (#5361) was copied into the stageddist/by the build but then pruned by the prepublish allowlist step, soomniroute servecrashed on the published 3.8.41 withERR_MODULE_NOT_FOUND(dist/server-ws.mjsimports./tls-options.mjs). Addedtls-options.mjstoAPP_STAGING_ALLOWED_EXACT_PATHS(survives the prune) anddist/tls-options.mjstoPACK_ARTIFACT_REQUIRED_PATHS(thecheck:pack-artifactgate now fails loudly if it ever vanishes again — same guard pattern aswebdav-handler.mjs). Regression guards intests/unit/pack-artifact-policy.test.ts. (#5452 — thanks @KooshaPari for the parallel fix #5494) -
dashboard: fix the Add Provider / onboarding wizard button silently doing nothing. The
/dashboard/providers/newroute was a redirect stub (it bounced straight back to/dashboard/providers), so every "Add Provider" button and dashboard widget link opened nothing, and the fully-builtProviderOnboardingWizardcomponent stayed orphaned (never rendered by any route). The route now renders the wizard directly; auth is enforced centrally by the(dashboard)layout, same as the sibling provider routes. Regression guard intests/unit/onboarding-wizard-route-5427.test.ts. (#5427) -
db (import): fix
EBUSY: resource busy or lockedwhen importing a database on Windows. The import route deleted the livestorage.sqlite+ WAL/-shm/-journalsidecars with a plainfs.unlinkSyncimmediately afterresetDbInstance(), but Windows releases the SQLite file handle asynchronously afterclose()(mmap / antivirus), so the unlink raced and threwEBUSY. The route now deletes viaunlinkFileWithRetry(EBUSY/EPERM backoff) — the same helper the restore path already uses. Regression guard intests/unit/db-import-ebusy-5406.test.ts. (#5406, consolidated under #5161) -
build: keep
ioredisout of the client/CLI bundle — a dast-smoke regression revealed the module was being pulled into browser/Electron client-side chunks; adding it to theSPAWN_CAPABLE_PREFIXESleaf excludes it from client bundles while keeping it available on the server path. (#5546) -
providers (mimocode): route per-account traffic through SOCKS5 proxy dispatchers — each mimocode account's requests are now dispatched via its configured SOCKS5 proxy rather than the default direct connection. (#5521 — thanks @pizzav-xyz)
-
providers: persist the Configured provider filter selection across page reloads — the filter was resetting to "All" on every navigation. (#5510 — thanks @KooshaPari)
-
providers (chatgpt-web): support GPT-5.5 Pro model handoff — adds the model mapping and handoff routing needed for the GPT-5.5 Pro tier. (#5536 — thanks @Thinkscape)
-
dashboard: keep onboarding schemas browser-safe — the schema module imported a server-side
dbreference that crashed the browser bundle; it is now imported only on the server path. (#5525 — thanks @KooshaPari) -
routing (bifrost): add auto-fallback cooldown for bifrost targets — prevents rapid re-selection of a failing bifrost backend within the cooldown window, complementing the existing circuit-breaker mechanism. (#5519 — thanks @KooshaPari)
-
providers (opencode-plugin): bump the opencode plugin to v0.2.0 and wire auto-publish on release so the plugin package tracks OmniRoute releases automatically. (#5363 — thanks @herjarsa)
-
rate-limit: normalize queue refresh settings — aligns the queue-refresh interval configuration across rate-limit strategies so stale queues are released on a consistent schedule. (#5499 — thanks @KooshaPari)
-
fallback: normalize provider error-rule header extraction — ensures fallback retry decisions correctly read all response headers regardless of casing, fixing cases where a provider's
Retry-Afteror custom error header was silently dropped. (#5473 — thanks @KooshaPari) -
routing: gate Claude adaptive-thinking defaults behind the feature flag — prevents the thinking budget from being injected into requests for models that do not support the extended-thinking parameter, avoiding upstream
400errors on non-thinking Claude variants. (#5480 — thanks @KooshaPari) -
ci: fix post-merge CI regressions introduced by the dead-code sweep — restores test imports and type references broken when the ratchet landed before downstream consumers were updated. (#5467 — thanks @KooshaPari)
-
sse: treat terminal stream cancels as complete — an aborted SSE stream was being left in a partial state, causing downstream consumers to wait indefinitely for a final event that would never arrive. (#5491 — thanks @JxnLexn)
-
api: fix framing of non-streaming JSON responses —
stream: falsechat-completions responses were returned without correct content-length framing, causing some clients to misparse the response body. (#5416 — thanks @rdself) -
dashboard (tests): protect dynamic dashboard endpoint tests with CSRF validation — the test suite was exercising dashboard API routes without CSRF tokens, masking a coverage gap for those endpoints. (#5405 — thanks @rdself)
-
providers: remove the dead Phind provider (service shut down) and deduplicate the HuggingChat catalog listing that had accumulated a stale duplicate entry. (#5530 — thanks @backryun)
-
providers (longcat): correct the LongCat free tier — LongCat-2.0 is now GA; the one-time 10M-token promo (KYC required) is correctly reflected in the catalog, replacing the stale legacy beta entry. (#5508 — thanks @backryun)
📝 Maintenance
-
dashboard (refactor): consolidate the duplicate caveman on/off toggle from the compression settings tab onto the single-source panel (T11), eliminating the stale off-sync copy. (#5524)
-
tests: add quota guard for Claude-Code identity version lockstep (Phase 2) — asserts that the Claude-Code version reported in quota accounting stays in sync with the deployed version, preventing silent drift. (#5514)
-
docs: add relay backend strategy guide documenting supported relay backend types, selection criteria, and configuration patterns. (#5547)
-
docs: clarify bifrost relay backend environment variables — documents which env vars control bifrost's relay backend selection and failover behavior. (#5520 — thanks @KooshaPari)
-
tests: add relay routing fallback header behavior tests — regression guard asserting that fallback-triggered relay requests carry the correct forwarded headers through the routing layer. (#5526 — thanks @KooshaPari)
-
ci: add npm
fetch-retryconfiguration and codify the release-freeze protocol (Hard Rule #21) — reduces transient npm registry fetch failures in CI and establishes the documented procedure for freezing releases. (#5506) -
deps: bump 11 production dependencies to their latest compatible versions. (#5414)
-
deps: bump Electron from 42.4.1 to 42.5.1 in
/electron. (#5413) -
deps: bump the development dependency group with 9 updates. (#5415)
-
maintenance (dead-code): repo-wide sweep of unused exported symbols, types, and schemas — removes 35 no-longer-referenced exports across cloud-agent, a2a, SSE, memory, quota, skills, gamification, codex, qdrant, playground, provider catalog, and combo modules, reducing the exported API surface and eliminating stale misleading types. (#5372, #5373, #5374, #5375, #5376, #5377, #5378, #5380, #5381, #5382, #5383, #5384, #5385, #5386, #5387, #5388, #5389, #5390, #5391, #5392, #5393, #5395, #5396, #5397, #5398, #5399, #5400, #5401, #5402, #5403, #5404, #5463, #5464, #5466, #5468 — thanks @JxnLexn)
-
maintenance (DRY): DRY consolidation of shared helpers — extracts 17 duplicated utilities into single shared modules: vscode metadata helpers, proxy route handlers, auth zip extractors, combo-builder model options, vscode tokenized-request helpers, quota strategy ranking helpers, recharts donut card, provider-specific validation, batch response formatter, Redis runtime helpers, version-manager request parsing, media-generation route helpers, service install helpers, settings transform schemas, relay stream finalizer, machine-id fallback, and node SQLite adapter. (#5471, #5472, #5475, #5477, #5479, #5482, #5484, #5485, #5488, #5490, #5492, #5493, #5495, #5496, #5497, #5498, #5500 — thanks @JxnLexn)
What's Changed
- deps: bump the development group across 1 directory with 9 updates by @dependabot[bot] in #5415
- [codex] add relay backend strategy guide by @KooshaPari in #5533
- Release v3.8.42 by @diegosouzapw in #5459
Full Changelog: v3.8.41...v3.8.42