From 1a19c52dd2b89ceedec9706ecbca0fcdbe5e2ca0 Mon Sep 17 00:00:00 2001 From: "hermes-seaeye[bot]" <307254004+hermes-seaeye[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 07:45:59 +0000 Subject: [PATCH] fmt(js): `npm run fix` on merge (#95365) Co-authored-by: github-actions[bot] --- .../electron/connection-registry.test.ts | 1 + apps/desktop/electron/main.ts | 10 ++-------- .../electron/native-auth-decisions.test.ts | 1 - .../desktop/electron/native-auth-decisions.ts | 1 + .../electron/plugin-profile-routes.test.ts | 6 +++--- apps/desktop/electron/remote-liveness.ts | 8 ++------ .../src/app/chat/session-tile-actions.ts | 2 ++ .../app/chat/sidebar/session-index.test.ts | 1 + .../gateway/hooks/use-gateway-boot.test.tsx | 8 +++++++- .../src/app/gateway/hooks/use-gateway-boot.ts | 1 + .../gateway/hooks/use-gateway-request.test.ts | 7 +++++++ .../src/app/shell/model-catalog-menu.tsx | 3 +-- apps/desktop/src/lib/connection-scoped.ts | 2 ++ apps/desktop/src/lib/model-options.test.ts | 14 ++++++++------ .../tests/hide-bot-chats.runtime.test.ts | 19 +++++++++++-------- .../store/gateway-connection-scope.test.ts | 3 ++- .../src/store/gateway-shared-remote.test.ts | 9 ++------- apps/desktop/src/store/session-states.test.ts | 4 +--- 18 files changed, 54 insertions(+), 46 deletions(-) diff --git a/apps/desktop/electron/connection-registry.test.ts b/apps/desktop/electron/connection-registry.test.ts index a89fc52315..b07f6672d8 100644 --- a/apps/desktop/electron/connection-registry.test.ts +++ b/apps/desktop/electron/connection-registry.test.ts @@ -726,6 +726,7 @@ test('roster: unique profiles keep bare handles; duplicates get @name-device', ( test('roster: source profile metadata follows the connection-qualified row', () => { const local = { id: 'local', kind: 'local' as const, label: 'This device' } const vps = { id: 'vps', kind: 'remote' as const, label: 'VPS', url: 'http://vps:8642' } + const vpsMeta = { display_name: 'Emma', ui_meta: { 'hermes-bots': { title: 'Emma', shape: 'blobatar::sun', color: '#8b5cf6' } }, diff --git a/apps/desktop/electron/main.ts b/apps/desktop/electron/main.ts index 3e3c870841..e3154b32cf 100644 --- a/apps/desktop/electron/main.ts +++ b/apps/desktop/electron/main.ts @@ -9542,9 +9542,7 @@ async function teardownSshConnection(profile) { // connectWindowsRemote does not share POSIX lock/kill. Stay // silent on the kill path, but leave a log so quit is not a // mysterious no-op on Windows remotes. - sshRememberLog( - '[ssh] skip remote serve teardown on Windows remotes; POSIX disconnect does not apply' - ) + sshRememberLog('[ssh] skip remote serve teardown on Windows remotes; POSIX disconnect does not apply') } : remoteLifecycle.disconnect } @@ -14099,11 +14097,7 @@ ipcMain.handle('hermes:connection-config:oauth-login', async (_event, rawUrl) => return { ok: true, baseUrl, connected: true } } catch (error) { - rememberLog( - `[native-oauth] native login failed (${ - error instanceof Error ? error.message : String(error) - })` - ) + rememberLog(`[native-oauth] native login failed (${error instanceof Error ? error.message : String(error)})`) return { ok: false, error: error instanceof Error ? error.message : String(error), connected: false } } diff --git a/apps/desktop/electron/native-auth-decisions.test.ts b/apps/desktop/electron/native-auth-decisions.test.ts index 0434d432cd..815af88b85 100644 --- a/apps/desktop/electron/native-auth-decisions.test.ts +++ b/apps/desktop/electron/native-auth-decisions.test.ts @@ -134,7 +134,6 @@ test('oauthGuardMayHardFail keeps the strict guard when the list is unusable', ( assert.equal(oauthGuardMayHardFail([{ supportsPassword: true }]), true) }) - test('oauthGuardMayHardFail treats status-shaped string basic as password-only', () => { assert.equal(oauthGuardMayHardFail(['basic'] as any), false) assert.equal(oauthGuardMayHardFail([' basic '] as any), false) diff --git a/apps/desktop/electron/native-auth-decisions.ts b/apps/desktop/electron/native-auth-decisions.ts index 0596f53ed9..fddaadef0e 100644 --- a/apps/desktop/electron/native-auth-decisions.ts +++ b/apps/desktop/electron/native-auth-decisions.ts @@ -168,6 +168,7 @@ export function normalizeAdvertisedAuthProviders(providers: unknown): Advertised } out.push({ name, supportsPassword: PASSWORD_PROVIDER_NAMES.has(name) }) + continue } diff --git a/apps/desktop/electron/plugin-profile-routes.test.ts b/apps/desktop/electron/plugin-profile-routes.test.ts index b84d4a0249..0d12f0f88b 100644 --- a/apps/desktop/electron/plugin-profile-routes.test.ts +++ b/apps/desktop/electron/plugin-profile-routes.test.ts @@ -286,9 +286,9 @@ describe('localRouteFallbackProfiles', () => { }) it('synthesizes local routes for a genuine local enumeration error', () => { - expect( - localRouteFallbackProfiles([], 'local', ['default'], isLocalEnumerationFailure('ECONNREFUSED')) - ).toEqual(['default']) + expect(localRouteFallbackProfiles([], 'local', ['default'], isLocalEnumerationFailure('ECONNREFUSED'))).toEqual([ + 'default' + ]) }) }) diff --git a/apps/desktop/electron/remote-liveness.ts b/apps/desktop/electron/remote-liveness.ts index c8e436215e..69ea6af4a4 100644 --- a/apps/desktop/electron/remote-liveness.ts +++ b/apps/desktop/electron/remote-liveness.ts @@ -68,9 +68,7 @@ export class RemoteRevalidationCoordinator { } } -interface EnsureHealthyPooledRemoteBackendForDispatchOptions< - TConnection extends RemoteConnectionDescriptor -> { +interface EnsureHealthyPooledRemoteBackendForDispatchOptions { connectionPromise: Promise currentConnectionPromise: () => null | Promise probe: (connection: TConnection, path: string, options: { timeoutMs: number }) => Promise @@ -86,9 +84,7 @@ interface EnsureHealthyPooledRemoteBackendForDispatchOptions< * caller. The caller should single-flight this function per cached promise so * concurrent dispatches share one retire/reconnect sequence. */ -export async function ensureHealthyPooledRemoteBackendForDispatch< - TConnection extends RemoteConnectionDescriptor ->({ +export async function ensureHealthyPooledRemoteBackendForDispatch({ connectionPromise, currentConnectionPromise, probe, diff --git a/apps/desktop/src/app/chat/session-tile-actions.ts b/apps/desktop/src/app/chat/session-tile-actions.ts index 8e91641218..c418ec5af8 100644 --- a/apps/desktop/src/app/chat/session-tile-actions.ts +++ b/apps/desktop/src/app/chat/session-tile-actions.ts @@ -98,6 +98,7 @@ export function listTileSessionRow(deps: { const knownOwner = sessionTileOwnerRoute(deps.storedSessionId) ?? knownSessionOwner(deps.sessions, deps.storedSessionId) + const ownerRoute: SessionProfileRoute | undefined = knownOwner && typeof knownOwner === 'object' ? knownOwner : undefined @@ -178,6 +179,7 @@ export function useSessionTileActions({ requestGateway, runtimeId, scope, stored (method: string, params?: Record, timeoutMs?: number, signal?: AbortSignal) => { const knownOwner: SessionOwnerScope = sessionTileOwnerRoute(storedIdRef.current) ?? knownSessionOwner($sessions.get(), storedIdRef.current) + // A bare profile is the legacy/unknown tile shape. Preserve its ambient // behavior; only a composite route is strong enough to retarget a tile // across same-named sources. diff --git a/apps/desktop/src/app/chat/sidebar/session-index.test.ts b/apps/desktop/src/app/chat/sidebar/session-index.test.ts index 033ee42442..2a2fba12e1 100644 --- a/apps/desktop/src/app/chat/sidebar/session-index.test.ts +++ b/apps/desktop/src/app/chat/sidebar/session-index.test.ts @@ -128,6 +128,7 @@ describe('resolvePinnedSessions', () => { row('foreign', { last_active: 1, pinned: true, profile: 'k9' }), row('local', { last_active: 50, pinned: true, profile: 'default' }) ] + const index = buildSessionByAnyId(sessions, [], []) expect(resolvePinnedSessions(['foreign', 'local'], index, sessions, settled).map(s => s.id)).toEqual([ diff --git a/apps/desktop/src/app/gateway/hooks/use-gateway-boot.test.tsx b/apps/desktop/src/app/gateway/hooks/use-gateway-boot.test.tsx index 80a792394c..c0a4d4701f 100644 --- a/apps/desktop/src/app/gateway/hooks/use-gateway-boot.test.tsx +++ b/apps/desktop/src/app/gateway/hooks/use-gateway-boot.test.tsx @@ -9,7 +9,13 @@ import { selectConnection, setConnectionsRegistry } from '@/store/connections' -import { activeGateway, closeSecondaryGateways, ensureGatewayForAgent, isActivePrimary, requestGatewayForAgent } from '@/store/gateway' +import { + activeGateway, + closeSecondaryGateways, + ensureGatewayForAgent, + isActivePrimary, + requestGatewayForAgent +} from '@/store/gateway' import { reconnectGateway } from '@/store/gateway-reconnect' import { $gatewaySwitching, diff --git a/apps/desktop/src/app/gateway/hooks/use-gateway-boot.ts b/apps/desktop/src/app/gateway/hooks/use-gateway-boot.ts index ecaa77c00c..3299f62df1 100644 --- a/apps/desktop/src/app/gateway/hooks/use-gateway-boot.ts +++ b/apps/desktop/src/app/gateway/hooks/use-gateway-boot.ts @@ -742,6 +742,7 @@ export function useGatewayBoot({ const offEvent = gateway.onEvent(event => { const connectionId = activeGatewayConnectionId() + const scopedEvent = { ...event, profile: sourceProfile, diff --git a/apps/desktop/src/app/gateway/hooks/use-gateway-request.test.ts b/apps/desktop/src/app/gateway/hooks/use-gateway-request.test.ts index 20e54f34bd..b3dc038143 100644 --- a/apps/desktop/src/app/gateway/hooks/use-gateway-request.test.ts +++ b/apps/desktop/src/app/gateway/hooks/use-gateway-request.test.ts @@ -87,6 +87,7 @@ const remoteConnection = { function installRemoteDesktop() { let mintCount = 0 + const getConnection = vi.fn(async (profile?: null | string) => ({ authMode: 'token' as const, baseUrl: 'http://127.0.0.1:5151', @@ -95,15 +96,18 @@ function installRemoteDesktop() { token: 'local-token', wsUrl: 'ws://127.0.0.1:5151/api/ws?token=local' })) + const getConnectionFor = vi.fn(async ({ connectionId, profile }: { connectionId: string; profile: string }) => ({ ...remoteConnection, connectionId, profile })) + const getGatewayWsUrl = vi.fn(async () => ({ ok: true as const, wsUrl: 'ws://127.0.0.1:5151/api/ws?token=fresh-local' })) + const getGatewayWsUrlFor = vi.fn( async ({ connectionId, profile }: { connectionId: string; profile: string }): Promise => { mintCount += 1 @@ -132,6 +136,7 @@ function installPrimaryDesktop(authMode: 'oauth' | 'token') { token: 'primary-token', wsUrl: authMode === 'oauth' ? 'wss://gateway.example.test/api/ws?ticket=stale' : 'ws://127.0.0.1:5151/api/ws' })) + const getGatewayWsUrl = vi.fn(async (profile?: null | string) => ({ ok: true as const, wsUrl: @@ -139,6 +144,7 @@ function installPrimaryDesktop(authMode: 'oauth' | 'token') { ? `wss://gateway.example.test/api/ws?profile=${profile ?? 'default'}&ticket=fresh` : 'ws://127.0.0.1:5151/api/ws?token=fresh' })) + const getConnectionFor = vi.fn() const getGatewayWsUrlFor = vi.fn() @@ -183,6 +189,7 @@ async function expectSecondaryRecoveryFailure( gateway.connectionState = 'closed' vi.useFakeTimers() + const retry = request('session.resume').then( () => undefined, error => error diff --git a/apps/desktop/src/app/shell/model-catalog-menu.tsx b/apps/desktop/src/app/shell/model-catalog-menu.tsx index 7e971437c6..541a17d61c 100644 --- a/apps/desktop/src/app/shell/model-catalog-menu.tsx +++ b/apps/desktop/src/app/shell/model-catalog-menu.tsx @@ -145,8 +145,7 @@ export function ModelCatalogMenu({ // Gateway-first even with no session: a connected (possibly remote) // gateway owns the model catalog, including virtual providers the local // REST fallback can't know about (#53817). - queryFn: (): Promise => - requestModelOptions({ gateway, profile, request, sessionId }) + queryFn: (): Promise => requestModelOptions({ gateway, profile, request, sessionId }) }) const loading = modelOptions.isPending && !modelOptions.data diff --git a/apps/desktop/src/lib/connection-scoped.ts b/apps/desktop/src/lib/connection-scoped.ts index abca2bb827..2ea04e75cb 100644 --- a/apps/desktop/src/lib/connection-scoped.ts +++ b/apps/desktop/src/lib/connection-scoped.ts @@ -131,6 +131,7 @@ export function connectionScopedAtom( options?: ConnectionScopeOptions ): WritableAtom { const includeProfile = options?.includeProfile !== false + const entry: ScopedEntry = { $value: atom(fallback), applying: false, @@ -140,6 +141,7 @@ export function connectionScopedAtom( key, suffix: connectionScopeSuffix(activeConnection, includeProfile) } + entry.$value.set(loadEntry(entry)) registry.push(entry) diff --git a/apps/desktop/src/lib/model-options.test.ts b/apps/desktop/src/lib/model-options.test.ts index f7fde1e338..144013f215 100644 --- a/apps/desktop/src/lib/model-options.test.ts +++ b/apps/desktop/src/lib/model-options.test.ts @@ -124,22 +124,25 @@ describe('requestModelOptions', () => { provider: 'nous', providers: [{ models: ['chrome-model'], name: 'Nous', slug: 'nous' }] } + const routedPayload = { model: 'berry-model', provider: 'openai', providers: [{ models: ['berry-model'], name: 'OpenAI', slug: 'openai' }] } + const gateway = { request: vi.fn(() => Promise.resolve(gatewayPayload)) } + const request = vi.fn(() => Promise.resolve(routedPayload)) as unknown as ( method: string, params?: Record ) => Promise - await expect( - requestModelOptions({ gateway: gateway as never, request, sessionId: 'tile-1' }) - ).resolves.toBe(routedPayload) + await expect(requestModelOptions({ gateway: gateway as never, request, sessionId: 'tile-1' })).resolves.toBe( + routedPayload + ) expect(request).toHaveBeenCalledWith('model.options', { explicit_only: true, session_id: 'tile-1' }) expect(gateway.request).not.toHaveBeenCalled() @@ -151,13 +154,12 @@ describe('requestModelOptions', () => { provider: 'hermes-local', providers: [{ models: ['berry-local'], name: 'Hermes Local', slug: 'hermes-local' }] } + const request = vi.fn(() => Promise.reject(new Error('gateway request unavailable'))) vi.mocked(getGlobalModelOptions).mockResolvedValueOnce(restPayload) - await expect(requestModelOptions({ profile: 'berry', request, sessionId: 'tile-1' })).resolves.toEqual( - restPayload - ) + await expect(requestModelOptions({ profile: 'berry', request, sessionId: 'tile-1' })).resolves.toEqual(restPayload) expect(getGlobalModelOptions).toHaveBeenCalledWith({ explicitOnly: true }, 'berry') }) }) diff --git a/apps/desktop/src/plugins/hermes-bots/tests/hide-bot-chats.runtime.test.ts b/apps/desktop/src/plugins/hermes-bots/tests/hide-bot-chats.runtime.test.ts index 12e04aef2d..da3f06f2bc 100644 --- a/apps/desktop/src/plugins/hermes-bots/tests/hide-bot-chats.runtime.test.ts +++ b/apps/desktop/src/plugins/hermes-bots/tests/hide-bot-chats.runtime.test.ts @@ -4,14 +4,15 @@ import { afterEach, describe, expect, it, vi } from 'vitest' const gatewayState = atom<'closed' | 'open'>('closed') -const listPersistedSessions = vi.fn( - async (_route: unknown, options: { profile: string }) => ({ - sessions: [{ id: `${options.profile}-bot`, profile: options.profile, started_at: 1, title: 'Bot Chat' }] - }) -) +const listPersistedSessions = vi.fn(async (_route: unknown, options: { profile: string }) => ({ + sessions: [{ id: `${options.profile}-bot`, profile: options.profile, started_at: 1, title: 'Bot Chat' }] +})) const setPersistedSessionHidden = vi.fn( - async (_route: unknown, _options: { hidden: boolean; profile: string; sessionId: string }) => ({ hidden: true, ok: true }) + async (_route: unknown, _options: { hidden: boolean; profile: string; sessionId: string }) => ({ + hidden: true, + ok: true + }) ) const request = vi.fn(async (method: string) => @@ -86,7 +87,9 @@ describe('Bot Mode hidden-session reconciliation lifecycle', () => { expect.objectContaining({ hidden: true, profile: 'beta', sessionId: 'beta-bot' }) ]) ) - expect(request.mock.calls.some(([method]) => method === 'session.list' || method === 'session.set_hidden')).toBe(false) + expect(request.mock.calls.some(([method]) => method === 'session.list' || method === 'session.set_hidden')).toBe( + false + ) disposers.forEach(dispose => dispose()) const readsAtDispose = listPersistedSessions.mock.calls.length @@ -97,4 +100,4 @@ describe('Bot Mode hidden-session reconciliation lifecycle', () => { expect(listPersistedSessions).toHaveBeenCalledTimes(readsAtDispose) }) -}) \ No newline at end of file +}) diff --git a/apps/desktop/src/store/gateway-connection-scope.test.ts b/apps/desktop/src/store/gateway-connection-scope.test.ts index ead38b7c98..fbae09fafd 100644 --- a/apps/desktop/src/store/gateway-connection-scope.test.ts +++ b/apps/desktop/src/store/gateway-connection-scope.test.ts @@ -50,6 +50,7 @@ const { setPrimaryGateway, setPrimaryGatewayConnectionId } = await import('./gateway') + const { setApiRequestConnection } = await import('@/hermes') function installDesktop(): void { @@ -160,7 +161,7 @@ describe('pruneSecondaryGateways with registry-scoped entries', () => { expect(gatewayMocks.closed).toHaveLength(1) }) - it("does not let a remote tile keep-set pin a local same-named secondary", async () => { + it('does not let a remote tile keep-set pin a local same-named secondary', async () => { // Chrome is on another profile so 'default' is a real secondary, not the // spared active key. A homelab bot tile keep-set must keep only the // composite scope — the local 'default' socket still idles out. diff --git a/apps/desktop/src/store/gateway-shared-remote.test.ts b/apps/desktop/src/store/gateway-shared-remote.test.ts index face9eac77..e4bd178c49 100644 --- a/apps/desktop/src/store/gateway-shared-remote.test.ts +++ b/apps/desktop/src/store/gateway-shared-remote.test.ts @@ -37,13 +37,8 @@ vi.mock('@/store/session', () => ({ })) vi.mock('@/store/notify-baseline', () => ({ markNativeNotifyBaseline: vi.fn() })) -const { - $gateway, - closeSecondaryGateways, - configureGatewayRegistry, - ensureGatewayForProfile, - setPrimaryGateway -} = await import('./gateway') +const { $gateway, closeSecondaryGateways, configureGatewayRegistry, ensureGatewayForProfile, setPrimaryGateway } = + await import('./gateway') type DesktopStub = { getConnection: ReturnType } diff --git a/apps/desktop/src/store/session-states.test.ts b/apps/desktop/src/store/session-states.test.ts index 653e895e7e..e95c39b7ad 100644 --- a/apps/desktop/src/store/session-states.test.ts +++ b/apps/desktop/src/store/session-states.test.ts @@ -72,9 +72,7 @@ describe('foregroundSessionScopes', () => { } ]) - expect(foregroundSessionScopes()).toEqual( - new Set(['conn:cloud-a::default', 'conn:cloud-b::default']) - ) + expect(foregroundSessionScopes()).toEqual(new Set(['conn:cloud-a::default', 'conn:cloud-b::default'])) }) it('releases an idle pane owner when the pane closes', () => {