Release v3.8.22 - #3623
Release v3.8.22#3623
Conversation
There was a problem hiding this comment.
Code Review
This pull request bumps the project version from 3.8.21 to 3.8.22 across package manifests, OpenAPI specifications, and changelogs. The reviewer identified that the internationalized changelog files are missing markdown links for the English CHANGELOG reference and provided suggestions to restore these links for consistency.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
|
||
| ## [3.8.22] — TBD | ||
|
|
||
| _See English CHANGELOG for v3.8.22 details._ |
There was a problem hiding this comment.
|
|
||
| ## [3.8.22] — TBD | ||
|
|
||
| _See English CHANGELOG for v3.8.22 details._ |
There was a problem hiding this comment.
|
|
||
| ## [3.8.22] — TBD | ||
|
|
||
| _See English CHANGELOG for v3.8.22 details._ |
There was a problem hiding this comment.
|
|
||
| ## [3.8.22] — TBD | ||
|
|
||
| _See English CHANGELOG for v3.8.22 details._ |
There was a problem hiding this comment.
|
|
||
| ## [3.8.22] — TBD | ||
|
|
||
| _See English CHANGELOG for v3.8.22 details._ |
There was a problem hiding this comment.
|
|
||
| ## [3.8.22] — TBD | ||
|
|
||
| _See English CHANGELOG for v3.8.22 details._ |
There was a problem hiding this comment.
|
|
||
| ## [3.8.22] — TBD | ||
|
|
||
| _See English CHANGELOG for v3.8.22 details._ |
There was a problem hiding this comment.
|
|
||
| ## [3.8.22] — TBD | ||
|
|
||
| _See English CHANGELOG for v3.8.22 details._ |
There was a problem hiding this comment.
|
|
||
| ## [3.8.22] — TBD | ||
|
|
||
| _See English CHANGELOG for v3.8.22 details._ |
There was a problem hiding this comment.
|
|
||
| ## [3.8.22] — TBD | ||
|
|
||
| _See English CHANGELOG for v3.8.22 details._ |
There was a problem hiding this comment.
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
Code Review SummaryStatus: No Issues Found | Recommendation: Merge This is a standard release preparation PR (v3.8.22) containing only:
No functional code changes, no bugs, no security concerns. Files Reviewed (44 files)
Reviewed by laguna-m.1-20260312:free · 230,029 tokens |
CI Coverage Report
Coverage artifact was not available for this run. |
#3501 Phase 1a: extract 3 auth-import modal clusters. Co-authored-by: oyi77 <oyi77@users.noreply.github.com>
38ffff6 to
d8b9759
Compare
…) (#3632) Integrated into release/v3.8.22
…ional endpoint (#3631) Integrated into release/v3.8.22
Integrated into release/v3.8.22
…ors (#3637) Integrated into release/v3.8.22 — circuit-breaker guard added in review (#1731v2)
…uth (#3659) Integrated into release/v3.8.22 — page.tsx conflict resolved + NoAuthAccountCard re-applied to ProviderDetailPageClient in review. MiMoCode endpoint validated live.
Integrated into release/v3.8.22 — Codex Responses WebSocket call history logging.
Integrated into release/v3.8.22 — page.tsx conflict resolved (re-applied toggle to ProviderDetailPageClient) + disable-test updated for catalog drift in review.
…follow-up) The mimocode RegistryEntry omitted the required authHeader field, which broke typecheck:core (TS2741). Match the no-auth convention (authType:"none" + authHeader:"none") used by veoaifree-web and other free providers. Follow-up to #3659 (@pizzav-xyz).
…llow-up roll-up
#3485 part 2) (#3678) Part 2 of #3485. WebDAV server (PROPFIND/GET/PUT/DELETE/MKCOL/MOVE/OPTIONS) handled in the custom server layer (standalone-server-ws.mjs) since the App Router cannot export WebDAV methods. Basic-Auth (constant-time), path-traversal hardened, password decrypt ported from encryption.ts (parity-tested), DATA_DIR resolution parity-tested against dataPaths.ts. End-to-end Obsidian-over-Tailscale validation is a live VPS step (Rule #18).
…ws + per-target compression limit (#3680) Integrated into release/v3.8.22
…#3675) Integrated into release/v3.8.22
…s — #3501 Phase 1e (#3683) #3501 Phase 1e: extract useModelCompatState hook (unblocks the model sections) + ModelRow/PassthroughModelsSection/PassthroughModelRow/CustomModelsSection/CompatibleModelsSection. god-component 6,838->4,921 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com>
* chore(release): open v3.8.22 development cycle * refactor(dashboard): extract ProviderDetailPageClient — diegosouzapw#3501 Phase 0 (diegosouzapw#3633) diegosouzapw#3501 Phase 0: extract ProviderDetailPageClient + smoke test. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract auth-import modals — diegosouzapw#3501 Phase 1a (diegosouzapw#3634) diegosouzapw#3501 Phase 1a: extract 3 auth-import modal clusters. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(db): reclassify localDb unexported modules as intentionally-internal (diegosouzapw#3499) (diegosouzapw#3635) Closes diegosouzapw#3499 — reclassify localDb unexported modules as intentionally-internal (audit + honest gate framing). * refactor(db): move call_logs aggregations into callLogStats db module (diegosouzapw#3500) (diegosouzapw#3636) diegosouzapw#3500 slice 1: call_logs aggregations → src/lib/db/callLogStats.ts (Rule diegosouzapw#5). Byte-identical queries; TDD 6/6. * refactor(dashboard): extract EditCompatibleNodeModal — diegosouzapw#3501 Phase 1b (diegosouzapw#3638) diegosouzapw#3501 Phase 1b: extract EditCompatibleNodeModal (cycle-safe via leaf constants module). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(db): move community_servers SQL into gamification db module (diegosouzapw#3500 slice 3) (diegosouzapw#3639) diegosouzapw#3500 slice 3: community_servers SQL → gamification db module. * refactor(db): move usage_history SQL into usageAnalytics module (diegosouzapw#3500 slice 2) (diegosouzapw#3644) diegosouzapw#3500 slice 2: usage_history/daily_usage_summary SQL → usageAnalytics db module. * refactor(db): move skills UPDATE + db-backups SQL into db modules (diegosouzapw#3500 slice 5) (diegosouzapw#3647) diegosouzapw#3500 slice 5: skills UPDATE (allowlist) + db-backups SQL → db modules. * refactor(db): move usage_logs/semantic_cache/proxy_logs SQL into db modules (diegosouzapw#3500 slice 4) (diegosouzapw#3648) diegosouzapw#3500 slice 4: usage_logs/semantic_cache/proxy_logs SQL → db modules. All internal routes done (2 external by-design remain). * chore(db-gate): reclassify external-DB reads, fully close diegosouzapw#3500 (diegosouzapw#3649) Closes diegosouzapw#3500: reclassify external-DB reads; all internal raw-SQL migrated to db/ modules. * refactor(dashboard): extract pure helpers to providerPageHelpers — diegosouzapw#3501 Phase 2 (diegosouzapw#3653) diegosouzapw#3501 Phase 2: extract pure helpers to providerPageHelpers (leaf, cycle-safe). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract remaining shared helpers to providerPageHelpers — diegosouzapw#3501 Phase 2b (diegosouzapw#3658) diegosouzapw#3501 Phase 2b: extract remaining shared helpers to providerPageHelpers (leaf, cycle-safe). Heavy modals unblocked. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(reasoning): replay reasoning_content on plain DeepSeek turns (diegosouzapw#1682) (diegosouzapw#3632) Integrated into release/v3.8.22 * fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint (diegosouzapw#3631) Integrated into release/v3.8.22 * refactor: small code cleanup (diegosouzapw#3523) Integrated into release/v3.8.22 * fix(combo): skip same-provider targets on 408/500/502/503/504/524 errors (diegosouzapw#3637) Integrated into release/v3.8.22 — circuit-breaker guard added in review (#1731v2) * feat(providers): add MiMoCode free-tier provider with bootstrap JWT auth (diegosouzapw#3659) Integrated into release/v3.8.22 — page.tsx conflict resolved + NoAuthAccountCard re-applied to ProviderDetailPageClient in review. MiMoCode endpoint validated live. * Log Responses WebSocket calls in history (diegosouzapw#3616) Integrated into release/v3.8.22 — Codex Responses WebSocket call history logging. * Add Claude Code routing preference for unprefixed Claude models (diegosouzapw#3540) Integrated into release/v3.8.22 — page.tsx conflict resolved (re-applied toggle to ProviderDetailPageClient) + disable-test updated for catalog drift in review. * docs(changelog): credit diegosouzapw#3632/diegosouzapw#3631/diegosouzapw#3637/diegosouzapw#3659/diegosouzapw#3540/diegosouzapw#3616/diegosouzapw#3523 (v3.8.22 targeted review round) * fix(mimocode): add required authHeader:"none" to registry entry (diegosouzapw#3659 follow-up) The mimocode RegistryEntry omitted the required authHeader field, which broke typecheck:core (TS2741). Match the no-auth convention (authType:"none" + authHeader:"none") used by veoaifree-web and other free providers. Follow-up to diegosouzapw#3659 (@pizzav-xyz). * fix(responses): detect stream readiness for tool-call-only and object-less chunks (diegosouzapw#3612) (diegosouzapw#3661) Closes diegosouzapw#3612 * fix(mitm): remove duplicated 'Command failed:' error prefix (diegosouzapw#3641) (diegosouzapw#3662) Closes diegosouzapw#3641 * fix(cli): honor HERMES_HOME for Hermes Agent config path (diegosouzapw#3628) (diegosouzapw#3663) Closes diegosouzapw#3628 * fix(api): fetch live OpenCode model catalog for no-auth model picker (diegosouzapw#3611) (diegosouzapw#3664) Closes diegosouzapw#3611 * fix(api): flag provider topology error state by current status, not stale history (diegosouzapw#3619) (diegosouzapw#3666) Closes diegosouzapw#3619 * fix(electron): launch peer-stamping server-ws.mjs entrypoint to avoid 403 LOCAL_ONLY (diegosouzapw#3386) (diegosouzapw#3665) Closes diegosouzapw#3386 * fix(dashboard): restore home topology live in-flight pulse (diegosouzapw#3507) (diegosouzapw#3667) Closes diegosouzapw#3507 * fix(oauth): name Kiro/AWS auto-imported accounts and dedupe by profileArn (diegosouzapw#3615) (diegosouzapw#3671) Closes diegosouzapw#3615 * fix(resilience): clear stale transient connection cooldowns on startup (diegosouzapw#3625) (diegosouzapw#3672) Closes diegosouzapw#3625 * fix(i18n): use logical CSS direction utilities for sidebar and key overlays (RTL diegosouzapw#3541) (diegosouzapw#3670) Closes diegosouzapw#3541 * fix(dashboard): honor auto-hide and switch to visible filter on passthrough Test-all (diegosouzapw#3610) (diegosouzapw#3669) Closes diegosouzapw#3610 * refactor(dashboard): extract AddApiKeyModal + EditConnectionModal — diegosouzapw#3501 Phase 1c (diegosouzapw#3674) diegosouzapw#3501 Phase 1c: extract AddApiKeyModal, EditConnectionModal, WebSessionCredentialGuide into components/; god-component 10,166->8,092 LOC. Reconciles the v3.8.22 file-size drift for this file. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * docs(changelog): reconcile v3.8.22 — credit diegosouzapw#3621/diegosouzapw#3622 + MiMoCode follow-up roll-up * refactor(dashboard): extract ConnectionRow + ModelCompatPopover + SiliconFlowEndpointModal — diegosouzapw#3501 Phase 1d (diegosouzapw#3676) diegosouzapw#3501 Phase 1d: god-component 8,092->6,838 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * feat(obsidian): add WebDAV config route + encrypt creds at rest (diegosouzapw#3485 part 1) (diegosouzapw#3677) Part 1 of diegosouzapw#3485. Adds /api/settings/obsidian/webdav (GET/POST/DELETE) wiring the ready obsidianSync lib, encrypts webdav password + obsidian token at rest, removes the duplicate UI block, drops the KNOWN_MISSING entry. WebDAV file server is part 2. * feat(obsidian): add /api/v1/webdav file server for Obsidian vault sync (diegosouzapw#3485 part 2) (diegosouzapw#3678) Part 2 of diegosouzapw#3485. WebDAV server (PROPFIND/GET/PUT/DELETE/MKCOL/MOVE/OPTIONS) handled in the custom server layer (standalone-server-ws.mjs) since the App Router cannot export WebDAV methods. Basic-Auth (constant-time), path-traversal hardened, password decrypt ported from encryption.ts (parity-tested), DATA_DIR resolution parity-tested against dataPaths.ts. End-to-end Obsidian-over-Tailscale validation is a live VPS step (Rule diegosouzapw#18). * fix(combo): stop premature context compaction — real auto-combo windows + per-target compression limit (diegosouzapw#3680) Integrated into release/v3.8.22 * feat(dashboard): deactivate/activate accounts from the quota overview (diegosouzapw#3675) Integrated into release/v3.8.22 * fix(dashboard): close review gaps in bulk provider connection actions (diegosouzapw#3271 follow-up) (diegosouzapw#3673) Integrated into release/v3.8.22 — page.tsx conflict (god-component split diegosouzapw#3501) resolved by re-applying the bulk-action deltas to ProviderDetailPageClient.tsx * refactor(dashboard): extract useModelCompatState hook + model sections — diegosouzapw#3501 Phase 1e (diegosouzapw#3683) diegosouzapw#3501 Phase 1e: extract useModelCompatState hook (unblocks the model sections) + ModelRow/PassthroughModelsSection/PassthroughModelRow/CustomModelsSection/CompatibleModelsSection. god-component 6,838->4,921 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract useProviderConnections/Settings/Models hooks — diegosouzapw#3501 Phase 1f (diegosouzapw#3684) diegosouzapw#3501 Phase 1f: god-component 4,948->4,062 LOC. Connection state+handlers, settings, and model metadata moved into hooks/. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * chore(release): v3.8.22 CHANGELOG + env-doc sync - Set release date in CHANGELOG [3.8.22] to 2026-06-11 - Add HERMES_HOME to .env.example (from diegosouzapw#3628/diegosouzapw#3663) - Add HERMES_HOME + OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS to ENVIRONMENT.md (diegosouzapw#3628/diegosouzapw#3540) * docs(changelog): credit diegosouzapw#3673 + diegosouzapw#3675 — leninejunior bulk-actions + quota-toggle --------- Co-authored-by: oyi77 <oyi77@users.noreply.github.com> Co-authored-by: Abhishek Divekar <adivekar@utexas.edu> Co-authored-by: NOXX - Commiter <artur1992123@mail.ru> Co-authored-by: Nicolas Lorin <androw95220@gmail.com> Co-authored-by: Hernan Javier Ardila Sanchez <hjasgr@gmail.com> Co-authored-by: PizzaV <103120356+pizzav-xyz@users.noreply.github.com> Co-authored-by: kkkayye <98376609+kkkayye@users.noreply.github.com> Co-authored-by: Witroch4 <witalo_rocha@hotmail.com> Co-authored-by: Lenine Júnior <lenine@engrene.com.br>
* chore(release): open v3.8.22 development cycle * refactor(dashboard): extract ProviderDetailPageClient — diegosouzapw#3501 Phase 0 (diegosouzapw#3633) diegosouzapw#3501 Phase 0: extract ProviderDetailPageClient + smoke test. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract auth-import modals — diegosouzapw#3501 Phase 1a (diegosouzapw#3634) diegosouzapw#3501 Phase 1a: extract 3 auth-import modal clusters. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(db): reclassify localDb unexported modules as intentionally-internal (diegosouzapw#3499) (diegosouzapw#3635) Closes diegosouzapw#3499 — reclassify localDb unexported modules as intentionally-internal (audit + honest gate framing). * refactor(db): move call_logs aggregations into callLogStats db module (diegosouzapw#3500) (diegosouzapw#3636) diegosouzapw#3500 slice 1: call_logs aggregations → src/lib/db/callLogStats.ts (Rule diegosouzapw#5). Byte-identical queries; TDD 6/6. * refactor(dashboard): extract EditCompatibleNodeModal — diegosouzapw#3501 Phase 1b (diegosouzapw#3638) diegosouzapw#3501 Phase 1b: extract EditCompatibleNodeModal (cycle-safe via leaf constants module). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(db): move community_servers SQL into gamification db module (diegosouzapw#3500 slice 3) (diegosouzapw#3639) diegosouzapw#3500 slice 3: community_servers SQL → gamification db module. * refactor(db): move usage_history SQL into usageAnalytics module (diegosouzapw#3500 slice 2) (diegosouzapw#3644) diegosouzapw#3500 slice 2: usage_history/daily_usage_summary SQL → usageAnalytics db module. * refactor(db): move skills UPDATE + db-backups SQL into db modules (diegosouzapw#3500 slice 5) (diegosouzapw#3647) diegosouzapw#3500 slice 5: skills UPDATE (allowlist) + db-backups SQL → db modules. * refactor(db): move usage_logs/semantic_cache/proxy_logs SQL into db modules (diegosouzapw#3500 slice 4) (diegosouzapw#3648) diegosouzapw#3500 slice 4: usage_logs/semantic_cache/proxy_logs SQL → db modules. All internal routes done (2 external by-design remain). * chore(db-gate): reclassify external-DB reads, fully close diegosouzapw#3500 (diegosouzapw#3649) Closes diegosouzapw#3500: reclassify external-DB reads; all internal raw-SQL migrated to db/ modules. * refactor(dashboard): extract pure helpers to providerPageHelpers — diegosouzapw#3501 Phase 2 (diegosouzapw#3653) diegosouzapw#3501 Phase 2: extract pure helpers to providerPageHelpers (leaf, cycle-safe). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract remaining shared helpers to providerPageHelpers — diegosouzapw#3501 Phase 2b (diegosouzapw#3658) diegosouzapw#3501 Phase 2b: extract remaining shared helpers to providerPageHelpers (leaf, cycle-safe). Heavy modals unblocked. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(reasoning): replay reasoning_content on plain DeepSeek turns (diegosouzapw#1682) (diegosouzapw#3632) Integrated into release/v3.8.22 * fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint (diegosouzapw#3631) Integrated into release/v3.8.22 * refactor: small code cleanup (diegosouzapw#3523) Integrated into release/v3.8.22 * fix(combo): skip same-provider targets on 408/500/502/503/504/524 errors (diegosouzapw#3637) Integrated into release/v3.8.22 — circuit-breaker guard added in review (#1731v2) * feat(providers): add MiMoCode free-tier provider with bootstrap JWT auth (diegosouzapw#3659) Integrated into release/v3.8.22 — page.tsx conflict resolved + NoAuthAccountCard re-applied to ProviderDetailPageClient in review. MiMoCode endpoint validated live. * Log Responses WebSocket calls in history (diegosouzapw#3616) Integrated into release/v3.8.22 — Codex Responses WebSocket call history logging. * Add Claude Code routing preference for unprefixed Claude models (diegosouzapw#3540) Integrated into release/v3.8.22 — page.tsx conflict resolved (re-applied toggle to ProviderDetailPageClient) + disable-test updated for catalog drift in review. * docs(changelog): credit diegosouzapw#3632/diegosouzapw#3631/diegosouzapw#3637/diegosouzapw#3659/diegosouzapw#3540/diegosouzapw#3616/diegosouzapw#3523 (v3.8.22 targeted review round) * fix(mimocode): add required authHeader:"none" to registry entry (diegosouzapw#3659 follow-up) The mimocode RegistryEntry omitted the required authHeader field, which broke typecheck:core (TS2741). Match the no-auth convention (authType:"none" + authHeader:"none") used by veoaifree-web and other free providers. Follow-up to diegosouzapw#3659 (@pizzav-xyz). * fix(responses): detect stream readiness for tool-call-only and object-less chunks (diegosouzapw#3612) (diegosouzapw#3661) Closes diegosouzapw#3612 * fix(mitm): remove duplicated 'Command failed:' error prefix (diegosouzapw#3641) (diegosouzapw#3662) Closes diegosouzapw#3641 * fix(cli): honor HERMES_HOME for Hermes Agent config path (diegosouzapw#3628) (diegosouzapw#3663) Closes diegosouzapw#3628 * fix(api): fetch live OpenCode model catalog for no-auth model picker (diegosouzapw#3611) (diegosouzapw#3664) Closes diegosouzapw#3611 * fix(api): flag provider topology error state by current status, not stale history (diegosouzapw#3619) (diegosouzapw#3666) Closes diegosouzapw#3619 * fix(electron): launch peer-stamping server-ws.mjs entrypoint to avoid 403 LOCAL_ONLY (diegosouzapw#3386) (diegosouzapw#3665) Closes diegosouzapw#3386 * fix(dashboard): restore home topology live in-flight pulse (diegosouzapw#3507) (diegosouzapw#3667) Closes diegosouzapw#3507 * fix(oauth): name Kiro/AWS auto-imported accounts and dedupe by profileArn (diegosouzapw#3615) (diegosouzapw#3671) Closes diegosouzapw#3615 * fix(resilience): clear stale transient connection cooldowns on startup (diegosouzapw#3625) (diegosouzapw#3672) Closes diegosouzapw#3625 * fix(i18n): use logical CSS direction utilities for sidebar and key overlays (RTL diegosouzapw#3541) (diegosouzapw#3670) Closes diegosouzapw#3541 * fix(dashboard): honor auto-hide and switch to visible filter on passthrough Test-all (diegosouzapw#3610) (diegosouzapw#3669) Closes diegosouzapw#3610 * refactor(dashboard): extract AddApiKeyModal + EditConnectionModal — diegosouzapw#3501 Phase 1c (diegosouzapw#3674) diegosouzapw#3501 Phase 1c: extract AddApiKeyModal, EditConnectionModal, WebSessionCredentialGuide into components/; god-component 10,166->8,092 LOC. Reconciles the v3.8.22 file-size drift for this file. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * docs(changelog): reconcile v3.8.22 — credit diegosouzapw#3621/diegosouzapw#3622 + MiMoCode follow-up roll-up * refactor(dashboard): extract ConnectionRow + ModelCompatPopover + SiliconFlowEndpointModal — diegosouzapw#3501 Phase 1d (diegosouzapw#3676) diegosouzapw#3501 Phase 1d: god-component 8,092->6,838 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * feat(obsidian): add WebDAV config route + encrypt creds at rest (diegosouzapw#3485 part 1) (diegosouzapw#3677) Part 1 of diegosouzapw#3485. Adds /api/settings/obsidian/webdav (GET/POST/DELETE) wiring the ready obsidianSync lib, encrypts webdav password + obsidian token at rest, removes the duplicate UI block, drops the KNOWN_MISSING entry. WebDAV file server is part 2. * feat(obsidian): add /api/v1/webdav file server for Obsidian vault sync (diegosouzapw#3485 part 2) (diegosouzapw#3678) Part 2 of diegosouzapw#3485. WebDAV server (PROPFIND/GET/PUT/DELETE/MKCOL/MOVE/OPTIONS) handled in the custom server layer (standalone-server-ws.mjs) since the App Router cannot export WebDAV methods. Basic-Auth (constant-time), path-traversal hardened, password decrypt ported from encryption.ts (parity-tested), DATA_DIR resolution parity-tested against dataPaths.ts. End-to-end Obsidian-over-Tailscale validation is a live VPS step (Rule diegosouzapw#18). * fix(combo): stop premature context compaction — real auto-combo windows + per-target compression limit (diegosouzapw#3680) Integrated into release/v3.8.22 * feat(dashboard): deactivate/activate accounts from the quota overview (diegosouzapw#3675) Integrated into release/v3.8.22 * fix(dashboard): close review gaps in bulk provider connection actions (diegosouzapw#3271 follow-up) (diegosouzapw#3673) Integrated into release/v3.8.22 — page.tsx conflict (god-component split diegosouzapw#3501) resolved by re-applying the bulk-action deltas to ProviderDetailPageClient.tsx * refactor(dashboard): extract useModelCompatState hook + model sections — diegosouzapw#3501 Phase 1e (diegosouzapw#3683) diegosouzapw#3501 Phase 1e: extract useModelCompatState hook (unblocks the model sections) + ModelRow/PassthroughModelsSection/PassthroughModelRow/CustomModelsSection/CompatibleModelsSection. god-component 6,838->4,921 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract useProviderConnections/Settings/Models hooks — diegosouzapw#3501 Phase 1f (diegosouzapw#3684) diegosouzapw#3501 Phase 1f: god-component 4,948->4,062 LOC. Connection state+handlers, settings, and model metadata moved into hooks/. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * chore(release): v3.8.22 CHANGELOG + env-doc sync - Set release date in CHANGELOG [3.8.22] to 2026-06-11 - Add HERMES_HOME to .env.example (from diegosouzapw#3628/diegosouzapw#3663) - Add HERMES_HOME + OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS to ENVIRONMENT.md (diegosouzapw#3628/diegosouzapw#3540) * docs(changelog): credit diegosouzapw#3673 + diegosouzapw#3675 — leninejunior bulk-actions + quota-toggle --------- Co-authored-by: oyi77 <oyi77@users.noreply.github.com> Co-authored-by: Abhishek Divekar <adivekar@utexas.edu> Co-authored-by: NOXX - Commiter <artur1992123@mail.ru> Co-authored-by: Nicolas Lorin <androw95220@gmail.com> Co-authored-by: Hernan Javier Ardila Sanchez <hjasgr@gmail.com> Co-authored-by: PizzaV <103120356+pizzav-xyz@users.noreply.github.com> Co-authored-by: kkkayye <98376609+kkkayye@users.noreply.github.com> Co-authored-by: Witroch4 <witalo_rocha@hotmail.com> Co-authored-by: Lenine Júnior <lenine@engrene.com.br>
* chore(release): open v3.8.22 development cycle * refactor(dashboard): extract ProviderDetailPageClient — diegosouzapw#3501 Phase 0 (diegosouzapw#3633) diegosouzapw#3501 Phase 0: extract ProviderDetailPageClient + smoke test. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract auth-import modals — diegosouzapw#3501 Phase 1a (diegosouzapw#3634) diegosouzapw#3501 Phase 1a: extract 3 auth-import modal clusters. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(db): reclassify localDb unexported modules as intentionally-internal (diegosouzapw#3499) (diegosouzapw#3635) Closes diegosouzapw#3499 — reclassify localDb unexported modules as intentionally-internal (audit + honest gate framing). * refactor(db): move call_logs aggregations into callLogStats db module (diegosouzapw#3500) (diegosouzapw#3636) diegosouzapw#3500 slice 1: call_logs aggregations → src/lib/db/callLogStats.ts (Rule diegosouzapw#5). Byte-identical queries; TDD 6/6. * refactor(dashboard): extract EditCompatibleNodeModal — diegosouzapw#3501 Phase 1b (diegosouzapw#3638) diegosouzapw#3501 Phase 1b: extract EditCompatibleNodeModal (cycle-safe via leaf constants module). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(db): move community_servers SQL into gamification db module (diegosouzapw#3500 slice 3) (diegosouzapw#3639) diegosouzapw#3500 slice 3: community_servers SQL → gamification db module. * refactor(db): move usage_history SQL into usageAnalytics module (diegosouzapw#3500 slice 2) (diegosouzapw#3644) diegosouzapw#3500 slice 2: usage_history/daily_usage_summary SQL → usageAnalytics db module. * refactor(db): move skills UPDATE + db-backups SQL into db modules (diegosouzapw#3500 slice 5) (diegosouzapw#3647) diegosouzapw#3500 slice 5: skills UPDATE (allowlist) + db-backups SQL → db modules. * refactor(db): move usage_logs/semantic_cache/proxy_logs SQL into db modules (diegosouzapw#3500 slice 4) (diegosouzapw#3648) diegosouzapw#3500 slice 4: usage_logs/semantic_cache/proxy_logs SQL → db modules. All internal routes done (2 external by-design remain). * chore(db-gate): reclassify external-DB reads, fully close diegosouzapw#3500 (diegosouzapw#3649) Closes diegosouzapw#3500: reclassify external-DB reads; all internal raw-SQL migrated to db/ modules. * refactor(dashboard): extract pure helpers to providerPageHelpers — diegosouzapw#3501 Phase 2 (diegosouzapw#3653) diegosouzapw#3501 Phase 2: extract pure helpers to providerPageHelpers (leaf, cycle-safe). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract remaining shared helpers to providerPageHelpers — diegosouzapw#3501 Phase 2b (diegosouzapw#3658) diegosouzapw#3501 Phase 2b: extract remaining shared helpers to providerPageHelpers (leaf, cycle-safe). Heavy modals unblocked. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(reasoning): replay reasoning_content on plain DeepSeek turns (diegosouzapw#1682) (diegosouzapw#3632) Integrated into release/v3.8.22 * fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint (diegosouzapw#3631) Integrated into release/v3.8.22 * refactor: small code cleanup (diegosouzapw#3523) Integrated into release/v3.8.22 * fix(combo): skip same-provider targets on 408/500/502/503/504/524 errors (diegosouzapw#3637) Integrated into release/v3.8.22 — circuit-breaker guard added in review (#1731v2) * feat(providers): add MiMoCode free-tier provider with bootstrap JWT auth (diegosouzapw#3659) Integrated into release/v3.8.22 — page.tsx conflict resolved + NoAuthAccountCard re-applied to ProviderDetailPageClient in review. MiMoCode endpoint validated live. * Log Responses WebSocket calls in history (diegosouzapw#3616) Integrated into release/v3.8.22 — Codex Responses WebSocket call history logging. * Add Claude Code routing preference for unprefixed Claude models (diegosouzapw#3540) Integrated into release/v3.8.22 — page.tsx conflict resolved (re-applied toggle to ProviderDetailPageClient) + disable-test updated for catalog drift in review. * docs(changelog): credit diegosouzapw#3632/diegosouzapw#3631/diegosouzapw#3637/diegosouzapw#3659/diegosouzapw#3540/diegosouzapw#3616/diegosouzapw#3523 (v3.8.22 targeted review round) * fix(mimocode): add required authHeader:"none" to registry entry (diegosouzapw#3659 follow-up) The mimocode RegistryEntry omitted the required authHeader field, which broke typecheck:core (TS2741). Match the no-auth convention (authType:"none" + authHeader:"none") used by veoaifree-web and other free providers. Follow-up to diegosouzapw#3659 (@pizzav-xyz). * fix(responses): detect stream readiness for tool-call-only and object-less chunks (diegosouzapw#3612) (diegosouzapw#3661) Closes diegosouzapw#3612 * fix(mitm): remove duplicated 'Command failed:' error prefix (diegosouzapw#3641) (diegosouzapw#3662) Closes diegosouzapw#3641 * fix(cli): honor HERMES_HOME for Hermes Agent config path (diegosouzapw#3628) (diegosouzapw#3663) Closes diegosouzapw#3628 * fix(api): fetch live OpenCode model catalog for no-auth model picker (diegosouzapw#3611) (diegosouzapw#3664) Closes diegosouzapw#3611 * fix(api): flag provider topology error state by current status, not stale history (diegosouzapw#3619) (diegosouzapw#3666) Closes diegosouzapw#3619 * fix(electron): launch peer-stamping server-ws.mjs entrypoint to avoid 403 LOCAL_ONLY (diegosouzapw#3386) (diegosouzapw#3665) Closes diegosouzapw#3386 * fix(dashboard): restore home topology live in-flight pulse (diegosouzapw#3507) (diegosouzapw#3667) Closes diegosouzapw#3507 * fix(oauth): name Kiro/AWS auto-imported accounts and dedupe by profileArn (diegosouzapw#3615) (diegosouzapw#3671) Closes diegosouzapw#3615 * fix(resilience): clear stale transient connection cooldowns on startup (diegosouzapw#3625) (diegosouzapw#3672) Closes diegosouzapw#3625 * fix(i18n): use logical CSS direction utilities for sidebar and key overlays (RTL diegosouzapw#3541) (diegosouzapw#3670) Closes diegosouzapw#3541 * fix(dashboard): honor auto-hide and switch to visible filter on passthrough Test-all (diegosouzapw#3610) (diegosouzapw#3669) Closes diegosouzapw#3610 * refactor(dashboard): extract AddApiKeyModal + EditConnectionModal — diegosouzapw#3501 Phase 1c (diegosouzapw#3674) diegosouzapw#3501 Phase 1c: extract AddApiKeyModal, EditConnectionModal, WebSessionCredentialGuide into components/; god-component 10,166->8,092 LOC. Reconciles the v3.8.22 file-size drift for this file. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * docs(changelog): reconcile v3.8.22 — credit diegosouzapw#3621/diegosouzapw#3622 + MiMoCode follow-up roll-up * refactor(dashboard): extract ConnectionRow + ModelCompatPopover + SiliconFlowEndpointModal — diegosouzapw#3501 Phase 1d (diegosouzapw#3676) diegosouzapw#3501 Phase 1d: god-component 8,092->6,838 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * feat(obsidian): add WebDAV config route + encrypt creds at rest (diegosouzapw#3485 part 1) (diegosouzapw#3677) Part 1 of diegosouzapw#3485. Adds /api/settings/obsidian/webdav (GET/POST/DELETE) wiring the ready obsidianSync lib, encrypts webdav password + obsidian token at rest, removes the duplicate UI block, drops the KNOWN_MISSING entry. WebDAV file server is part 2. * feat(obsidian): add /api/v1/webdav file server for Obsidian vault sync (diegosouzapw#3485 part 2) (diegosouzapw#3678) Part 2 of diegosouzapw#3485. WebDAV server (PROPFIND/GET/PUT/DELETE/MKCOL/MOVE/OPTIONS) handled in the custom server layer (standalone-server-ws.mjs) since the App Router cannot export WebDAV methods. Basic-Auth (constant-time), path-traversal hardened, password decrypt ported from encryption.ts (parity-tested), DATA_DIR resolution parity-tested against dataPaths.ts. End-to-end Obsidian-over-Tailscale validation is a live VPS step (Rule diegosouzapw#18). * fix(combo): stop premature context compaction — real auto-combo windows + per-target compression limit (diegosouzapw#3680) Integrated into release/v3.8.22 * feat(dashboard): deactivate/activate accounts from the quota overview (diegosouzapw#3675) Integrated into release/v3.8.22 * fix(dashboard): close review gaps in bulk provider connection actions (diegosouzapw#3271 follow-up) (diegosouzapw#3673) Integrated into release/v3.8.22 — page.tsx conflict (god-component split diegosouzapw#3501) resolved by re-applying the bulk-action deltas to ProviderDetailPageClient.tsx * refactor(dashboard): extract useModelCompatState hook + model sections — diegosouzapw#3501 Phase 1e (diegosouzapw#3683) diegosouzapw#3501 Phase 1e: extract useModelCompatState hook (unblocks the model sections) + ModelRow/PassthroughModelsSection/PassthroughModelRow/CustomModelsSection/CompatibleModelsSection. god-component 6,838->4,921 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract useProviderConnections/Settings/Models hooks — diegosouzapw#3501 Phase 1f (diegosouzapw#3684) diegosouzapw#3501 Phase 1f: god-component 4,948->4,062 LOC. Connection state+handlers, settings, and model metadata moved into hooks/. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * chore(release): v3.8.22 CHANGELOG + env-doc sync - Set release date in CHANGELOG [3.8.22] to 2026-06-11 - Add HERMES_HOME to .env.example (from diegosouzapw#3628/diegosouzapw#3663) - Add HERMES_HOME + OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS to ENVIRONMENT.md (diegosouzapw#3628/diegosouzapw#3540) * docs(changelog): credit diegosouzapw#3673 + diegosouzapw#3675 — leninejunior bulk-actions + quota-toggle --------- Co-authored-by: oyi77 <oyi77@users.noreply.github.com> Co-authored-by: Abhishek Divekar <adivekar@utexas.edu> Co-authored-by: NOXX - Commiter <artur1992123@mail.ru> Co-authored-by: Nicolas Lorin <androw95220@gmail.com> Co-authored-by: Hernan Javier Ardila Sanchez <hjasgr@gmail.com> Co-authored-by: PizzaV <103120356+pizzav-xyz@users.noreply.github.com> Co-authored-by: kkkayye <98376609+kkkayye@users.noreply.github.com> Co-authored-by: Witroch4 <witalo_rocha@hotmail.com> Co-authored-by: Lenine Júnior <lenine@engrene.com.br>
Release v3.8.22 —
release/v3.8.22→main. Living release notes — finalized at release time.[3.8.22] — 2026-06-11
✨ Added
mimocode(aliasmcode) exposing Xiaomi'smimo-automodel (1M context) via device-fingerprint bootstrap-JWT auth (/api/free-ai/bootstrap→ Bearer JWT →/api/free-ai/openai/chat). Supports multiple accounts (N fingerprints → round-robin with exponential cooldown), re-bootstrap on 401/403, and cooldown on 429. Reuses a new genericNoAuthAccountCarddashboard component (also wired foropencode). 22 unit tests; upstream validated live during review. (Maintainer follow-up: added the requiredauthHeader: "none"field to the registry entry.) Co-authored with @pizzav-xyz.claude-*model IDs ([Add Claude Code routing preference for unprefixed Claude models #3540] — thanks @Witroch4): opt-in setting (default off) that routes bareclaude-*model IDs from Claude Code clients through the Claude Code OAuth account instead of requiring a provider prefix. Configurable via theOMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELSenv flag or a dashboard toggle on the Claude provider page; explicit provider prefixes still win. Full layer coverage (resolver + DB setting + zod schemas + types + UI) with 6 tests. Co-authored with @Witroch4./v1/responsesWebSocket calls are now persisted to request history — success completions plus prepare-failures, upstream WS errors and premature closes — withsanitizeErrorMessageapplied to the stored error. Two proxy-side integration tests cover the success and failure paths./api/v1/webdavfile server (PROPFIND/GET/PUT/DELETE/MKCOL/MOVE, Basic-Auth, path-traversal hardened) so Obsidian mobile can sync the vault ([quality-gate] ObsidianSourceCard calls non-existent /api/settings/obsidian/webdav (404) #3485, part 2). Implemented in the custom server layer (scripts/dev/webdav-handler.mjs) — intercepted before Next.js to support non-standard HTTP methods (PROPFIND,MKCOL,MOVE,LOCK). Reads vault path and credentials (with enc:v1: AES-256-GCM decryption) directly from the SQLitekey_valuetable; credentials configured via PR1's/api/settings/obsidian/webdavendpoint. 36 TDD unit tests covering traversal guard, constant-time auth, decrypt round-trip, XML generation, and full CRUD cycle.♻️ Code Quality
providers/[id]: extract
useProviderConnections,useProviderSettings,useProviderModelshooks from the god-component — [refactor] Decompose providers/[id]/page.tsx god-component (12,882 LOC → ≤800, phased/strangler) #3501 Phase 1f.ProviderDetailPageClient.tsx: 4,948 → 4,063 LOC (−885 lines). New hooks inhooks/:useProviderConnections.ts(954 LOC — all connection management, batch ops, proxy/CLIProxyAPI state, batch-test runner with MAX_BULK_IDS chunking),useProviderSettings.ts(264 LOC — Codex global service mode + Claude routing preference),useProviderModels.ts(155 LOC — model metadata, aliases). Frozen baselines updated. 10 Phase-1f smoke tests; typecheck/cycles/lint green. Co-authored with @oyi77.providers/[id]: extract
useModelCompatStatehook + model sections (ModelRow,PassthroughModelRow,PassthroughModelsSection,CustomModelsSection,CompatibleModelsSection) from the god-component — [refactor] Decompose providers/[id]/page.tsx god-component (12,882 LOC → ≤800, phased/strangler) #3501 Phase 1e.ProviderDetailPageClient.tsx: 6,838 → 4,922 LOC (−1,916 lines). New leafhooks/useModelCompatState.ts(101 LOC); compat helpers moved toproviderPageHelpers.ts. Frozen baselines:providerPageHelpers.ts: 822. 12 Phase-1e smoke tests; typecheck/cycles/lint green; [BUG] The "Auto-hide failed models" option has been selected. Clicking the "Test all models" button will not automatically hide the incorrect models. (OpenCode Free supplier) #3610 auto-hide fix preserved.providers/[id]: extract
ConnectionRow(+CooldownTimer/inferErrorType/getStatusPresentation),ModelCompatPopover(+recordToHeaderRows), andSiliconFlowEndpointModalfrom the god-component intocomponents/— [refactor] Decompose providers/[id]/page.tsx god-component (12,882 LOC → ≤800, phased/strangler) #3501 Phase 1d.ProviderDetailPageClient.tsx: 8,092 → 6,838 LOC (−1,254 lines). Frozen baselines:ConnectionRow.tsx: 941. 7 new Phase-1d smoke tests; typecheck/cycles/lint green.providers/[id]: extract AddApiKeyModal + EditConnectionModal (+ WebSessionCredentialGuide) from the god-component into components/ ([[refactor] Decompose providers/[id]/page.tsx god-component (12,882 LOC → ≤800, phased/strangler) #3501] Phase 1c): extracted the two heaviest inline modals —
AddApiKeyModal(~787-LOC body) andEditConnectionModal(~1091-LOC body) — plus sharedWebSessionCredentialGuide(~103 LOC) into standalone files underproviders/[id]/components/modals/andproviders/[id]/components/respectively. AddedERROR_TYPE_LABELSandformatTimeAgotoproviderPageHelpers.ts(leaf) soEditConnectionModalandConnectionRowshare them without cycles. Pruned 14 now-unused imports from the god-component.ProviderDetailPageClient.tsx: 9,981 → 8,092 LOC (−1,889 lines). Frozen baselines:AddApiKeyModal.tsx: 842,EditConnectionModal.tsx: 1170. 6 new Phase-1c smoke tests; all 21 vitest modal tests pass; typecheck/cycles/lint green.refactor: small db/utils cleanup ([refactor: small code cleanup #3523] — thanks @androw): table-driven
compression_analyticscolumn migration (replaces 17 repeatedALTER TABLEcalls), a single mergedserializeJsonFieldhelper indb/providers.ts(folded two byte-identical serializers), and removal of the dead no-opsyncProviderDataToCloud/getProvidersNeedingRefreshstubs fromshared/utils/machine.ts(no remaining callers). Pure refactor; behavior unchanged.Provider-detail god-component decomposition — Phase 2b (remaining shared helpers→leaf) ([[refactor] Decompose providers/[id]/page.tsx god-component (12,882 LOC → ≤800, phased/strangler) #3501]): extended
providers/[id]/providerPageHelpers.tswith all remaining pure helpers needed by the heavy modals (AddApiKeyModal/EditConnectionModal) before they can be extracted. Moved 22 symbols: web-session credential label/hint/check/title helpers; upstream-headers helpers (upstreamHeadersRecordsEqual,headerRowsToRecord,effectiveUpstreamHeadersForProtocol,anyUpstreamHeadersBadge,getProtoSlice) plus theirHeaderDraftRow/CompatModelRow/CompatModelMap/CompatByProtocolMaptypes; Codex consts and helpers (CODEX_REASONING_STRENGTH_OPTIONS,CODEX_ACCOUNT_SERVICE_TIER_VALUES,CODEX_GLOBAL_SERVICE_MODE_VALUES,getCodexServiceTierLabel,normalizeCodexLimitPolicy,getCodexRequestDefaults,getClaudeCodeCompatibleRequestDefaults); misc helpers (compatProtocolLabelKey,extractCommandCodeCredentialInput,normalizeAndValidateHttpBaseUrl,SILICONFLOW_ENDPOINTS,CommandCodeAuthFlowState). New transitive imports wired into the leaf:MODEL_COMPAT_PROTOCOL_KEYS(@/shared/constants/modelCompat),CodexServiceTier/getCodexRequestDefaults/getClaudeCodeCompatibleRequestDefaults(@/lib/providers/requestDefaults),CodexGlobalServiceMode(@/lib/providers/codexFastTier),WebSessionCredentialRequirement(./webSessionCredentials).ProviderDetailPageClient.tsx: 10,288 → 9,980 LOC. Leaf module: 589 LOC (acyclic). 25-assertion unit test suite passes; smoke test 3/3; no import cycles. Co-authored with @oyi77.Provider-detail god-component decomposition — Phase 2 (helpers→lib) ([[refactor] Decompose providers/[id]/page.tsx god-component (12,882 LOC → ≤800, phased/strangler) #3501]): extracted the pure shared helpers —
ProviderMessageTranslator/LocalProviderMetadatatypes,providerText/providerCountText/readBooleanToggle, and the provider base-URL + routing-tag/excluded-model parse/format block — into a new leafproviders/[id]/providerPageHelpers.ts(imports only@/shared, so the client and modals share them with no import cycle).ProviderDetailPageClient.tsx: 10,435 → 10,288 LOC. Unblocks extracting the heavierAddApiKeyModal/EditConnectionModal(which depend on these helpers) without cycling. The Phase 0 smoke test caught a missing transitive import (isSelfHostedChatProvider) at mount — now wired + locked by a new helpers unit test (12 assertions). Co-authored with @oyi77.[quality-gate] Rule #5: 15 API routes contain raw SQL (should live in src/lib/db/) #3500 fully resolved — Hard Rule fix(oauth): prevent duplicate connections on re-authentication #5 (no raw SQL in route handlers): all 13 internal offenders migrated to
src/lib/db/modules across slices (calllogs, usage_history/daily_usage_summary, community_servers, usage_logs, semantic_cache, proxy_logs, skills UPDATE, db-backups). The gate'sKNOWN_RAW_SQLset is renamed toEXTERNAL_DB_ALLOWED(with a back-compat alias) and now holds only the 2 external-DB reads (oauth/cursor/auto-import,oauth/kiro/auto-import) — these open _another app's SQLite to import credentials, so by design they cannot live in OmniRoute'sdb/domain. The gate still blocks any NEW raw SQL against OmniRoute's DB.chore(db-gate): reclassify
KNOWN_UNEXPORTED→INTENTIONALLY_INTERNALinscripts/check/check-db-rules.mjs([[quality-gate] Rule #2: localDb.ts missing re-exports for 25 db modules #3499]): a full audit of all 25 db modules confirmed each is consumed via direct/dynamic import per Hard Rule build(deps): bump actions/github-script from 7 to 8 #2 ("Never barrel-import from localDb.ts"). The old framing labelled them as "debt", which was misleading — they are the correct pattern. The gate's blocking behaviour is unchanged (a NEW unexported module still fails); only the name, comments, and per-module justifications were updated to reflect audited truth. Four modules flaggedDEAD?(compressionScheduler,discovery,pluginMetrics,prompts) have zero production importers and are documented as schema-reserved. A new regression-guard test (tests/unit/check-db-rules-classification.test.ts) asserts every non-dead module in the set has ≥1 real importer, so a future consumer removal surfaces as a test failure requiring explicit reclassification.refactor(db): move
call_logsaggregations intocallLogStatsdb module ([[quality-gate] Rule #5: 15 API routes contain raw SQL (should live in src/lib/db/) #3500]): extracted raw SQL from three route handlers (/api/provider-metrics,/api/search/stats,/api/v1/search/analytics) into a newsrc/lib/db/callLogStats.tsdomain module (getProviderMetrics,getSearchProviderStats,getRecentSearchLogs,getSearchAggregateStats,getSearchProviderCounts). First slice of [quality-gate] Rule #5: 15 API routes contain raw SQL (should live in src/lib/db/) #3500 (call_logs cluster). Behavior unchanged; the three routes are removed fromKNOWN_RAW_SQLin the gate. Validated with TDD unit tests (6 assertions seeding an in-memory SQLite fixture).refactor(db): move
usage_history/daily_usage_summarySQL intousageAnalyticsdb module ([[quality-gate] Rule #5: 15 API routes contain raw SQL (should live in src/lib/db/) #3500]): extracted all inlinedb.prepare(...)calls from two route handlers (/api/usage/analytics,/api/settings/export-json) into a newsrc/lib/db/usageAnalytics.tsmodule and extendedsrc/lib/db/callLogStats.tswithgetFallbackStats. New exports:buildUnifiedSource,buildPresetUnifiedSource(UNION CTE builders), plus 12 typed query functions covering summary, daily, daily-cost, heatmap, model, provider, account, api-key, service-tier, weekly-pattern, and preset-cost aggregations, plusgetAllUsageHistory/getAllDomainCostHistory/getAllDomainBudgetsfor backup export. Second slice of [quality-gate] Rule #5: 15 API routes contain raw SQL (should live in src/lib/db/) #3500.KNOWN_RAW_SQLdrops from 12 → 10. Validated with 21 TDD unit tests (tests/unit/db-usage-analytics-3500.test.ts) seeding a temp SQLite fixture.refactor(db): move
community_serversauth look-up intogamificationdb module ([[quality-gate] Rule #5: 15 API routes contain raw SQL (should live in src/lib/db/) #3500]): extracted raw SQL from two federation route handlers (/api/gamification/federation/leaderboard,/api/gamification/federation/score) into a newgetConnectedServerByKeyHash(apiKeyHash)function insrc/lib/db/gamification.ts. Third slice of [quality-gate] Rule #5: 15 API routes contain raw SQL (should live in src/lib/db/) #3500 (gamification federation cluster). Behavior unchanged; the two routes are removed fromKNOWN_RAW_SQLin the gate. Validated with TDD unit tests (3 assertions seeding a temp SQLite fixture).refactor(db): move
skills UPDATE+db-backupsSQL into db modules ([[quality-gate] Rule #5: 15 API routes contain raw SQL (should live in src/lib/db/) #3500]): fifth slice of [quality-gate] Rule #5: 15 API routes contain raw SQL (should live in src/lib/db/) #3500. Extracted the dynamicUPDATE skills SET …fromsrc/app/api/skills/[id]/route.tsinto a newsrc/lib/db/skills.tsmodule (updateSkill(id, patch)). The dynamic SET clause is injection-safe: column names are validated against a hard-coded allowlist of known writable columns before being interpolated; unknown keys are silently ignored. Extendedsrc/lib/db/backup.tswith three new functions:exportAllSummaryRows()(multi-table SELECT for key_value / combos / provider_connections / api_keys, used by exportAll),getTableNamesFromAdapter()(sqlite_master introspection via an adapter arg, used by import validation), andcountImportedRows()(post-import COUNT(*) per table). The backup domain module is the correct home for sqlite_master introspection — it is not "raw SQL in a route" once moved there.KNOWN_RAW_SQLdrops by 3 (from 8 → 5). Validated with 11 TDD unit tests (tests/unit/db-backups-skills-3500.test.ts).refactor(db): move
usage_logs/semantic_cache/proxy_logsSQL into db modules ([[quality-gate] Rule #5: 15 API routes contain raw SQL (should live in src/lib/db/) #3500]): extracted rawdb.prepare(...)SQL from three route handlers (/api/analytics/auto-routing→usageLogs.ts;/api/cache/entries→semanticCache.ts;/api/logs/export→proxyLogs.ts) into newsrc/lib/db/domain modules. New exports:getAutoRoutingTotalCount,getAutoRoutingVariantBreakdown,getAutoRoutingTopProviders(usage_logs),listSemanticCacheEntries,deleteSemanticCacheBySignature,deleteSemanticCacheByModel(semantic_cache), andexportProxyLogsSince(proxy_logs). Fourth slice of [quality-gate] Rule #5: 15 API routes contain raw SQL (should live in src/lib/db/) #3500.KNOWN_RAW_SQLdrops from 8 → 5. Validated with 13 TDD unit tests (tests/unit/db-logs-cache-3500.test.ts) seeding temp SQLite fixtures.Provider-detail god-component decomposition — Phase 0 ([[refactor] Decompose providers/[id]/page.tsx god-component (12,882 LOC → ≤800, phased/strangler) #3501]): introduced
ProviderDetailPageClient.tsxand reducedproviders/[id]/page.tsxto a thin 9-line route wrapper (was 12,882 LOC), following the repo's*PageClientconvention. Added the first-ever smoke render test for the page (Hard Rule fix(oauth): prevent connection test from corrupting valid tokens #8) as the safety net every later extraction phase is diffed against. Behavior unchanged; thecheck-file-sizeratchet now tracks the extracted client. Foundation for Phases 1–6 (strangler-fig). Thanks @oyi77 for the parallel modularization effort in refactor: modularize 12.8K-line providers/[id]/page.tsx (Issue #3594) #3627.Provider-detail god-component decomposition — Phase 1a ([[refactor] Decompose providers/[id]/page.tsx god-component (12,882 LOC → ≤800, phased/strangler) #3501]): extracted the three self-contained auth-import modal clusters (Codex/Claude/Gemini
Import*AuthModal+Apply*AuthModal+ their co-located helpers, ~2,160 LOC) intoproviders/[id]/components/modals/.ProviderDetailPageClient.tsxdrops 12,882 → 10,719 LOC. Behavior unchanged (smoke test green; clusters had clean{ onClose, onSuccess }/ inline-prop interfaces). Co-authored with @oyi77.Provider-detail god-component decomposition — Phase 1b ([[refactor] Decompose providers/[id]/page.tsx god-component (12,882 LOC → ≤800, phased/strangler) #3501]): extracted
EditCompatibleNodeModal(+ its node/props types) intoproviders/[id]/components/modals/, and moved the sharedCC_COMPATIBLE_DEFAULT_CHAT_PATHconstant into a leafproviderDetailConstants.tsso the page client and the modal can both import it without a circular dependency. Also removed two dangling section comments left by Phase 1a.ProviderDetailPageClient.tsx: 10,719 → 10,435 LOC. Behavior unchanged (smoke test + a new standalone modal render test green;check:cyclesclean). Co-authored with @oyi77.🔧 Bug Fixes
Combos / Auto-Combo: premature context compaction ("agent keeps forgetting things") ([fix(combo): stop premature context compaction — real auto-combo windows + per-target compression limit #3680]): two related context-window bugs fixed. (1)
GET /api/combos/autonow advertisescontext_length/max_output_tokens(MAX across the candidate pool — safe because the auto-combo context pre-filter routes oversized requests to large-window candidates), and the opencode plugin consumes them instead of hardcodinglimit: { context: 0 }— a zero context silently disables opencode's smart auto-compaction, letting sessions grow until the gateway's destructive history purge kicks in. (2) chatCore's proactive compression for DB combos (incl. quota-shared pools) no longer compresses atmin(...allTargets): it now uses the EXECUTING target's own window (resolveComboContextLimit), keeping min-of-targets only as a defensive fallback when the current provider/model resolves no specific limit. TDD: 8 server tests (tests/unit/auto-combo-context-advertising.test.ts) + 3 plugin tests (tests/auto-combo-context.test.ts).Obsidian/WebDAV: add the
/api/settings/obsidian/webdavconfig route (enable/disable vault sync), encrypt WebDAV credentials at rest, and remove the duplicate UI block ([quality-gate] ObsidianSourceCard calls non-existent /api/settings/obsidian/webdav (404) #3485, part 1).OpenCode Free / passthrough: "Test all models" now respects "Auto-hide failed models" and switches the list to the visible filter so hidden models actually disappear ([BUG] The "Auto-hide failed models" option has been selected. Clicking the "Test all models" button will not automatically hide the incorrect models. (OpenCode Free supplier) #3610). Three related bugs fixed:
autoHideFailedis now threaded from the outer component intoPassthroughModelsSectionvia a prop (single shared checkbox); the/api/models/test-allrequest body now includesautoHideFailed: trueso the server persists the hide; and after the loop,visibilityFilteris switched to"visible"when ≥1 model was hidden. Two pure-function helpers (buildPassthroughTestBody,shouldSwitchToVisibleFilter) extracted toproviderPageHelpers.tswith 7 unit tests.Resilience: clear stale transient connection cooldowns on startup so a prior unclean crash no longer makes every request time out at 120s after restart ([BUG] [BUG] Process crash on large request bodies leaves upstream connection broken after restart — all subsequent requests timeout at 120s #3625)
fix(home topology): restore live in-flight request pulse ([Re-wire home ProviderTopology live pulse to the unified requests source (post #3401) #3507]): the animated "pulse" edges in the home Provider Topology panel went dead after PR feat(ui): unifi active and finished requests into single view #1422 #3401 unified request visibility, because
activeRequestswas hardcoded to[]. Re-wired touseLiveRequests()(the existing WebSocket hook on port 20129) so that every pending/running request drives the animation in real time. A pureselectActiveRequestsmapping helper was extracted tohome/topologyUtils.tswith 5 unit tests.Electron desktop: launch the peer-stamping
server-ws.mjsentrypoint so local-only routes (AgentBridge, MCP, services) no longer return 403 LOCAL_ONLY ([Bug]: AgentBridge fail to start due to403 LOCAL_ONLYon Linux Desktop Client (Debian 13 ARM64) #3386)Provider Topology: stop flagging healthy providers as errored based on stale historical failures; use current request status ([BUG] Provider Topology map displays persistent error state (red border) for healthy providers after historical failures #3619)
OpenCode Free: fetch the live model catalog from the provider's
modelsUrlfor the no-auth model picker instead of serving a stale hardcoded list ([BUG] Clicking the "From /model" option displays a list of models that are not the latest ones. (OpenCode Free supplier) #3611)Hermes Agent: honour the
HERMES_HOMEenv var when writing/reading the agent config instead of always using~/.hermes(Hermes Agent config ignores HERMES_HOME — written to ~/.hermes instead of the active config dir #3628). IntroducedgetHermesHome()/getHermesConfigPath()helpers (read at call-time) and routed all four hardcoded callsites through them so OmniRoute's config lands in the same directory that the Hermes PowerShell installer configures on Windows.MITM/cert: remove the duplicated "Command failed:" prefix in system-command error messages (#3641):
execFileTextwas prepending its own"Command failed: "prefix on top of Node'sexecFileerror message, which already begins with"Command failed: <cmd>"for non-zero exits. The error message now surfaces Node's message directly (no double prefix), with stderr appended only when non-empty.fix(reasoning): replay
reasoning_contenton plain DeepSeek turns ([fix(reasoning): replay reasoning_content on plain DeepSeek turns (#1682) #3632] — thanks @adivekar-utexas): the reasoning-replay gate previously only fired when an assistant message already carriedreasoning_content. Plain (non-tool-call) turns whosereasoning_contentwas stripped by the client (e.g. Cursor) were forwarded without it, so DeepSeek V4+ rejected the request with 400 "the reasoning_content in the thinking mode must be passed back". The gate now also covers missing/emptyreasoning_contenton DeepSeek replay targets, injecting the cached reasoning (or the non-Anthropic placeholder) so multi-turn text conversations no longer 400. Fixes [BUG] Reasoning replay cache only covers tool_calls messages — DeepSeek 400 on plain assistant turns #1682. 2 regression tests.fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint ([fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint #3631] — thanks @artickc): Kiro/CodeWhisperer access tokens and Q Developer profile ARNs are region-bound, so enterprise IAM Identity Center accounts outside
us-east-1(e.g.eu-central-1) were rejected by the default host. AddsresolveKiroRegion(stored region → profileArn region →us-east-1) andkiroRuntimeHost(regionalq.{region}.amazonaws.com, legacycodewhisperer.us-east-1for the default), routes chat + usage to the regional endpoint, and discovers the region-matchedprofileArnviaListAvailableProfilesin a best-effortpostExchangehook. 9 tests.fix(combo): skip same-provider/connection targets on connection-level errors ([fix(combo): skip same-provider targets on 408/500/502/503/504/524 errors #3637] — thanks @herjarsa): on connection-level upstream errors (408/500/502/503/504/524), remaining same-
provider:connectiontargets in a combo request are now skipped to avoid hammering a known-bad connection, in both the priority and round-robin paths. Adjusted in review to exclude OmniRoute circuit-breaker-open responses (503 +X-OmniRoute-Provider-Breaker/provider_circuit_open) from this skip, preserving the invariant that a breaker-open is an ordinary target failure (the next same-provider target is still tried). Co-authored with @herjarsa./v1/responses: detect stream readiness for tool-call-only and
object-less chunks so Codex-shaped (reasoning + tools) requests no longer fail with "Stream ended before producing useful content" ([BUG] v3.8.19 /v1/responses: Codex-shaped requests (reasoning + tools) fail 'Stream ended before producing useful content'; bare requests succeed #3612)RTL locales (ar/fa/he/ur): use logical CSS direction utilities for the sidebar and key overlays so the layout mirrors correctly under
dir=rtl([BUG] The internationalization translation was done very poorly. #3541, partial — core layout)Kiro/AWS auto-import: set a descriptive account name and dedupe by
profileArnso imports no longer create nameless duplicate "OAuth Account" rows ([BUG] Auto-imported Kiro/AWS credentials create anonymous "OAuth Account" with empty name #3615)fix(guardrails): the
/api/guardrails/testroute now validates its body throughvalidateBody()(Zod) instead of parsing raw JSON directly, aligning it with the repo-wide input-validation pattern (Hard Rule chore(env): sync .env.example with current .env structure #7). (#3621 — thanks @diegosouzapw)fix(dashboard): bulk provider connection actions — close audit, API, and UX gaps in the batch activate/deactivate flow: register the
provider.credentials.batch_updatedevent inHIGH_LEVEL_ACTIONSandACTIVITY_ICONS(was silently dropped from the Activity feed); fix/api/providersPATCH to returnwarnstatus whennotFoundis non-empty instead of alwayssuccess;/api/providers/test-batchempty-result early-return now includes asummaryso stale-ID mode reports to the user; bulk activate/deactivate chunks selection by 100 to avoid the Zod 400 cap on large provider accounts. (#3673 — thanks @leninejunior)📝 Maintenance
execFileSyncmaxBufferinvalidate-pack-artifactso the npm-pack inventory no longer overflows on large tarballs during release validation — follow-up to the v3.8.21 pack-artifact hotfix. (#3622 — thanks @diegosouzapw)🙌 Contributors
Thanks to everyone whose work lands in v3.8.22: