From 74cb4cb80c7f6e6c0dfe05e079b5143bceefca35 Mon Sep 17 00:00:00 2001 From: "hermes-seaeye[bot]" <307254004+hermes-seaeye[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 21:44:19 +0000 Subject: [PATCH] fmt(js): `npm run fix` on merge (#95858) Co-authored-by: github-actions[bot] --- apps/desktop/electron/connection-registry.ts | 129 ++++++------- apps/desktop/electron/oauth-partition.test.ts | 14 +- apps/desktop/electron/oauth-partition.ts | 6 +- .../src/app/chat/sidebar/fleet-rail.test.ts | 60 +++++- .../chat/sidebar/profile-rail-fleet.test.tsx | 24 ++- .../src/app/chat/sidebar/profile-switcher.tsx | 177 ++++++++++-------- .../contrib/hooks/use-background-sync.test.ts | 4 +- .../app/contrib/hooks/use-background-sync.ts | 1 + .../session/hooks/use-model-controls.test.tsx | 6 +- apps/desktop/src/hover-variant.test.ts | 1 + apps/desktop/src/store/cron-model-impact.ts | 1 + apps/desktop/src/store/session-states.test.ts | 4 +- 12 files changed, 247 insertions(+), 180 deletions(-) diff --git a/apps/desktop/electron/connection-registry.ts b/apps/desktop/electron/connection-registry.ts index 2757a28e01..bb9d1f0f82 100644 --- a/apps/desktop/electron/connection-registry.ts +++ b/apps/desktop/electron/connection-registry.ts @@ -1075,7 +1075,10 @@ export function normalizeRegistry(raw: unknown): ConnectionRegistry { if (Array.isArray(parsed.quarantined)) { for (const item of parsed.quarantined) { if (item && typeof item === 'object' && 'entry' in (item as Record)) { - quarantine(String((item as Record).reason || 'unknown'), (item as Record).entry) + quarantine( + String((item as Record).reason || 'unknown'), + (item as Record).entry + ) } } } @@ -1105,82 +1108,82 @@ export function normalizeRegistry(raw: unknown): ConnectionRegistry { // One bad entry must never abort the whole registry load (#94246): any // unexpected throw quarantines THIS entry and the loop moves on. try { - const entry = item as Record - const kind = entry.kind + const entry = item as Record + const kind = entry.kind - if (kind !== 'local' && kind !== 'remote' && kind !== 'cloud' && kind !== 'ssh') { - quarantine('entry-unrecognized-kind', item) - - continue - } - - let label = String(entry.label || '').trim() - - if (!label) { - // Defensive: registry entries are always written with labels, but a - // hand-edited file may drop one. Derive rather than discard. - label = - kind === 'ssh' ? String(entry.host || 'ssh') : hostLabelFromBaseUrl(String(entry.url || '')) || String(kind) - } - - label = uniqueLabel(label, seenLabels) - - let id = kind === 'local' ? LOCAL_CONNECTION_ID : String(entry.id || '').trim() - - if (!id || (seenIds.has(id) && kind !== 'local')) { - id = connectionIdForLabel(label, seenIds) - } - - if (seenIds.has(id)) { - continue // second 'local' entry — first one wins - } - - seenLabels.add(labelKey(label)) - seenIds.add(id) - - const clean: RegistryConnection = { id, kind, label } - - if (kind === 'remote' || kind === 'cloud') { - const url = String(entry.url || '').trim() - - if (!url) { - quarantine('entry-missing-url', item) + if (kind !== 'local' && kind !== 'remote' && kind !== 'cloud' && kind !== 'ssh') { + quarantine('entry-unrecognized-kind', item) continue } - clean.url = url - clean.authMode = normAuthMode(entry.authMode) + let label = String(entry.label || '').trim() - if (entry.token !== undefined) { - clean.token = entry.token + if (!label) { + // Defensive: registry entries are always written with labels, but a + // hand-edited file may drop one. Derive rather than discard. + label = + kind === 'ssh' ? String(entry.host || 'ssh') : hostLabelFromBaseUrl(String(entry.url || '')) || String(kind) } - const storedHeaders = normalizeRemoteHeaders(entry.headers) + label = uniqueLabel(label, seenLabels) - if (Object.keys(storedHeaders).length > 0) { - clean.headers = storedHeaders + let id = kind === 'local' ? LOCAL_CONNECTION_ID : String(entry.id || '').trim() + + if (!id || (seenIds.has(id) && kind !== 'local')) { + id = connectionIdForLabel(label, seenIds) } - const org = String(entry.org || '').trim() - - if (kind === 'cloud' && org) { - clean.org = org - } - } else if (kind === 'ssh') { - const ssh = normalizeSshConfig({ ...entry, mode: 'ssh' }) - - if (!ssh) { - quarantine('entry-missing-ssh-host', item) - - continue + if (seenIds.has(id)) { + continue // second 'local' entry — first one wins } - const { mode: _mode, ...sshFields } = ssh - Object.assign(clean, sshFields) - } + seenLabels.add(labelKey(label)) + seenIds.add(id) - connections.push(clean) + const clean: RegistryConnection = { id, kind, label } + + if (kind === 'remote' || kind === 'cloud') { + const url = String(entry.url || '').trim() + + if (!url) { + quarantine('entry-missing-url', item) + + continue + } + + clean.url = url + clean.authMode = normAuthMode(entry.authMode) + + if (entry.token !== undefined) { + clean.token = entry.token + } + + const storedHeaders = normalizeRemoteHeaders(entry.headers) + + if (Object.keys(storedHeaders).length > 0) { + clean.headers = storedHeaders + } + + const org = String(entry.org || '').trim() + + if (kind === 'cloud' && org) { + clean.org = org + } + } else if (kind === 'ssh') { + const ssh = normalizeSshConfig({ ...entry, mode: 'ssh' }) + + if (!ssh) { + quarantine('entry-missing-ssh-host', item) + + continue + } + + const { mode: _mode, ...sshFields } = ssh + Object.assign(clean, sshFields) + } + + connections.push(clean) } catch { quarantine('entry-normalization-failed', safeEntryCopy(item)) } diff --git a/apps/desktop/electron/oauth-partition.test.ts b/apps/desktop/electron/oauth-partition.test.ts index 13a47b4ba5..8aabdc6b95 100644 --- a/apps/desktop/electron/oauth-partition.test.ts +++ b/apps/desktop/electron/oauth-partition.test.ts @@ -68,9 +68,7 @@ describe('resolveOauthPartition (#92183 per-connection cookie jars)', () => { remote('conn-b', 'https://gw-b.example.com') ]) - expect(resolveOauthPartition('https://gw-a.example.com/api/status', { registry: reg })).toBe( - LEGACY_OAUTH_PARTITION - ) + expect(resolveOauthPartition('https://gw-a.example.com/api/status', { registry: reg })).toBe(LEGACY_OAUTH_PARTITION) expect(resolveOauthPartition('https://gw-b.example.com/api/status', { registry: reg })).not.toBe( LEGACY_OAUTH_PARTITION ) @@ -100,12 +98,10 @@ describe('resolveOauthPartition (#92183 per-connection cookie jars)', () => { ) expect(resolveOauthPartition('not a url', { registry: reg })).toBe(LEGACY_OAUTH_PARTITION) expect(resolveOauthPartition('', { registry: reg })).toBe(LEGACY_OAUTH_PARTITION) - expect(resolveOauthPartition('https://gw-a.example.com', { registry: null as any })).toBe( - LEGACY_OAUTH_PARTITION - ) - expect(resolveOauthPartition('https://gw-a.example.com', { registry: { primary: 'x', connections: 'junk' } as any })).toBe( - LEGACY_OAUTH_PARTITION - ) + expect(resolveOauthPartition('https://gw-a.example.com', { registry: null as any })).toBe(LEGACY_OAUTH_PARTITION) + expect( + resolveOauthPartition('https://gw-a.example.com', { registry: { primary: 'x', connections: 'junk' } as any }) + ).toBe(LEGACY_OAUTH_PARTITION) }) it('does not treat a hostname PREFIX as a base-url match', () => { diff --git a/apps/desktop/electron/oauth-partition.ts b/apps/desktop/electron/oauth-partition.ts index 420c9b309a..d83eece8a1 100644 --- a/apps/desktop/electron/oauth-partition.ts +++ b/apps/desktop/electron/oauth-partition.ts @@ -142,11 +142,7 @@ export function resolveOauthPartition(requestUrl: unknown, opts: ResolveOauthPar // Longest base-url prefix wins (sub-path gateways behind one proxy); // identical URLs tie-break on the lexicographically smallest id so the // choice is deterministic across processes and launches. - if ( - !best || - baseNorm.length > best.baseNorm.length || - (baseNorm.length === best.baseNorm.length && id < best.id) - ) { + if (!best || baseNorm.length > best.baseNorm.length || (baseNorm.length === best.baseNorm.length && id < best.id)) { best = { baseNorm, id } } } diff --git a/apps/desktop/src/app/chat/sidebar/fleet-rail.test.ts b/apps/desktop/src/app/chat/sidebar/fleet-rail.test.ts index 0b786c2a5a..49f94f6251 100644 --- a/apps/desktop/src/app/chat/sidebar/fleet-rail.test.ts +++ b/apps/desktop/src/app/chat/sidebar/fleet-rail.test.ts @@ -12,11 +12,41 @@ const connections: DesktopRegistryConnection[] = [ const roster: DesktopAgentRoster = { agents: [ - { connectionId: 'pandora', connectionKind: 'remote', connectionLabel: 'Pandora', profile: 'default', handle: 'hermes-pandora' }, - { connectionId: 'pandora', connectionKind: 'remote', connectionLabel: 'Pandora', profile: 'scout', handle: 'scout' }, - { connectionId: 'pandora', connectionKind: 'remote', connectionLabel: 'Pandora', profile: 'omer', handle: 'omer-pandora' }, - { connectionId: 'local', connectionKind: 'local', connectionLabel: 'This device', profile: 'default', handle: 'hermes' }, - { connectionId: 'local', connectionKind: 'local', connectionLabel: 'This device', profile: 'omer', handle: 'omer-this-device' } + { + connectionId: 'pandora', + connectionKind: 'remote', + connectionLabel: 'Pandora', + profile: 'default', + handle: 'hermes-pandora' + }, + { + connectionId: 'pandora', + connectionKind: 'remote', + connectionLabel: 'Pandora', + profile: 'scout', + handle: 'scout' + }, + { + connectionId: 'pandora', + connectionKind: 'remote', + connectionLabel: 'Pandora', + profile: 'omer', + handle: 'omer-pandora' + }, + { + connectionId: 'local', + connectionKind: 'local', + connectionLabel: 'This device', + profile: 'default', + handle: 'hermes' + }, + { + connectionId: 'local', + connectionKind: 'local', + connectionLabel: 'This device', + profile: 'omer', + handle: 'omer-this-device' + } ], sources: [ { connectionId: 'pandora', kind: 'remote', label: 'Pandora', reachable: true }, @@ -38,9 +68,18 @@ describe('buildRestGroups', () => { it('carries each gateway default as its own square plus named profiles alphabetically', () => { const [local] = buildRestGroups({ activeConnectionId: 'pandora', connections, roster }) - expect(local.defaultAgent).toMatchObject({ connectionId: 'local', profile: 'default', isDefault: true, handle: 'hermes' }) + expect(local.defaultAgent).toMatchObject({ + connectionId: 'local', + profile: 'default', + isDefault: true, + handle: 'hermes' + }) expect(local.named.map(agent => agent.profile)).toEqual(['omer']) - expect(local.named[0]).toMatchObject({ connectionLabel: 'This device', handle: 'omer-this-device', isDefault: false }) + expect(local.named[0]).toMatchObject({ + connectionLabel: 'This device', + handle: 'omer-this-device', + isDefault: false + }) const [pandora] = buildRestGroups({ activeConnectionId: 'local', connections, roster }) expect(pandora.named.map(agent => agent.profile)).toEqual(['omer', 'scout']) @@ -66,7 +105,12 @@ describe('buildRestGroups', () => { }) it('skips a registration the roster collapsed into another (same backend, two addresses)', () => { - const twin: DesktopRegistryConnection = { id: 'pandora-lan', kind: 'remote', label: 'Pandora LAN', url: 'http://10.0.0.2' } as DesktopRegistryConnection + const twin: DesktopRegistryConnection = { + id: 'pandora-lan', + kind: 'remote', + label: 'Pandora LAN', + url: 'http://10.0.0.2' + } as DesktopRegistryConnection const groups = buildRestGroups({ activeConnectionId: 'local', connections: [...connections, twin], roster }) expect(groups.map(group => group.connectionId)).toEqual(['pandora', 'vps']) diff --git a/apps/desktop/src/app/chat/sidebar/profile-rail-fleet.test.tsx b/apps/desktop/src/app/chat/sidebar/profile-rail-fleet.test.tsx index d2bc44f072..a8d80ffa30 100644 --- a/apps/desktop/src/app/chat/sidebar/profile-rail-fleet.test.tsx +++ b/apps/desktop/src/app/chat/sidebar/profile-rail-fleet.test.tsx @@ -142,9 +142,27 @@ const registry: DesktopConnectionsRegistry = { const roster: DesktopAgentRoster = { agents: [ - { connectionId: 'pandora', connectionKind: 'remote', connectionLabel: 'Pandora', profile: 'default', handle: 'hermes-pandora' }, - { connectionId: 'pandora', connectionKind: 'remote', connectionLabel: 'Pandora', profile: 'scout', handle: 'scout' }, - { connectionId: 'local', connectionKind: 'local', connectionLabel: 'This device', profile: 'default', handle: 'hermes' }, + { + connectionId: 'pandora', + connectionKind: 'remote', + connectionLabel: 'Pandora', + profile: 'default', + handle: 'hermes-pandora' + }, + { + connectionId: 'pandora', + connectionKind: 'remote', + connectionLabel: 'Pandora', + profile: 'scout', + handle: 'scout' + }, + { + connectionId: 'local', + connectionKind: 'local', + connectionLabel: 'This device', + profile: 'default', + handle: 'hermes' + }, { connectionId: 'local', connectionKind: 'local', connectionLabel: 'This device', profile: 'omer', handle: 'omer' } ], sources: [ diff --git a/apps/desktop/src/app/chat/sidebar/profile-switcher.tsx b/apps/desktop/src/app/chat/sidebar/profile-switcher.tsx index 53fa1b5c10..39b4b32002 100644 --- a/apps/desktop/src/app/chat/sidebar/profile-switcher.tsx +++ b/apps/desktop/src/app/chat/sidebar/profile-switcher.tsx @@ -178,8 +178,7 @@ export function ProfileRail() { const connections = registry?.connections const restGroups = useMemo( - () => - multipleConnections ? buildRestGroups({ activeConnectionId, connections: connections ?? [], roster }) : [], + () => (multipleConnections ? buildRestGroups({ activeConnectionId, connections: connections ?? [], roster }) : []), [activeConnectionId, connections, multipleConnections, roster] ) @@ -353,42 +352,42 @@ export function ProfileRail() { // from the single-gateway rail; fleet mode only decides where it sits). const activeStrip = ( <> - {multiProfile && ( - - profile.name)} strategy={horizontalListSortingStrategy}> - {/* relative → the strip is the dragged square's offsetParent, so the + {multiProfile && ( + + profile.name)} strategy={horizontalListSortingStrategy}> + {/* relative → the strip is the dragged square's offsetParent, so the clamp modifier bounds drags to the occupied cells (not the +). */} -
- {named.map(profile => ( - openRemoteOverrideDialog(profile.name)} - onDelete={() => setPendingDelete(profile)} - onEditSoul={() => setPendingSoul(profile.name)} - onRecolor={color => setProfileColor(profile.name, color)} - onRename={() => setPendingRename(profile)} - onSelect={() => selectProfile(profile.name)} - remoteHost={remoteOverrides[normalizeProfileKey(profile.name)]?.host ?? null} - /> - ))} -
-
-
- )} +
+ {named.map(profile => ( + openRemoteOverrideDialog(profile.name)} + onDelete={() => setPendingDelete(profile)} + onEditSoul={() => setPendingSoul(profile.name)} + onRecolor={color => setProfileColor(profile.name, color)} + onRename={() => setPendingRename(profile)} + onSelect={() => selectProfile(profile.name)} + remoteHost={remoteOverrides[normalizeProfileKey(profile.name)]?.host ?? null} + /> + ))} +
+
+
+ )} ) @@ -397,7 +396,12 @@ export function ProfileRail() { {/* Fleet: every gateway carries its own home square inside its group, so the pinned pill is purely the "all profiles on this gateway" toggle. */} {fleet && ( - setShowAllProfiles(true)} /> + setShowAllProfiles(true)} + /> )} {/* One button toggles default ↔ all: home face when scoped to a profile, @@ -452,53 +456,51 @@ export function ProfileRail() { {/* The active gateway's squares. In fleet mode they sit in the gateway's registry slot with a home square at their head, so the strip keeps one shape whichever gateway is active. */} - {fleet ? ( - fleetSequence.map((entry, index) => - entry.kind === 'active' ? ( - - + entry.kind === 'active' ? ( + + + + {defaultProfile && ( + selectProfile(defaultProfile.name)} + /> + )} + {activeStrip} + + + ) : ( + setProfileColor(agent.profile, color)} + onRename={setPendingRestRename} + onSelect={switchToRest} + pendingRoute={pendingRoute} /> - - {defaultProfile && ( - selectProfile(defaultProfile.name)} - /> - )} - {activeStrip} - - - ) : ( - setProfileColor(agent.profile, color)} - onRename={setPendingRestRename} - onSelect={switchToRest} - pendingRoute={pendingRoute} - /> + ) ) - ) - ) : ( - activeStrip - )} + : activeStrip} setCreateOpen(true)} /> @@ -850,7 +852,16 @@ interface ProfilePillProps { connectionId?: string } -function ProfilePill({ active, connectionId, glyph, label, muted = false, onSelect, pending = false, slot }: ProfilePillProps) { +function ProfilePill({ + active, + connectionId, + glyph, + label, + muted = false, + onSelect, + pending = false, + slot +}: ProfilePillProps) { return (