Skip to content

fix(combo): skip same-provider targets on 408/500/502/503/504/524 errors - #3637

Merged
diegosouzapw merged 5 commits into
cheaper-inference:release/v3.8.22from
herjarsa:fix/1731v2-exhausted-connections
Jun 11, 2026
Merged

diegosouzapw merged 5 commits into
cheaper-inference:release/v3.8.22from
herjarsa:fix/1731v2-exhausted-connections

Conversation

@herjarsa

Copy link
Copy Markdown
Contributor

Problem

When a combo has multiple models from the same provider and one returns a connection-level error (408/500/502/503/504/524), the combo engine continues trying every remaining target from the same provider one-by-one, each wasting time before eventually failing.

Solution

Add a per-request exhaustedConnections Set (keyed by provider:connectionId) that marks a provider connection as exhausted when a target fails with a connection-level error. Subsequent targets with the same provider:connectionId are skipped immediately.

Changes

  • Priority path (combo.ts): Add exhaustedConnections skip check before existing exhaustedProviders check; mark connection on 408/500/502/503/504/524
  • Round-robin path (combo.ts): Same pattern
  • Network errors (DNS, ECONNREFUSED): Already converted to 502 by handleSingleModelWithTimeout's .catch() — covered automatically
  • 429 and 499: Handled separately (transientRateLimitedProviders and immediate combo stop) — not affected

Tests

  • Updated 2 circuit-breaker test assertions (now expect 2nd same-provider target to be skipped)
  • 75/75 tests passing
  • typecheck:core clean

Verification

ℹ tests 75
ℹ pass 75
ℹ fail 0

diegosouzapw and others added 2 commits June 11, 2026 05:46
…xpansion (cheaper-inference#3624)

v3.8.21 broadened package.json files to include open-sse/ and src/*/*
directories for TypeScript-first imports, but pack-artifact-policy.ts
was not updated. Add the new directories to PACK_ARTIFACT_ROOT_ALLOWED_PATH_PREFIXES.
Also increase execFileSync maxBuffer to 64 MB to fix ENOBUFS on large packs.
Add connection-granular exhaustion tracking (exhaustedConnections Set)
that marks provider:connectionId as exhausted when a target returns
connection-level errors. Remaining same-provider targets are skipped
immediately instead of being tried one-by-one.

Changes:
- Priority path: skip exhausted connections before provider-check
- Round-robin path: same pattern
- Both paths: mark connection exhausted on 408/500/502/503/504/524
- Network errors (DNS, ECONNREFUSED) covered via .catch() → 502
- Tests updated for new skip behavior (75/75 passing)
@herjarsa
herjarsa requested a review from diegosouzapw as a code owner June 11, 2026 12:09

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces connection-level error tracking to skip remaining targets on a known-bad connection (e.g., 502/503/504 errors) for both standard and round-robin combo routing. However, the accompanying unit tests were updated to assert failure because both test models share the same provider, bypassing the fallback logic. The reviewer suggests updating the second model in these tests to a different provider to properly verify that fallback still occurs for circuit breaker responses.

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.

Comment thread tests/unit/combo-routing-engine.test.ts Outdated
Comment on lines +2102 to +2103
assert.equal(result.ok, false);
assert.deepEqual(calls, ["openai/model-a"]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test is named "handleComboChat treats provider circuit breaker responses as ordinary target failures". Its purpose is to verify that when a target returns a circuit breaker response (503), the engine treats it as a non-fatal failure and successfully falls back to the next target.\n\nHowever, because both models in the test are on the same provider (openai/model-a and openai/model-b), the new same-provider connection-level error skip logic immediately skips openai/model-b. As a result, the test now asserts result.ok is false and calls is ["openai/model-a"], which means it no longer verifies that fallback actually occurs for circuit breaker responses.\n\nTo preserve the original intent of the test while keeping the new skip logic, please change the second model in the test setup (line 2085) to a different provider (e.g., "anthropic/model-b"), and then assert that result.ok is true and calls contains both models.

Comment thread tests/unit/combo-routing-engine.test.ts Outdated
Comment on lines +2631 to +2632
assert.equal(result.ok, false);
assert.deepEqual(calls, ["openai/model-a"]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the priority strategy test above, this round-robin test is named "handleComboChat round-robin treats provider circuit breaker responses as ordinary target failures". Because both models are on the same provider (openai), the second model is skipped, and the test no longer verifies that round-robin fallback actually succeeds for circuit breaker responses.\n\nPlease change the second model in the test setup (line 2621) to a different provider (e.g., "anthropic/model-b") and update the assertions to expect result.ok to be true and calls to be ["openai/model-a", "anthropic/model-b"].

…fallback verification

Per Gemini Code Assist review: use different provider for second model to
verify fallback still works across providers when one provider is exhausted.
openai/model-a fails -> openai marked exhausted -> anthropic/model-b still tried.
@diegosouzapw
diegosouzapw changed the base branch from main to release/v3.8.22 June 11, 2026 14:25
diegosouzapw and others added 2 commits June 11, 2026 11:37
…ip (#1731v2)

A provider circuit-breaker-open response (providerCircuitOpenResponse: 503 +
X-OmniRoute-Provider-Breaker: open / provider_circuit_open code) is an OmniRoute
resilience signal, not a per-connection upstream failure. The new #1731v2
connection-skip logic was catching its 503 status and poisoning
exhaustedProviders/exhaustedConnections, which wrongly skipped remaining
same-provider targets while the breaker was open — regressing the invariant that
breaker-open responses are treated as ordinary target failures.

Add isProviderCircuitOpenResult guard to both the priority and round-robin
connection-skip blocks. Revert the two circuit-breaker tests to use two
same-provider (openai) targets again, proving breaker-open does NOT skip
same-provider targets.

Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
@diegosouzapw
diegosouzapw merged commit 337f16c into cheaper-inference:release/v3.8.22 Jun 11, 2026
1 check failed
@diegosouzapw

Copy link
Copy Markdown
Collaborator

Merged into release/v3.8.22 — thanks @herjarsa! 🎉 The per-connection / per-provider skip on connection-level errors (408/500/502/503/504/524) is a solid improvement. During review I added one fix-in-place commit: a circuit-breaker guard. A provider circuit-breaker-open response is a 503 (X-OmniRoute-Provider-Breaker: open / provider_circuit_open), so the new skip logic was catching it and poisoning exhaustedProviders/exhaustedConnections — which would skip remaining same-provider targets while the breaker is open, regressing the invariant that breaker-open is an ordinary target failure. I added isProviderCircuitOpenResult to exclude it from both the priority and round-robin blocks, and reverted the two circuit-breaker tests to use two same-provider (openai) targets again so they prove breaker-open does NOT skip same-provider. Credited you as author + me as co-author. Shipping in the next release.

diegosouzapw added a commit that referenced this pull request Jun 11, 2026
@diegosouzapw diegosouzapw mentioned this pull request Jun 11, 2026
diegosouzapw added a commit that referenced this pull request Jun 11, 2026
* chore(release): open v3.8.22 development cycle

* refactor(dashboard): extract ProviderDetailPageClient — #3501 Phase 0 (#3633)

#3501 Phase 0: extract ProviderDetailPageClient + smoke test.

Co-authored-by: oyi77 <oyi77@users.noreply.github.com>

* refactor(dashboard): extract auth-import modals — #3501 Phase 1a (#3634)

#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 (#3499) (#3635)

Closes #3499 — reclassify localDb unexported modules as intentionally-internal (audit + honest gate framing).

* refactor(db): move call_logs aggregations into callLogStats db module (#3500) (#3636)

#3500 slice 1: call_logs aggregations → src/lib/db/callLogStats.ts (Rule #5). Byte-identical queries; TDD 6/6.

* refactor(dashboard): extract EditCompatibleNodeModal — #3501 Phase 1b (#3638)

#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 (#3500 slice 3) (#3639)

#3500 slice 3: community_servers SQL → gamification db module.

* refactor(db): move usage_history SQL into usageAnalytics module (#3500 slice 2) (#3644)

#3500 slice 2: usage_history/daily_usage_summary SQL → usageAnalytics db module.

* refactor(db): move skills UPDATE + db-backups SQL into db modules (#3500 slice 5) (#3647)

#3500 slice 5: skills UPDATE (allowlist) + db-backups SQL → db modules.

* refactor(db): move usage_logs/semantic_cache/proxy_logs SQL into db modules (#3500 slice 4) (#3648)

#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 #3500 (#3649)

Closes #3500: reclassify external-DB reads; all internal raw-SQL migrated to db/ modules.

* refactor(dashboard): extract pure helpers to providerPageHelpers — #3501 Phase 2 (#3653)

#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 — #3501 Phase 2b (#3658)

#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 (#1682) (#3632)

Integrated into release/v3.8.22

* fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint (#3631)

Integrated into release/v3.8.22

* refactor: small code cleanup (#3523)

Integrated into release/v3.8.22

* fix(combo): skip same-provider targets on 408/500/502/503/504/524 errors (#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 (#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 (#3616)

Integrated into release/v3.8.22 — Codex Responses WebSocket call history logging.

* Add Claude Code routing preference for unprefixed Claude models (#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 #3632/#3631/#3637/#3659/#3540/#3616/#3523 (v3.8.22 targeted review round)

* fix(mimocode): add required authHeader:"none" to registry entry (#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 #3659 (@pizzav-xyz).

* fix(responses): detect stream readiness for tool-call-only and object-less chunks (#3612) (#3661)

Closes #3612

* fix(mitm): remove duplicated 'Command failed:' error prefix (#3641) (#3662)

Closes #3641

* fix(cli): honor HERMES_HOME for Hermes Agent config path (#3628) (#3663)

Closes #3628

* fix(api): fetch live OpenCode model catalog for no-auth model picker (#3611) (#3664)

Closes #3611

* fix(api): flag provider topology error state by current status, not stale history (#3619) (#3666)

Closes #3619

* fix(electron): launch peer-stamping server-ws.mjs entrypoint to avoid 403 LOCAL_ONLY (#3386) (#3665)

Closes #3386

* fix(dashboard): restore home topology live in-flight pulse (#3507) (#3667)

Closes #3507

* fix(oauth): name Kiro/AWS auto-imported accounts and dedupe by profileArn (#3615) (#3671)

Closes #3615

* fix(resilience): clear stale transient connection cooldowns on startup (#3625) (#3672)

Closes #3625

* fix(i18n): use logical CSS direction utilities for sidebar and key overlays (RTL #3541) (#3670)

Closes #3541

* fix(dashboard): honor auto-hide and switch to visible filter on passthrough Test-all (#3610) (#3669)

Closes #3610

* refactor(dashboard): extract AddApiKeyModal + EditConnectionModal — #3501 Phase 1c (#3674)

#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 #3621/#3622 + MiMoCode follow-up roll-up

* refactor(dashboard): extract ConnectionRow + ModelCompatPopover + SiliconFlowEndpointModal — #3501 Phase 1d (#3676)

#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 (#3485 part 1) (#3677)

Part 1 of #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 (#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).

* fix(combo): stop premature context compaction — real auto-combo windows + per-target compression limit (#3680)

Integrated into release/v3.8.22

* feat(dashboard): deactivate/activate accounts from the quota overview (#3675)

Integrated into release/v3.8.22

* fix(dashboard): close review gaps in bulk provider connection actions (#3271 follow-up) (#3673)

Integrated into release/v3.8.22 — page.tsx conflict (god-component split #3501) resolved by re-applying the bulk-action deltas to ProviderDetailPageClient.tsx

* refactor(dashboard): extract useModelCompatState hook + model sections — #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>

* refactor(dashboard): extract useProviderConnections/Settings/Models hooks — #3501 Phase 1f (#3684)

#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 #3628/#3663)
- Add HERMES_HOME + OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS to ENVIRONMENT.md (#3628/#3540)

* docs(changelog): credit #3673 + #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>
@diegosouzapw diegosouzapw mentioned this pull request Jun 12, 2026
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
* chore(release): open v3.8.22 development cycle

* refactor(dashboard): extract ProviderDetailPageClient — cheaper-inference#3501 Phase 0 (cheaper-inference#3633)

cheaper-inference#3501 Phase 0: extract ProviderDetailPageClient + smoke test.

Co-authored-by: oyi77 <oyi77@users.noreply.github.com>

* refactor(dashboard): extract auth-import modals — cheaper-inference#3501 Phase 1a (cheaper-inference#3634)

cheaper-inference#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 (cheaper-inference#3499) (cheaper-inference#3635)

Closes cheaper-inference#3499 — reclassify localDb unexported modules as intentionally-internal (audit + honest gate framing).

* refactor(db): move call_logs aggregations into callLogStats db module (cheaper-inference#3500) (cheaper-inference#3636)

cheaper-inference#3500 slice 1: call_logs aggregations → src/lib/db/callLogStats.ts (Rule cheaper-inference#5). Byte-identical queries; TDD 6/6.

* refactor(dashboard): extract EditCompatibleNodeModal — cheaper-inference#3501 Phase 1b (cheaper-inference#3638)

cheaper-inference#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 (cheaper-inference#3500 slice 3) (cheaper-inference#3639)

cheaper-inference#3500 slice 3: community_servers SQL → gamification db module.

* refactor(db): move usage_history SQL into usageAnalytics module (cheaper-inference#3500 slice 2) (cheaper-inference#3644)

cheaper-inference#3500 slice 2: usage_history/daily_usage_summary SQL → usageAnalytics db module.

* refactor(db): move skills UPDATE + db-backups SQL into db modules (cheaper-inference#3500 slice 5) (cheaper-inference#3647)

cheaper-inference#3500 slice 5: skills UPDATE (allowlist) + db-backups SQL → db modules.

* refactor(db): move usage_logs/semantic_cache/proxy_logs SQL into db modules (cheaper-inference#3500 slice 4) (cheaper-inference#3648)

cheaper-inference#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 cheaper-inference#3500 (cheaper-inference#3649)

Closes cheaper-inference#3500: reclassify external-DB reads; all internal raw-SQL migrated to db/ modules.

* refactor(dashboard): extract pure helpers to providerPageHelpers — cheaper-inference#3501 Phase 2 (cheaper-inference#3653)

cheaper-inference#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 — cheaper-inference#3501 Phase 2b (cheaper-inference#3658)

cheaper-inference#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 (cheaper-inference#1682) (cheaper-inference#3632)

Integrated into release/v3.8.22

* fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint (cheaper-inference#3631)

Integrated into release/v3.8.22

* refactor: small code cleanup (cheaper-inference#3523)

Integrated into release/v3.8.22

* fix(combo): skip same-provider targets on 408/500/502/503/504/524 errors (cheaper-inference#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 (cheaper-inference#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 (cheaper-inference#3616)

Integrated into release/v3.8.22 — Codex Responses WebSocket call history logging.

* Add Claude Code routing preference for unprefixed Claude models (cheaper-inference#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 cheaper-inference#3632/cheaper-inference#3631/cheaper-inference#3637/cheaper-inference#3659/cheaper-inference#3540/cheaper-inference#3616/cheaper-inference#3523 (v3.8.22 targeted review round)

* fix(mimocode): add required authHeader:"none" to registry entry (cheaper-inference#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 cheaper-inference#3659 (@pizzav-xyz).

* fix(responses): detect stream readiness for tool-call-only and object-less chunks (cheaper-inference#3612) (cheaper-inference#3661)

Closes cheaper-inference#3612

* fix(mitm): remove duplicated 'Command failed:' error prefix (cheaper-inference#3641) (cheaper-inference#3662)

Closes cheaper-inference#3641

* fix(cli): honor HERMES_HOME for Hermes Agent config path (cheaper-inference#3628) (cheaper-inference#3663)

Closes cheaper-inference#3628

* fix(api): fetch live OpenCode model catalog for no-auth model picker (cheaper-inference#3611) (cheaper-inference#3664)

Closes cheaper-inference#3611

* fix(api): flag provider topology error state by current status, not stale history (cheaper-inference#3619) (cheaper-inference#3666)

Closes cheaper-inference#3619

* fix(electron): launch peer-stamping server-ws.mjs entrypoint to avoid 403 LOCAL_ONLY (cheaper-inference#3386) (cheaper-inference#3665)

Closes cheaper-inference#3386

* fix(dashboard): restore home topology live in-flight pulse (cheaper-inference#3507) (cheaper-inference#3667)

Closes cheaper-inference#3507

* fix(oauth): name Kiro/AWS auto-imported accounts and dedupe by profileArn (cheaper-inference#3615) (cheaper-inference#3671)

Closes cheaper-inference#3615

* fix(resilience): clear stale transient connection cooldowns on startup (cheaper-inference#3625) (cheaper-inference#3672)

Closes cheaper-inference#3625

* fix(i18n): use logical CSS direction utilities for sidebar and key overlays (RTL cheaper-inference#3541) (cheaper-inference#3670)

Closes cheaper-inference#3541

* fix(dashboard): honor auto-hide and switch to visible filter on passthrough Test-all (cheaper-inference#3610) (cheaper-inference#3669)

Closes cheaper-inference#3610

* refactor(dashboard): extract AddApiKeyModal + EditConnectionModal — cheaper-inference#3501 Phase 1c (cheaper-inference#3674)

cheaper-inference#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 cheaper-inference#3621/cheaper-inference#3622 + MiMoCode follow-up roll-up

* refactor(dashboard): extract ConnectionRow + ModelCompatPopover + SiliconFlowEndpointModal — cheaper-inference#3501 Phase 1d (cheaper-inference#3676)

cheaper-inference#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 (cheaper-inference#3485 part 1) (cheaper-inference#3677)

Part 1 of cheaper-inference#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 (cheaper-inference#3485 part 2) (cheaper-inference#3678)

Part 2 of cheaper-inference#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 cheaper-inference#18).

* fix(combo): stop premature context compaction — real auto-combo windows + per-target compression limit (cheaper-inference#3680)

Integrated into release/v3.8.22

* feat(dashboard): deactivate/activate accounts from the quota overview (cheaper-inference#3675)

Integrated into release/v3.8.22

* fix(dashboard): close review gaps in bulk provider connection actions (cheaper-inference#3271 follow-up) (cheaper-inference#3673)

Integrated into release/v3.8.22 — page.tsx conflict (god-component split cheaper-inference#3501) resolved by re-applying the bulk-action deltas to ProviderDetailPageClient.tsx

* refactor(dashboard): extract useModelCompatState hook + model sections — cheaper-inference#3501 Phase 1e (cheaper-inference#3683)

cheaper-inference#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 — cheaper-inference#3501 Phase 1f (cheaper-inference#3684)

cheaper-inference#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 cheaper-inference#3628/cheaper-inference#3663)
- Add HERMES_HOME + OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS to ENVIRONMENT.md (cheaper-inference#3628/cheaper-inference#3540)

* docs(changelog): credit cheaper-inference#3673 + cheaper-inference#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>
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
* chore(release): open v3.8.22 development cycle

* refactor(dashboard): extract ProviderDetailPageClient — cheaper-inference#3501 Phase 0 (cheaper-inference#3633)

cheaper-inference#3501 Phase 0: extract ProviderDetailPageClient + smoke test.

Co-authored-by: oyi77 <oyi77@users.noreply.github.com>

* refactor(dashboard): extract auth-import modals — cheaper-inference#3501 Phase 1a (cheaper-inference#3634)

cheaper-inference#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 (cheaper-inference#3499) (cheaper-inference#3635)

Closes cheaper-inference#3499 — reclassify localDb unexported modules as intentionally-internal (audit + honest gate framing).

* refactor(db): move call_logs aggregations into callLogStats db module (cheaper-inference#3500) (cheaper-inference#3636)

cheaper-inference#3500 slice 1: call_logs aggregations → src/lib/db/callLogStats.ts (Rule cheaper-inference#5). Byte-identical queries; TDD 6/6.

* refactor(dashboard): extract EditCompatibleNodeModal — cheaper-inference#3501 Phase 1b (cheaper-inference#3638)

cheaper-inference#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 (cheaper-inference#3500 slice 3) (cheaper-inference#3639)

cheaper-inference#3500 slice 3: community_servers SQL → gamification db module.

* refactor(db): move usage_history SQL into usageAnalytics module (cheaper-inference#3500 slice 2) (cheaper-inference#3644)

cheaper-inference#3500 slice 2: usage_history/daily_usage_summary SQL → usageAnalytics db module.

* refactor(db): move skills UPDATE + db-backups SQL into db modules (cheaper-inference#3500 slice 5) (cheaper-inference#3647)

cheaper-inference#3500 slice 5: skills UPDATE (allowlist) + db-backups SQL → db modules.

* refactor(db): move usage_logs/semantic_cache/proxy_logs SQL into db modules (cheaper-inference#3500 slice 4) (cheaper-inference#3648)

cheaper-inference#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 cheaper-inference#3500 (cheaper-inference#3649)

Closes cheaper-inference#3500: reclassify external-DB reads; all internal raw-SQL migrated to db/ modules.

* refactor(dashboard): extract pure helpers to providerPageHelpers — cheaper-inference#3501 Phase 2 (cheaper-inference#3653)

cheaper-inference#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 — cheaper-inference#3501 Phase 2b (cheaper-inference#3658)

cheaper-inference#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 (cheaper-inference#1682) (cheaper-inference#3632)

Integrated into release/v3.8.22

* fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint (cheaper-inference#3631)

Integrated into release/v3.8.22

* refactor: small code cleanup (cheaper-inference#3523)

Integrated into release/v3.8.22

* fix(combo): skip same-provider targets on 408/500/502/503/504/524 errors (cheaper-inference#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 (cheaper-inference#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 (cheaper-inference#3616)

Integrated into release/v3.8.22 — Codex Responses WebSocket call history logging.

* Add Claude Code routing preference for unprefixed Claude models (cheaper-inference#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 cheaper-inference#3632/cheaper-inference#3631/cheaper-inference#3637/cheaper-inference#3659/cheaper-inference#3540/cheaper-inference#3616/cheaper-inference#3523 (v3.8.22 targeted review round)

* fix(mimocode): add required authHeader:"none" to registry entry (cheaper-inference#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 cheaper-inference#3659 (@pizzav-xyz).

* fix(responses): detect stream readiness for tool-call-only and object-less chunks (cheaper-inference#3612) (cheaper-inference#3661)

Closes cheaper-inference#3612

* fix(mitm): remove duplicated 'Command failed:' error prefix (cheaper-inference#3641) (cheaper-inference#3662)

Closes cheaper-inference#3641

* fix(cli): honor HERMES_HOME for Hermes Agent config path (cheaper-inference#3628) (cheaper-inference#3663)

Closes cheaper-inference#3628

* fix(api): fetch live OpenCode model catalog for no-auth model picker (cheaper-inference#3611) (cheaper-inference#3664)

Closes cheaper-inference#3611

* fix(api): flag provider topology error state by current status, not stale history (cheaper-inference#3619) (cheaper-inference#3666)

Closes cheaper-inference#3619

* fix(electron): launch peer-stamping server-ws.mjs entrypoint to avoid 403 LOCAL_ONLY (cheaper-inference#3386) (cheaper-inference#3665)

Closes cheaper-inference#3386

* fix(dashboard): restore home topology live in-flight pulse (cheaper-inference#3507) (cheaper-inference#3667)

Closes cheaper-inference#3507

* fix(oauth): name Kiro/AWS auto-imported accounts and dedupe by profileArn (cheaper-inference#3615) (cheaper-inference#3671)

Closes cheaper-inference#3615

* fix(resilience): clear stale transient connection cooldowns on startup (cheaper-inference#3625) (cheaper-inference#3672)

Closes cheaper-inference#3625

* fix(i18n): use logical CSS direction utilities for sidebar and key overlays (RTL cheaper-inference#3541) (cheaper-inference#3670)

Closes cheaper-inference#3541

* fix(dashboard): honor auto-hide and switch to visible filter on passthrough Test-all (cheaper-inference#3610) (cheaper-inference#3669)

Closes cheaper-inference#3610

* refactor(dashboard): extract AddApiKeyModal + EditConnectionModal — cheaper-inference#3501 Phase 1c (cheaper-inference#3674)

cheaper-inference#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 cheaper-inference#3621/cheaper-inference#3622 + MiMoCode follow-up roll-up

* refactor(dashboard): extract ConnectionRow + ModelCompatPopover + SiliconFlowEndpointModal — cheaper-inference#3501 Phase 1d (cheaper-inference#3676)

cheaper-inference#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 (cheaper-inference#3485 part 1) (cheaper-inference#3677)

Part 1 of cheaper-inference#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 (cheaper-inference#3485 part 2) (cheaper-inference#3678)

Part 2 of cheaper-inference#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 cheaper-inference#18).

* fix(combo): stop premature context compaction — real auto-combo windows + per-target compression limit (cheaper-inference#3680)

Integrated into release/v3.8.22

* feat(dashboard): deactivate/activate accounts from the quota overview (cheaper-inference#3675)

Integrated into release/v3.8.22

* fix(dashboard): close review gaps in bulk provider connection actions (cheaper-inference#3271 follow-up) (cheaper-inference#3673)

Integrated into release/v3.8.22 — page.tsx conflict (god-component split cheaper-inference#3501) resolved by re-applying the bulk-action deltas to ProviderDetailPageClient.tsx

* refactor(dashboard): extract useModelCompatState hook + model sections — cheaper-inference#3501 Phase 1e (cheaper-inference#3683)

cheaper-inference#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 — cheaper-inference#3501 Phase 1f (cheaper-inference#3684)

cheaper-inference#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 cheaper-inference#3628/cheaper-inference#3663)
- Add HERMES_HOME + OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS to ENVIRONMENT.md (cheaper-inference#3628/cheaper-inference#3540)

* docs(changelog): credit cheaper-inference#3673 + cheaper-inference#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>
tkgo11 pushed a commit to tkgo11/OmniRoute that referenced this pull request Sep 23, 2026
…ors (cheaper-inference#3637)

Integrated into release/v3.8.22 — circuit-breaker guard added in review (#1731v2)
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
* chore(release): open v3.8.22 development cycle

* refactor(dashboard): extract ProviderDetailPageClient — cheaper-inference#3501 Phase 0 (cheaper-inference#3633)

cheaper-inference#3501 Phase 0: extract ProviderDetailPageClient + smoke test.

Co-authored-by: oyi77 <oyi77@users.noreply.github.com>

* refactor(dashboard): extract auth-import modals — cheaper-inference#3501 Phase 1a (cheaper-inference#3634)

cheaper-inference#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 (cheaper-inference#3499) (cheaper-inference#3635)

Closes cheaper-inference#3499 — reclassify localDb unexported modules as intentionally-internal (audit + honest gate framing).

* refactor(db): move call_logs aggregations into callLogStats db module (cheaper-inference#3500) (cheaper-inference#3636)

cheaper-inference#3500 slice 1: call_logs aggregations → src/lib/db/callLogStats.ts (Rule cheaper-inference#5). Byte-identical queries; TDD 6/6.

* refactor(dashboard): extract EditCompatibleNodeModal — cheaper-inference#3501 Phase 1b (cheaper-inference#3638)

cheaper-inference#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 (cheaper-inference#3500 slice 3) (cheaper-inference#3639)

cheaper-inference#3500 slice 3: community_servers SQL → gamification db module.

* refactor(db): move usage_history SQL into usageAnalytics module (cheaper-inference#3500 slice 2) (cheaper-inference#3644)

cheaper-inference#3500 slice 2: usage_history/daily_usage_summary SQL → usageAnalytics db module.

* refactor(db): move skills UPDATE + db-backups SQL into db modules (cheaper-inference#3500 slice 5) (cheaper-inference#3647)

cheaper-inference#3500 slice 5: skills UPDATE (allowlist) + db-backups SQL → db modules.

* refactor(db): move usage_logs/semantic_cache/proxy_logs SQL into db modules (cheaper-inference#3500 slice 4) (cheaper-inference#3648)

cheaper-inference#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 cheaper-inference#3500 (cheaper-inference#3649)

Closes cheaper-inference#3500: reclassify external-DB reads; all internal raw-SQL migrated to db/ modules.

* refactor(dashboard): extract pure helpers to providerPageHelpers — cheaper-inference#3501 Phase 2 (cheaper-inference#3653)

cheaper-inference#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 — cheaper-inference#3501 Phase 2b (cheaper-inference#3658)

cheaper-inference#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 (cheaper-inference#1682) (cheaper-inference#3632)

Integrated into release/v3.8.22

* fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint (cheaper-inference#3631)

Integrated into release/v3.8.22

* refactor: small code cleanup (cheaper-inference#3523)

Integrated into release/v3.8.22

* fix(combo): skip same-provider targets on 408/500/502/503/504/524 errors (cheaper-inference#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 (cheaper-inference#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 (cheaper-inference#3616)

Integrated into release/v3.8.22 — Codex Responses WebSocket call history logging.

* Add Claude Code routing preference for unprefixed Claude models (cheaper-inference#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 cheaper-inference#3632/cheaper-inference#3631/cheaper-inference#3637/cheaper-inference#3659/cheaper-inference#3540/cheaper-inference#3616/cheaper-inference#3523 (v3.8.22 targeted review round)

* fix(mimocode): add required authHeader:"none" to registry entry (cheaper-inference#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 cheaper-inference#3659 (@pizzav-xyz).

* fix(responses): detect stream readiness for tool-call-only and object-less chunks (cheaper-inference#3612) (cheaper-inference#3661)

Closes cheaper-inference#3612

* fix(mitm): remove duplicated 'Command failed:' error prefix (cheaper-inference#3641) (cheaper-inference#3662)

Closes cheaper-inference#3641

* fix(cli): honor HERMES_HOME for Hermes Agent config path (cheaper-inference#3628) (cheaper-inference#3663)

Closes cheaper-inference#3628

* fix(api): fetch live OpenCode model catalog for no-auth model picker (cheaper-inference#3611) (cheaper-inference#3664)

Closes cheaper-inference#3611

* fix(api): flag provider topology error state by current status, not stale history (cheaper-inference#3619) (cheaper-inference#3666)

Closes cheaper-inference#3619

* fix(electron): launch peer-stamping server-ws.mjs entrypoint to avoid 403 LOCAL_ONLY (cheaper-inference#3386) (cheaper-inference#3665)

Closes cheaper-inference#3386

* fix(dashboard): restore home topology live in-flight pulse (cheaper-inference#3507) (cheaper-inference#3667)

Closes cheaper-inference#3507

* fix(oauth): name Kiro/AWS auto-imported accounts and dedupe by profileArn (cheaper-inference#3615) (cheaper-inference#3671)

Closes cheaper-inference#3615

* fix(resilience): clear stale transient connection cooldowns on startup (cheaper-inference#3625) (cheaper-inference#3672)

Closes cheaper-inference#3625

* fix(i18n): use logical CSS direction utilities for sidebar and key overlays (RTL cheaper-inference#3541) (cheaper-inference#3670)

Closes cheaper-inference#3541

* fix(dashboard): honor auto-hide and switch to visible filter on passthrough Test-all (cheaper-inference#3610) (cheaper-inference#3669)

Closes cheaper-inference#3610

* refactor(dashboard): extract AddApiKeyModal + EditConnectionModal — cheaper-inference#3501 Phase 1c (cheaper-inference#3674)

cheaper-inference#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 cheaper-inference#3621/cheaper-inference#3622 + MiMoCode follow-up roll-up

* refactor(dashboard): extract ConnectionRow + ModelCompatPopover + SiliconFlowEndpointModal — cheaper-inference#3501 Phase 1d (cheaper-inference#3676)

cheaper-inference#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 (cheaper-inference#3485 part 1) (cheaper-inference#3677)

Part 1 of cheaper-inference#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 (cheaper-inference#3485 part 2) (cheaper-inference#3678)

Part 2 of cheaper-inference#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 cheaper-inference#18).

* fix(combo): stop premature context compaction — real auto-combo windows + per-target compression limit (cheaper-inference#3680)

Integrated into release/v3.8.22

* feat(dashboard): deactivate/activate accounts from the quota overview (cheaper-inference#3675)

Integrated into release/v3.8.22

* fix(dashboard): close review gaps in bulk provider connection actions (cheaper-inference#3271 follow-up) (cheaper-inference#3673)

Integrated into release/v3.8.22 — page.tsx conflict (god-component split cheaper-inference#3501) resolved by re-applying the bulk-action deltas to ProviderDetailPageClient.tsx

* refactor(dashboard): extract useModelCompatState hook + model sections — cheaper-inference#3501 Phase 1e (cheaper-inference#3683)

cheaper-inference#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 — cheaper-inference#3501 Phase 1f (cheaper-inference#3684)

cheaper-inference#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 cheaper-inference#3628/cheaper-inference#3663)
- Add HERMES_HOME + OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS to ENVIRONMENT.md (cheaper-inference#3628/cheaper-inference#3540)

* docs(changelog): credit cheaper-inference#3673 + cheaper-inference#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>
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.

2 participants