Skip to content

fix(desktop): recover stale remote backends and scope profile caches per connection - #102673

Closed
SmelterLabs wants to merge 1 commit into
NousResearch:mainfrom
SmelterLabs:pr/desktop-stale-backend-recovery
Closed

SmelterLabs wants to merge 1 commit into
NousResearch:mainfrom
SmelterLabs:pr/desktop-stale-backend-recovery

Conversation

@SmelterLabs

Copy link
Copy Markdown

What this fixes

Five related defects in the desktop app's remote-backend handling. All of them are reachable from ordinary multi-gateway use, and we have been carrying this patch downstream since 2026-08-26 on a daily-updated fork, so it has real runtime hours behind it.

1. Foreground profile activation trusted a stale cache. Activating a registry profile took the cached backend at face value. It now probes that exact cached entry via revalidateConnectionFor and retires the pool/transport scope when the probe comes back stale, instead of handing the UI a dead backend.

2. The two revalidation paths raced. Both could run concurrently against the same connection. They now serialize through a single-flight coordinator.

3. Profile caches leaked across gateways. The cache was global, so profiles from one gateway could surface against another. Caches are now connection-scoped.

4. A bare profile name spawned the wrong thing. Given a bare name, the desktop spawned a same-named local child rather than routing to the active registry socket. This misroutes any remote profile whose display name differs from its default key.

5. The idle reaper could take an in-use backend. An active chat backend was eligible for reaping mid-conversation. touchBackend now keepalives it.

Testing

  • tsc --noEmit clean.
  • vitest run src/store/connections.test.ts src/store/profile.test.ts src/store/gateway-agent-scope.test.ts src/store/gateway-profile-request.test.ts — 4 files, 76 tests, all passing against current main (63279301b).
  • New coverage added alongside the fix in connections.test.ts, gateway-agent-scope.test.ts, and gateway-profile-request.test.ts.

Notes

Cherry-picked cleanly onto current main with no conflicts. Happy to split this into five separate PRs if that is easier to review — they are independent fixes that happened to land together, and the shared surface is store/connections.ts and store/gateway.ts.

🤖 Generated with Claude Code

…per connection

Five related defects in the desktop's remote-backend handling, all reachable
from normal multi-gateway use:

- Foreground registry-profile activation trusted the cached backend. It now
  probes the exact cached entry (revalidateConnectionFor) and retires its
  pool/transport scope when the probe shows it stale.
- The two revalidation paths raced each other. They now serialize through a
  single-flight coordinator.
- Profile caches were global, so profiles leaked across gateways. They are
  now connection-scoped.
- A bare profile name spawned a same-named local child instead of routing to
  the active registry socket. This misroutes any remote profile whose
  display name differs from its default key.
- An active chat backend could be taken by the idle reaper mid-conversation.
  touchBackend now keepalives it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@SmelterLabs
SmelterLabs force-pushed the pr/desktop-stale-backend-recovery branch from a95ba4e to 3e8f742 Compare September 18, 2026 17:21
@SmelterLabs

Copy link
Copy Markdown
Author

Closing: superseded by the v2026.9.21 shared-backend redesign. The profile-cache scoping and dispatch-time recovery from this PR landed upstream independently, and the remaining pre-activation handshake and prewarm guard were written for the old one-backend-per-profile model, which the new supervisor in electron/main.ts replaces. Thanks for the review time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/desktop Electron desktop app (apps/desktop/*) P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants