Skip to content

fix(desktop): show saved gateways without opening Settings - #119727

Merged
OutThisLife merged 3 commits into
mainfrom
bb/desktop-gateway-registry-startup
Sep 23, 2026
Merged

OutThisLife merged 3 commits into
mainfrom
bb/desktop-gateway-registry-startup

Conversation

@OutThisLife

Copy link
Copy Markdown

What does this PR do?

Loads the saved gateway registry during renderer startup so the sidebar shows the registered gateways without opening Settings. Previously, the optional status-bar ConnectionSwitcher owned the initial read and registry-change subscription. When that control did not mount, the registry stayed null and the fleet rail never started enumeration.

The always-mounted gateway lifecycle now owns those reads. Simple mode also keeps the existing rail visible for multiple registered gateways, even when the active gateway has only its default profile.

Related Issue

Fixes #101257.

Related alternative: #101529 loads the registry from ProfileRail on mount. This PR uses the boot owner instead, covering hidden rails and status bars, ongoing registry changes, and failed initial reads. The contributor's branch is unchanged.

Type of Change

  • Bug fix

Changes Made

  • use-connections-registry.ts owns initial hydration and the registry-change subscription, with two delayed retries and a focus retry after failure. Reads are serialized; changes received during a read request another snapshot. Healthy registries are not polled.
  • use-gateway-boot.ts mounts that lifecycle. Source restoration still waits for primary boot reads and excludes peer/auxiliary windows. ConnectionSwitcher only consumes the published state.
  • store/connections.ts bounds registry IPC reads at five seconds and preserves the last good cache if a read times out.
  • store/interface-mode.ts and app/contrib/controller.tsx include saved gateway count in Simple mode's existing rail visibility policy. No styling changes.
  • Move lifecycle tests out of the switcher tests, add a real-boot-hook regression with saved/removed events, and update the multi-connection guide.

How to Test

  1. Register multiple gateways, hide the status bar, and restart Desktop without opening Settings. The sidebar should list the registered gateways.
  2. Repeat in Simple mode with only a default profile on the active gateway. The rail should remain available for gateway navigation.
  3. Save, rename, or remove an inactive gateway. The list should update without changing the active gateway or replaying the startup-source preference.

Verification performed on macOS:

  • Regression observed failing before the startup-owner change, then passing after it.
  • 138 targeted tests passed across the boot hook, registry lifecycle, connections store, interface mode, switcher, fleet rail, and fleet roster.
  • Chrome component verification with production components/CSS and in-memory IPC fixtures: Simple and Advanced startup without the switcher or Settings; recovery after two rejected reads; newly saved gateway appears without reload.
  • Full native Electron/backend cold-start E2E. The browser check above is isolated component verification, not live-gateway verification.

Targeted command, from apps/desktop:

npm exec --offline -- vitest run --project ui \
  src/app/gateway/hooks/use-connections-registry.test.tsx \
  src/app/gateway/hooks/use-gateway-boot.test.tsx \
  src/store/connections.test.ts \
  src/store/interface-mode.test.ts \
  src/app/chat/sidebar/connection-switcher.test.tsx \
  src/app/chat/sidebar/profile-rail-fleet.test.tsx \
  src/store/fleet-roster.test.ts

Checklist

  • Read the contributing guide; conventional commits; searched existing PRs.
  • Changes are limited to this fix and its documentation/tests.
  • Added behavioral regression coverage and retained startup-restoration guards.
  • Updated the multi-connection desktop documentation.
  • Considered cross-platform impact: renderer lifecycle changes only; no OS-specific APIs or new dependencies.
  • Full repository test suite, typecheck, lint, and build were not run.
  • Config keys and tool schemas: N/A.

Screenshots / Logs

Test Files  7 passed (7)
     Tests  138 passed (138)

The isolated browser checks rendered all three fixture gateway groups with zero mounted status bars and no Settings opened. No runtime exceptions occurred. External network access was blocked; the existing Google Fonts request produced the expected blocked-resource console error.

@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

૮ >ﻌ< ა ci review

ran on db7558a — test(desktop): wait for the endpoint form before editing it

debug info

CI timings

CI timings · View report · View job

Wall time 6m10s vs 5m11s (+19.0%). 7 job(s) slower, 6 faster, 1 unchanged.

  • Python tests / Run tests: +56.0s
  • Docs Site / docs-site-checks: +51.0s
  • JS & TS checks / JS & TS checks: +17.0s
  • OS-specific tests / macOS-only tests: -13.0s
  • Python tests / e2e: +10.0s

@OutThisLife
OutThisLife enabled auto-merge (rebase) September 23, 2026 01:56

@arkheioncorp arkheioncorp left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Review: fix(desktop): show saved gateways without opening Settings

Verdict: APPROVE

Findings

  • Sound refactoring. Moving connection registry lifecycle from ConnectionSwitcher into a dedicated useConnectionsRegistry hook is the right decomposition — the component should paint a cache, not own IPC retry/backoff logic.
  • Boot lifecycle preserved. The hook correctly defers initializeConnectionsRegistry until boot.running is false, and skips it for peer/auxiliary windows — same semantics as the old effect, just relocated.
  • Retry/backoff is correct. Two fixed delays (1s, 2s) then warn-on-focus is reasonable; the "requested while pending" queue prevents concurrent refresh storms when Electron pushes onChanged during an in-flight read.
  • Test coverage. The new hook tests exercise the boot-gated init, peer/auxiliary early return, and the stuck-IPC + focus-recovery path. The gutted component tests (boot-phase, peer, auxiliary) are redundant with the hook tests — the remaining component test still validates the repaint-on-registry-change behavior.
  • Mode context extension. Adding connectionCount to ModeContext and using it for profileRailVisible is consistent with the existing profileCount policy. The controller subscription is the right wireup point.
  • Documentation updated. The multi-connection doc now accurately describes that the registry loads at startup without Settings and that loading ≠ connecting.

Minor notes (non-blocking)

  • The rewritten "repaints the menu after a connections.save without reload" test no longer exercises the Electron onChanged IPC path directly — that path is covered by use-connections-registry.test.ts and use-gateway-boot.test.ts, so coverage is not lost, just relocated.

No security concerns, no logic errors. Approve.

@OutThisLife
OutThisLife merged commit 40f29e2 into main Sep 23, 2026
32 checks passed
@OutThisLife
OutThisLife deleted the bb/desktop-gateway-registry-startup branch September 23, 2026 02:15
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.

Desktop: gateway list shows only the remote gateway until Settings → Gateway is opened and closed

2 participants