From 0807673e1f470a56a77cbd1bbd8f058ff63f2ea6 Mon Sep 17 00:00:00 2001 From: "hermes-seaeye[bot]" <307254004+hermes-seaeye[bot]@users.noreply.github.com> Date: Sat, 15 Aug 2026 06:22:02 +0000 Subject: [PATCH] fmt(js): `npm run fix` on merge (#86751) Co-authored-by: github-actions[bot] --- .../electron/connection-registry.test.ts | 38 +++++++++++++++---- apps/desktop/electron/connection-registry.ts | 30 ++++++++++++--- apps/desktop/electron/main.ts | 1 + apps/desktop/electron/updater-process.ts | 1 + .../app/chat/sidebar/cron-jobs-section.tsx | 6 ++- .../app/chat/sidebar/virtual-session-list.tsx | 4 +- .../desktop/src/app/cron/cron-actions.test.ts | 4 +- apps/desktop/src/app/cron/cron-actions.ts | 11 ++---- apps/desktop/src/app/cron/index.tsx | 22 ++++++++--- .../hooks/use-message-stream/gateway-event.ts | 6 ++- .../components/assistant-ui/thread/list.tsx | 6 ++- apps/desktop/src/store/cron.test.ts | 8 +--- .../store/suggestion-providers/skill.test.ts | 12 +++--- .../src/store/suggestion-providers/skill.ts | 6 ++- tests-js/react-dom-pair-compat.test.ts | 2 + 15 files changed, 110 insertions(+), 47 deletions(-) diff --git a/apps/desktop/electron/connection-registry.test.ts b/apps/desktop/electron/connection-registry.test.ts index eb4c025fbe..2ebe940aae 100644 --- a/apps/desktop/electron/connection-registry.test.ts +++ b/apps/desktop/electron/connection-registry.test.ts @@ -9,8 +9,7 @@ import assert from 'node:assert/strict' import { test } from 'vitest' -import type { - ConnectionRegistry} from './connection-registry'; +import type { ConnectionRegistry } from './connection-registry' import { agentHandle, connectionIdForLabel, @@ -75,7 +74,8 @@ test('uniqueLabel counts up (never "X 2 2") and clamps long candidates', () => { test('save rejects the reserved "local" id on non-local kinds', () => { assert.throws( - () => normalizeConnectionInput({ id: 'local', kind: 'remote', label: 'Sneaky', url: 'http://x:1' }, emptyRegistry()), + () => + normalizeConnectionInput({ id: 'local', kind: 'remote', label: 'Sneaky', url: 'http://x:1' }, emptyRegistry()), /reserved/ ) }) @@ -108,7 +108,14 @@ test('token only persists on token-auth remotes; oauth/cloud drop it', () => { // --- mergeConnectionInput (edit inheritance) --- test('merge preserves fields the editor does not carry (org, ssh extras)', () => { - const cloud = { authMode: 'oauth' as const, id: 'c', kind: 'cloud' as const, label: 'Cloud', org: 'nous', url: 'https://a.cloud' } + const cloud = { + authMode: 'oauth' as const, + id: 'c', + kind: 'cloud' as const, + label: 'Cloud', + org: 'nous', + url: 'https://a.cloud' + } const renamed = mergeConnectionInput({ id: 'c', kind: 'cloud', label: 'Renamed', url: 'https://a.cloud' }, cloud) assert.equal(renamed.org, 'nous') @@ -262,8 +269,22 @@ test('normalizeRegistry round-trips a valid registry unchanged in shape', () => primary: 'homelab', connections: [ { id: 'local', kind: 'local', label: 'This device' }, - { id: 'homelab', kind: 'remote', label: 'Homelab', url: 'http://10.0.0.5:9119', authMode: 'token', token: { v: 1 } }, - { id: 'cloud-1', kind: 'cloud', label: 'Hermes Cloud', url: 'https://a.hermes.cloud', authMode: 'oauth', org: 'nous' }, + { + id: 'homelab', + kind: 'remote', + label: 'Homelab', + url: 'http://10.0.0.5:9119', + authMode: 'token', + token: { v: 1 } + }, + { + id: 'cloud-1', + kind: 'cloud', + label: 'Hermes Cloud', + url: 'https://a.hermes.cloud', + authMode: 'oauth', + org: 'nous' + }, { id: 'spark', kind: 'ssh', label: 'Spark', host: 'spark1', user: 'tek', port: 2222 } ] } @@ -272,7 +293,10 @@ test('normalizeRegistry round-trips a valid registry unchanged in shape', () => assert.equal(registry.primary, 'homelab') assert.equal(registry.connections.length, 4) - assert.deepEqual(registry.connections.map(c => c.id), ['local', 'homelab', 'cloud-1', 'spark']) + assert.deepEqual( + registry.connections.map(c => c.id), + ['local', 'homelab', 'cloud-1', 'spark'] + ) assert.deepEqual(registry.connections[1].token, { v: 1 }) assert.equal(registry.connections[3].port, 2222) }) diff --git a/apps/desktop/electron/connection-registry.ts b/apps/desktop/electron/connection-registry.ts index 7f4e33b3e6..2156e74982 100644 --- a/apps/desktop/electron/connection-registry.ts +++ b/apps/desktop/electron/connection-registry.ts @@ -27,7 +27,13 @@ * these into the IPC layer and owns file I/O + secret encryption. */ -import { hostLabelFromBaseUrl, modeIsRemoteLike, normalizeRemoteBaseUrl, normalizeSshConfig, normAuthMode } from './connection-config' +import { + hostLabelFromBaseUrl, + modeIsRemoteLike, + normalizeRemoteBaseUrl, + normalizeSshConfig, + normAuthMode +} from './connection-config' export const REGISTRY_VERSION = 2 @@ -204,7 +210,12 @@ export function normalizeConnectionInput(input: ConnectionInput, registry: Conne throw new Error('The id "local" is reserved for the local connection.') } - const id = input.id || connectionIdForLabel(label, registry.connections.map(c => c.id)) + const id = + input.id || + connectionIdForLabel( + label, + registry.connections.map(c => c.id) + ) if (kind === 'ssh') { const ssh = normalizeSshConfig({ @@ -436,7 +447,10 @@ export function migrateV1ToRegistry(v1: unknown): ConnectionRegistry { ) const entry: RegistryConnection = { - id: connectionIdForLabel(label, connections.map(c => c.id)), + id: connectionIdForLabel( + label, + connections.map(c => c.id) + ), kind, label, url, @@ -473,12 +487,18 @@ export function migrateV1ToRegistry(v1: unknown): ConnectionRegistry { return existing } - const label = uniqueLabel(ssh.host, connections.map(c => c.label)) + const label = uniqueLabel( + ssh.host, + connections.map(c => c.label) + ) const { mode: _mode, ...sshFields } = ssh const entry: RegistryConnection = { - id: connectionIdForLabel(label, connections.map(c => c.id)), + id: connectionIdForLabel( + label, + connections.map(c => c.id) + ), kind: 'ssh', label, ...sshFields diff --git a/apps/desktop/electron/main.ts b/apps/desktop/electron/main.ts index 52b28ff6c2..e1f5676a46 100644 --- a/apps/desktop/electron/main.ts +++ b/apps/desktop/electron/main.ts @@ -7248,6 +7248,7 @@ async function discoverCloudAgents(org?: string) { const err = new Error( 'Your Hermes Cloud session has expired. Open Settings → Gateway and sign in again.' ) as any + err.needsCloudLogin = true err.cause = error throw err diff --git a/apps/desktop/electron/updater-process.ts b/apps/desktop/electron/updater-process.ts index 4cbb96247f..bb5e0a02c4 100644 --- a/apps/desktop/electron/updater-process.ts +++ b/apps/desktop/electron/updater-process.ts @@ -362,6 +362,7 @@ export function observeUpdaterHandoff( deps: ObserveUpdaterHandoffDeps = {} ): Promise { const setTimeoutFn = deps.setTimeoutFn ?? setTimeout + const clearTimeoutFn = deps.clearTimeoutFn ?? ((timer: unknown) => clearTimeout(timer as ReturnType)) diff --git a/apps/desktop/src/app/chat/sidebar/cron-jobs-section.tsx b/apps/desktop/src/app/chat/sidebar/cron-jobs-section.tsx index 30fb25bde1..8be72aba34 100644 --- a/apps/desktop/src/app/chat/sidebar/cron-jobs-section.tsx +++ b/apps/desktop/src/app/chat/sidebar/cron-jobs-section.tsx @@ -346,7 +346,11 @@ function CronJobSidebarRow({ onClick={onTrigger} type="button" > - {busy ? : } + {busy ? ( + + ) : ( + + )} diff --git a/apps/desktop/src/app/chat/sidebar/virtual-session-list.tsx b/apps/desktop/src/app/chat/sidebar/virtual-session-list.tsx index 2a10fd9a3f..48cbe68396 100644 --- a/apps/desktop/src/app/chat/sidebar/virtual-session-list.tsx +++ b/apps/desktop/src/app/chat/sidebar/virtual-session-list.tsx @@ -161,7 +161,9 @@ export const VirtualSessionList: FC = ({ )} ref={scrollerRef} > -
{rows}
+
+ {rows} +
) } diff --git a/apps/desktop/src/app/cron/cron-actions.test.ts b/apps/desktop/src/app/cron/cron-actions.test.ts index 61e6dd1aa3..654f65b6b7 100644 --- a/apps/desktop/src/app/cron/cron-actions.test.ts +++ b/apps/desktop/src/app/cron/cron-actions.test.ts @@ -143,9 +143,7 @@ describe('mutateAndRefreshCronJobs', () => { it('allows overlapping same-profile mutations to authoritatively refresh', async () => { const first = deferred() const second = deferred() - getCronJobs - .mockResolvedValueOnce([{ id: 'after-second' }]) - .mockResolvedValueOnce([{ id: 'after-both' }]) + getCronJobs.mockResolvedValueOnce([{ id: 'after-second' }]).mockResolvedValueOnce([{ id: 'after-both' }]) const firstResult = mutateAndRefreshCronJobs('work', () => first.promise) const secondResult = mutateAndRefreshCronJobs('work', () => second.promise) diff --git a/apps/desktop/src/app/cron/cron-actions.ts b/apps/desktop/src/app/cron/cron-actions.ts index 95cc07c63e..7fafe13c59 100644 --- a/apps/desktop/src/app/cron/cron-actions.ts +++ b/apps/desktop/src/app/cron/cron-actions.ts @@ -18,10 +18,7 @@ export interface CronMutationRefreshResult extends CronTriggerRefreshResult { value: T | null } -async function refreshForGeneration( - profile: string, - request: CronJobsRequest -): Promise { +async function refreshForGeneration(profile: string, request: CronJobsRequest): Promise { try { const jobs = await getCronJobs(profile) @@ -90,9 +87,7 @@ export async function triggerAndRefreshCronJobs( jobId: string, profile: 'all' | string ): Promise { - const { value: _value, ...result } = await mutateAndRefreshCronJobs(profile, () => - triggerCronJob(jobId) - ) + const { value: _value, ...result } = await mutateAndRefreshCronJobs(profile, () => triggerCronJob(jobId)) return result -} \ No newline at end of file +} diff --git a/apps/desktop/src/app/cron/index.tsx b/apps/desktop/src/app/cron/index.tsx index 1b6e6ab156..9bf6923b5c 100644 --- a/apps/desktop/src/app/cron/index.tsx +++ b/apps/desktop/src/app/cron/index.tsx @@ -541,9 +541,7 @@ export function CronView({ onClose, onOpenSession, setStatusbarItemGroup: _setSt setDeleting(true) try { - const { refreshError, stale } = await mutateAndRefreshCronJobs(profile, () => - deleteCronJob(pendingDelete.id) - ) + const { refreshError, stale } = await mutateAndRefreshCronJobs(profile, () => deleteCronJob(pendingDelete.id)) if (stale) { return @@ -564,7 +562,11 @@ export function CronView({ onClose, onOpenSession, setStatusbarItemGroup: _setSt async function handleEditorSave(values: EditorValues) { if (editor.mode === 'create') { - const { value: created, refreshError, stale } = await mutateAndRefreshCronJobs(profile, () => + const { + value: created, + refreshError, + stale + } = await mutateAndRefreshCronJobs(profile, () => createCronJob({ prompt: values.prompt, schedule: values.schedule, @@ -586,7 +588,11 @@ export function CronView({ onClose, onOpenSession, setStatusbarItemGroup: _setSt } else if (editor.mode === 'edit') { const scriptOnlyJob = jobIsScriptOnly(editor.job) - const { value: updated, refreshError, stale } = await mutateAndRefreshCronJobs(profile, () => + const { + value: updated, + refreshError, + stale + } = await mutateAndRefreshCronJobs(profile, () => updateCronJob(editor.job.id, cronEditorUpdates(values, { scriptOnlyJob })) ) @@ -612,7 +618,11 @@ export function CronView({ onClose, onOpenSession, setStatusbarItemGroup: _setSt async function handleBlueprintCreate(blueprint: AutomationBlueprint, values: Record) { const writableProfile = profileScope === ALL_PROFILES ? 'default' : profileScope - const { value: job, refreshError, stale } = await mutateAndRefreshCronJobs(profile, () => + const { + value: job, + refreshError, + stale + } = await mutateAndRefreshCronJobs(profile, () => instantiateAutomationBlueprint({ blueprint: blueprint.key, values }, writableProfile) ) diff --git a/apps/desktop/src/app/session/hooks/use-message-stream/gateway-event.ts b/apps/desktop/src/app/session/hooks/use-message-stream/gateway-event.ts index 238f3c9547..15eb0d6171 100644 --- a/apps/desktop/src/app/session/hooks/use-message-stream/gateway-event.ts +++ b/apps/desktop/src/app/session/hooks/use-message-stream/gateway-event.ts @@ -12,7 +12,11 @@ import { translateNow } from '@/i18n' import { type GatewayEventPayload, textPart } from '@/lib/chat-messages' import { coerceGatewayText, coerceThinkingText, normalizePersonalityValue } from '@/lib/chat-runtime' import { playCompletionSound } from '@/lib/completion-sound' -import { approvalReplaySessionId, resolveGatewayEventSessionId, UNSCOPED_STREAM_EVENT_TYPES } from '@/lib/gateway-events' +import { + approvalReplaySessionId, + resolveGatewayEventSessionId, + UNSCOPED_STREAM_EVENT_TYPES +} from '@/lib/gateway-events' import { triggerHaptic } from '@/lib/haptics' import { modelOptionsQueryKey } from '@/lib/model-options' import { isProviderSetupErrorMessage } from '@/lib/provider-setup-errors' diff --git a/apps/desktop/src/components/assistant-ui/thread/list.tsx b/apps/desktop/src/components/assistant-ui/thread/list.tsx index 9db5aedcb1..94afcf0474 100644 --- a/apps/desktop/src/components/assistant-ui/thread/list.tsx +++ b/apps/desktop/src/components/assistant-ui/thread/list.tsx @@ -577,7 +577,11 @@ const ThreadMessageListInner: FC = ({ // can be overwritten by another mounted pane; leave a scrolled-up reader // exactly where they were. useEffect( - () => subscribeToThreadForeground(() => isAtBottom, () => void scrollToBottom()), + () => + subscribeToThreadForeground( + () => isAtBottom, + () => void scrollToBottom() + ), [isAtBottom, scrollToBottom] ) diff --git a/apps/desktop/src/store/cron.test.ts b/apps/desktop/src/store/cron.test.ts index e4db02e1f5..2e69343548 100644 --- a/apps/desktop/src/store/cron.test.ts +++ b/apps/desktop/src/store/cron.test.ts @@ -1,12 +1,6 @@ import { beforeEach, describe, expect, it } from 'vitest' -import { - $cronJobs, - beginCronJobsRequest, - commitCronJobsRequest, - setCronJobs, - updateCronJobs -} from './cron' +import { $cronJobs, beginCronJobsRequest, commitCronJobsRequest, setCronJobs, updateCronJobs } from './cron' const oldJob = { id: 'old' } as never const newJob = { id: 'new' } as never diff --git a/apps/desktop/src/store/suggestion-providers/skill.test.ts b/apps/desktop/src/store/suggestion-providers/skill.test.ts index 3661a0aa52..f85c29675b 100644 --- a/apps/desktop/src/store/suggestion-providers/skill.test.ts +++ b/apps/desktop/src/store/suggestion-providers/skill.test.ts @@ -91,12 +91,12 @@ describe('skillTouchedInMessages', () => { }) it('matches qualified skill names (category/name, plugin:name)', () => { - expect(skillTouchedInMessages('hermes-agent-dev', [toolCall('skill_view', { name: 'github/hermes-agent-dev' })])).toBe( - true - ) - expect(skillTouchedInMessages('writing-plans', [toolCall('skill_view', { name: 'superpowers:writing-plans' })])).toBe( - true - ) + expect( + skillTouchedInMessages('hermes-agent-dev', [toolCall('skill_view', { name: 'github/hermes-agent-dev' })]) + ).toBe(true) + expect( + skillTouchedInMessages('writing-plans', [toolCall('skill_view', { name: 'superpowers:writing-plans' })]) + ).toBe(true) }) it('falls back to argsText when args were not parsed', () => { diff --git a/apps/desktop/src/store/suggestion-providers/skill.ts b/apps/desktop/src/store/suggestion-providers/skill.ts index 3e46e943cb..6b203aad55 100644 --- a/apps/desktop/src/store/suggestion-providers/skill.ts +++ b/apps/desktop/src/store/suggestion-providers/skill.ts @@ -149,7 +149,11 @@ export function skillTouchedInMessages(skillName: string, messages: readonly Cha for (const message of messages) { for (const part of message.parts) { - if (part.type === 'tool-call' && SKILL_TOOL_NAMES.has(part.toolName) && argNamesSkill(skillArgName(part), skillName)) { + if ( + part.type === 'tool-call' && + SKILL_TOOL_NAMES.has(part.toolName) && + argNamesSkill(skillArgName(part), skillName) + ) { return true } diff --git a/tests-js/react-dom-pair-compat.test.ts b/tests-js/react-dom-pair-compat.test.ts index 839d37f83d..46dec4280e 100644 --- a/tests-js/react-dom-pair-compat.test.ts +++ b/tests-js/react-dom-pair-compat.test.ts @@ -50,6 +50,7 @@ function workspaceManifests(): { name: string, manifest: Manifest }[] { for (const pattern of patterns) { // The globs in use are plain paths or a single trailing ``/*``. const parent = pattern.endsWith('/*') ? path.join(REPO_ROOT, pattern.slice(0, -2)) : null + const dirs = parent === null ? [pattern] : fs.existsSync(parent) @@ -78,6 +79,7 @@ test('workspaces declaring react and react-dom pin them to the same exact versio if (react !== reactDom) { offenders.push(`${name} declares react"${react}" but react-dom"${reactDom}"`) + continue }