fix(desktop): scope registered ssh primary gateway
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
} from '@/store/boot'
|
||||
import {
|
||||
$gateway,
|
||||
activeGatewayConnectionId,
|
||||
closeLegacySecondaryGateways,
|
||||
closeSecondaryGateways,
|
||||
configureGatewayRegistry,
|
||||
@@ -31,6 +32,7 @@ import {
|
||||
reportPrimaryGatewayState,
|
||||
setPrimaryGateway,
|
||||
setPrimaryGatewayConnection,
|
||||
setPrimaryGatewayConnectionId,
|
||||
touchSecondaryGateways
|
||||
} from '@/store/gateway'
|
||||
import { registerGatewayReconnect } from '@/store/gateway-reconnect'
|
||||
@@ -185,6 +187,7 @@ export function useGatewayBoot({
|
||||
}
|
||||
: null
|
||||
)
|
||||
setPrimaryGatewayConnectionId(next?.connectionId)
|
||||
}
|
||||
|
||||
if (!desktop) {
|
||||
@@ -737,9 +740,17 @@ export function useGatewayBoot({
|
||||
|
||||
const sourceProfile = normalizeProfileKey($activeGatewayProfile.get())
|
||||
|
||||
const offEvent = gateway.onEvent(event =>
|
||||
callbacksRef.current.handleGatewayEvent({ ...event, profile: sourceProfile })
|
||||
)
|
||||
const offEvent = gateway.onEvent(event => {
|
||||
const connectionId = activeGatewayConnectionId()
|
||||
const scopedEvent = {
|
||||
...event,
|
||||
profile: sourceProfile,
|
||||
...(connectionId ? { connectionId } : {})
|
||||
}
|
||||
|
||||
recordSessionEventScope(scopedEvent)
|
||||
callbacksRef.current.handleGatewayEvent(scopedEvent)
|
||||
})
|
||||
|
||||
// Wake signals: power resume (macOS/Windows), network coming back, and the
|
||||
// window regaining focus/visibility. Each nudges an immediate reconnect.
|
||||
|
||||
@@ -40,14 +40,17 @@ vi.mock('@/store/session', () => ({
|
||||
vi.mock('@/store/notify-baseline', () => ({ markNativeNotifyBaseline: vi.fn() }))
|
||||
|
||||
const {
|
||||
activeGatewayConnectionId,
|
||||
closeLegacySecondaryGateways,
|
||||
closeSecondaryGateways,
|
||||
configureGatewayRegistry,
|
||||
ensureGatewayForAgent,
|
||||
openGatewayForAgent,
|
||||
pruneSecondaryGateways,
|
||||
setPrimaryGateway
|
||||
setPrimaryGateway,
|
||||
setPrimaryGatewayConnectionId
|
||||
} = await import('./gateway')
|
||||
const { setApiRequestConnection } = await import('@/hermes')
|
||||
|
||||
function installDesktop(): void {
|
||||
;(window as unknown as { hermesDesktop: unknown }).hermesDesktop = {
|
||||
@@ -85,6 +88,25 @@ afterEach(() => {
|
||||
delete (window as unknown as { hermesDesktop?: unknown }).hermesDesktop
|
||||
})
|
||||
|
||||
describe('primary gateway registry scope', () => {
|
||||
it('publishes a registered primary connection id for ambient API/WebSocket helpers', () => {
|
||||
setPrimaryGateway({ connectionState: 'open' } as never, 'default')
|
||||
setPrimaryGatewayConnectionId(' homelab-ssh ')
|
||||
|
||||
expect(activeGatewayConnectionId()).toBe('homelab-ssh')
|
||||
expect(setApiRequestConnection).toHaveBeenLastCalledWith('homelab-ssh')
|
||||
})
|
||||
|
||||
it('clears primary connection scope when the primary becomes legacy/local again', () => {
|
||||
setPrimaryGateway({ connectionState: 'open' } as never, 'default')
|
||||
setPrimaryGatewayConnectionId('homelab-ssh')
|
||||
setPrimaryGateway({ connectionState: 'open' } as never, 'default')
|
||||
|
||||
expect(activeGatewayConnectionId()).toBeNull()
|
||||
expect(setApiRequestConnection).toHaveBeenLastCalledWith(null)
|
||||
})
|
||||
})
|
||||
|
||||
describe('pruneSecondaryGateways with registry-scoped entries', () => {
|
||||
it('keeps the previous source socket open when Sessions switches backends', async () => {
|
||||
await ensureGatewayForAgent('work', 'default')
|
||||
|
||||
@@ -226,11 +226,23 @@ export function setPrimaryGateway(gateway: HermesGateway | null, profile = 'defa
|
||||
|
||||
g.primaryGateway = gateway
|
||||
g.primaryProfile = next
|
||||
|
||||
if (g.activeKey === g.primaryProfile) {
|
||||
setApiRequestConnection(g.primaryConnectionId)
|
||||
}
|
||||
}
|
||||
|
||||
export function setPrimaryGatewayConnectionId(connectionId: null | string | undefined): void {
|
||||
g.primaryConnectionId = (connectionId ?? '').trim() || null
|
||||
|
||||
if (g.activeKey === g.primaryProfile) {
|
||||
setApiRequestConnection(g.primaryConnectionId)
|
||||
}
|
||||
}
|
||||
|
||||
/** Publish the registry source owned by the window primary socket. */
|
||||
export function setPrimaryGatewayConnection(connection: Pick<HermesConnection, 'connectionId'> | null): void {
|
||||
g.primaryConnectionId = connection?.connectionId?.trim() || null
|
||||
setPrimaryGatewayConnectionId(connection?.connectionId)
|
||||
}
|
||||
|
||||
function isPrimaryRegistryRoute(connectionId: null | string, profile: string): boolean {
|
||||
@@ -276,7 +288,7 @@ export function activeGateway(): HermesGateway | null {
|
||||
*/
|
||||
export function activeGatewayConnectionId(): null | string {
|
||||
if (g.activeKey === g.primaryProfile) {
|
||||
return null
|
||||
return g.primaryConnectionId
|
||||
}
|
||||
|
||||
return g.secondaries.get(g.activeKey)?.connectionId ?? null
|
||||
|
||||
Reference in New Issue
Block a user