mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
fmt(js): npm run fix on merge (#72411)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
af1cc1c245
commit
8c36cd4670
14 changed files with 53 additions and 77 deletions
|
|
@ -9,12 +9,7 @@ import { EventEmitter } from 'node:events'
|
|||
|
||||
import { describe, test } from 'vitest'
|
||||
|
||||
import {
|
||||
formatFoundInPage,
|
||||
installFoundInPageForwarder,
|
||||
performFind,
|
||||
stopFind
|
||||
} from './find-in-page'
|
||||
import { formatFoundInPage, installFoundInPageForwarder, performFind, stopFind } from './find-in-page'
|
||||
|
||||
// Minimal webContents stub. The Electron.WebContents type is huge, so we
|
||||
// model just the slice the helpers touch (`isDestroyed`, `findInPage`,
|
||||
|
|
@ -90,10 +85,10 @@ describe('formatFoundInPage', () => {
|
|||
})
|
||||
|
||||
test('null / undefined inputs still produce a well-formed payload', () => {
|
||||
assert.deepEqual(
|
||||
formatFoundInPage(null as unknown as { activeMatchOrdinal?: number; matches?: number }),
|
||||
{ activeMatchOrdinal: 0, count: 0 }
|
||||
)
|
||||
assert.deepEqual(formatFoundInPage(null as unknown as { activeMatchOrdinal?: number; matches?: number }), {
|
||||
activeMatchOrdinal: 0,
|
||||
count: 0
|
||||
})
|
||||
assert.deepEqual(formatFoundInPage(undefined), { activeMatchOrdinal: 0, count: 0 })
|
||||
})
|
||||
})
|
||||
|
|
@ -102,33 +97,25 @@ describe('performFind', () => {
|
|||
test('forwards the query and options to webContents.findInPage', () => {
|
||||
const wc = makeFakeWebContents()
|
||||
performFind(asWC(wc), 'hello', { forward: true, findNext: false })
|
||||
assert.deepEqual(wc.calls.find, [
|
||||
{ query: 'hello', options: { forward: true, findNext: false } }
|
||||
])
|
||||
assert.deepEqual(wc.calls.find, [{ query: 'hello', options: { forward: true, findNext: false } }])
|
||||
})
|
||||
|
||||
test('defaults forward to true when omitted', () => {
|
||||
const wc = makeFakeWebContents()
|
||||
performFind(asWC(wc), 'x', { findNext: true })
|
||||
assert.deepEqual(wc.calls.find, [
|
||||
{ query: 'x', options: { forward: true, findNext: true } }
|
||||
])
|
||||
assert.deepEqual(wc.calls.find, [{ query: 'x', options: { forward: true, findNext: true } }])
|
||||
})
|
||||
|
||||
test('defaults findNext to false when omitted', () => {
|
||||
const wc = makeFakeWebContents()
|
||||
performFind(asWC(wc), 'x', { forward: false })
|
||||
assert.deepEqual(wc.calls.find, [
|
||||
{ query: 'x', options: { forward: false, findNext: false } }
|
||||
])
|
||||
assert.deepEqual(wc.calls.find, [{ query: 'x', options: { forward: false, findNext: false } }])
|
||||
})
|
||||
|
||||
test('treats null / non-object options as "all defaults"', () => {
|
||||
const wc = makeFakeWebContents()
|
||||
performFind(asWC(wc), 'x', null)
|
||||
assert.deepEqual(wc.calls.find, [
|
||||
{ query: 'x', options: { forward: true, findNext: false } }
|
||||
])
|
||||
assert.deepEqual(wc.calls.find, [{ query: 'x', options: { forward: true, findNext: false } }])
|
||||
})
|
||||
|
||||
test('coerces a non-string query to string (defensive against bad renderer payloads)', () => {
|
||||
|
|
@ -178,18 +165,14 @@ describe('installFoundInPageForwarder', () => {
|
|||
// Drive the fake's emit directly — this exercises the same code path
|
||||
// as Electron's actual `webContents.emit('found-in-page', …)`.
|
||||
wc.emit('found-in-page', {}, { activeMatchOrdinal: 2, matches: 5 })
|
||||
assert.deepEqual(wc.calls.send, [
|
||||
{ channel: 'hermes:found-in-page', payload: { activeMatchOrdinal: 2, count: 5 } }
|
||||
])
|
||||
assert.deepEqual(wc.calls.send, [{ channel: 'hermes:found-in-page', payload: { activeMatchOrdinal: 2, count: 5 } }])
|
||||
})
|
||||
|
||||
test('handles missing fields without throwing', () => {
|
||||
const wc = makeFakeWebContents()
|
||||
installFoundInPageForwarder(asWC(wc))
|
||||
wc.emit('found-in-page', {}, {})
|
||||
assert.deepEqual(wc.calls.send, [
|
||||
{ channel: 'hermes:found-in-page', payload: { activeMatchOrdinal: 0, count: 0 } }
|
||||
])
|
||||
assert.deepEqual(wc.calls.send, [{ channel: 'hermes:found-in-page', payload: { activeMatchOrdinal: 0, count: 0 } }])
|
||||
})
|
||||
|
||||
test('skips send when webContents is destroyed at fire time', () => {
|
||||
|
|
|
|||
|
|
@ -41,10 +41,7 @@ export interface FoundInPagePayload {
|
|||
* keeping the projection explicit makes the wire shape auditable and keeps
|
||||
* tests independent of the runtime type.
|
||||
*/
|
||||
export function formatFoundInPage(result: {
|
||||
activeMatchOrdinal?: number
|
||||
matches?: number
|
||||
}): FoundInPagePayload {
|
||||
export function formatFoundInPage(result: { activeMatchOrdinal?: number; matches?: number }): FoundInPagePayload {
|
||||
return {
|
||||
activeMatchOrdinal: Number(result?.activeMatchOrdinal ?? 0),
|
||||
count: Number(result?.matches ?? 0)
|
||||
|
|
@ -102,9 +99,7 @@ export function stopFind(
|
|||
* highlight matches in THAT window, and the match counter must reflect
|
||||
* THAT window's DOM, not the primary's.
|
||||
*/
|
||||
export function installFoundInPageForwarder(
|
||||
webContents: Electron.WebContents | null | undefined
|
||||
): () => void {
|
||||
export function installFoundInPageForwarder(webContents: Electron.WebContents | null | undefined): () => void {
|
||||
if (!webContents || webContents.isDestroyed()) {
|
||||
return () => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10188,6 +10188,7 @@ ipcMain.handle('hermes:quick-entry:settings:get', async () => {
|
|||
|
||||
ipcMain.handle('hermes:quick-entry:settings:set', async (_event, patch) => {
|
||||
const current = readQuickEntrySettings()
|
||||
|
||||
const next = sanitizeQuickEntrySettings({
|
||||
enabled: patch?.enabled === undefined ? current.enabled : patch.enabled === true,
|
||||
shortcut: typeof patch?.shortcut === 'string' && patch.shortcut.trim() ? patch.shortcut : current.shortcut
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
import { type RefObject, useCallback, useEffect, useMemo } from 'react'
|
||||
|
||||
import {
|
||||
caretOffsetInEditor,
|
||||
composerPlainText,
|
||||
placeCaretAtOffset,
|
||||
renderComposerContents
|
||||
} from '../rich-editor'
|
||||
import { caretOffsetInEditor, composerPlainText, placeCaretAtOffset, renderComposerContents } from '../rich-editor'
|
||||
import { type ComposerSnapshot, createComposerUndoHistory } from '../undo-history'
|
||||
|
||||
interface UseComposerUndoArgs {
|
||||
|
|
|
|||
|
|
@ -193,7 +193,11 @@ describe('caret offsets in composerPlainText coordinates', () => {
|
|||
})
|
||||
|
||||
it('counts a chip as its whole @kind:value text', () => {
|
||||
editor.append(document.createTextNode('see '), refChipElement('file', '`src/a.ts`'), document.createTextNode(' now'))
|
||||
editor.append(
|
||||
document.createTextNode('see '),
|
||||
refChipElement('file', '`src/a.ts`'),
|
||||
document.createTextNode(' now')
|
||||
)
|
||||
|
||||
const chipText = '@file:`src/a.ts`'
|
||||
// Caret at the very end = everything before it.
|
||||
|
|
|
|||
|
|
@ -81,12 +81,14 @@ function rect(top: number, left: number, width: number, height: number): DOMRect
|
|||
function installRaf() {
|
||||
let nextId = 1
|
||||
const frames = new Map<number, FrameRequestCallback>()
|
||||
|
||||
const request = vi.fn((callback: FrameRequestCallback) => {
|
||||
const id = nextId++
|
||||
frames.set(id, callback)
|
||||
|
||||
return id
|
||||
})
|
||||
|
||||
const cancel = vi.fn((id: number) => {
|
||||
frames.delete(id)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -102,9 +102,7 @@ describe('refreshSessions identity + loading hygiene', () => {
|
|||
expect(first.map(s => s.id)).toEqual(['a', 'b'])
|
||||
|
||||
// Second refresh returns fresh (but equal) row objects, as the API does.
|
||||
listSidebarSessions.mockResolvedValue(
|
||||
sidebar({ sessions: [row('a'), row('b')] })
|
||||
)
|
||||
listSidebarSessions.mockResolvedValue(sidebar({ sessions: [row('a'), row('b')] }))
|
||||
|
||||
await act(async () => {
|
||||
await result.current.refreshSessions()
|
||||
|
|
@ -123,9 +121,7 @@ describe('refreshSessions identity + loading hygiene', () => {
|
|||
|
||||
const first = $sessions.get()
|
||||
|
||||
listSidebarSessions.mockResolvedValue(
|
||||
sidebar({ sessions: [row('a', { last_active: 2000, title: 'Renamed' })] })
|
||||
)
|
||||
listSidebarSessions.mockResolvedValue(sidebar({ sessions: [row('a', { last_active: 2000, title: 'Renamed' })] }))
|
||||
|
||||
await act(async () => {
|
||||
await result.current.refreshSessions()
|
||||
|
|
@ -197,9 +193,7 @@ describe('refreshSessions batches slices into one request', () => {
|
|||
const cron = [row('c1', { source: 'cron', title: 'nightly' })]
|
||||
const messaging = [row('m1', { source: 'telegram', title: 'tg chat' })]
|
||||
|
||||
listSidebarSessions.mockResolvedValue(
|
||||
sidebar({ sessions: recents }, cron, messaging)
|
||||
)
|
||||
listSidebarSessions.mockResolvedValue(sidebar({ sessions: recents }, cron, messaging))
|
||||
|
||||
const { result } = renderHook(() => useSessionListActions({ profileScope: 'default' }))
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,16 @@ export const Thread: FC<{
|
|||
/>
|
||||
)
|
||||
}),
|
||||
[cwd, gateway, hasBranchInNewChat, hasCancel, hasDismissError, hasRestoreToMessage, requestRestoreConfirm, sessionId]
|
||||
[
|
||||
cwd,
|
||||
gateway,
|
||||
hasBranchInNewChat,
|
||||
hasCancel,
|
||||
hasDismissError,
|
||||
hasRestoreToMessage,
|
||||
requestRestoreConfirm,
|
||||
sessionId
|
||||
]
|
||||
)
|
||||
|
||||
const emptyPlaceholder = intro ? (
|
||||
|
|
|
|||
|
|
@ -176,10 +176,7 @@ export function FindBar() {
|
|||
/>
|
||||
|
||||
{matchLabel && (
|
||||
<span
|
||||
aria-live="polite"
|
||||
className="min-w-[3rem] text-center text-[0.6875rem] text-(--ui-text-tertiary)"
|
||||
>
|
||||
<span aria-live="polite" className="min-w-[3rem] text-center text-[0.6875rem] text-(--ui-text-tertiary)">
|
||||
{matchLabel}
|
||||
</span>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -84,12 +84,14 @@ function installWindowStateBridge() {
|
|||
function installRaf() {
|
||||
let nextId = 1
|
||||
const frames = new Map<number, FrameRequestCallback>()
|
||||
|
||||
const request = vi.fn((callback: FrameRequestCallback) => {
|
||||
const id = nextId++
|
||||
frames.set(id, callback)
|
||||
|
||||
return id
|
||||
})
|
||||
|
||||
const cancel = vi.fn((id: number) => {
|
||||
frames.delete(id)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -173,10 +173,13 @@ export function usePetRoam({
|
|||
const delay = Math.max(0, pauseUntil - now)
|
||||
|
||||
if (delay > 0) {
|
||||
pauseTimer = window.setTimeout(() => {
|
||||
pauseTimer = 0
|
||||
step(performance.now())
|
||||
}, Math.min(delay, PAUSE_POLL_MS))
|
||||
pauseTimer = window.setTimeout(
|
||||
() => {
|
||||
pauseTimer = 0
|
||||
step(performance.now())
|
||||
},
|
||||
Math.min(delay, PAUSE_POLL_MS)
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
|||
9
apps/desktop/src/global.d.ts
vendored
9
apps/desktop/src/global.d.ts
vendored
|
|
@ -271,14 +271,9 @@ declare global {
|
|||
// searches that window (not the primary). `onFoundInPage` returns the
|
||||
// unsubscribe fn; the renderer wires it via `initFindInPageListener`
|
||||
// in store/find-in-page.ts and tears it down when the FindBar unmounts.
|
||||
findInPage: (
|
||||
query: string,
|
||||
options?: { forward?: boolean; findNext?: boolean }
|
||||
) => Promise<{ count: number }>
|
||||
findInPage: (query: string, options?: { forward?: boolean; findNext?: boolean }) => Promise<{ count: number }>
|
||||
stopFindInPage: () => Promise<void>
|
||||
onFoundInPage: (
|
||||
callback: (result: { activeMatchOrdinal: number; count: number }) => void
|
||||
) => () => void
|
||||
onFoundInPage: (callback: (result: { activeMatchOrdinal: number; count: number }) => void) => () => void
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ if (winParam === 'overlay') {
|
|||
renders in a single sash drag). Radix's provider holds only
|
||||
refs and stable callbacks, so hoisting is what it's for. */}
|
||||
<RootTooltipProvider>
|
||||
{/* useTransitions={false}: react-router v7's HashRouter wraps every
|
||||
{/* useTransitions={false}: react-router v7's HashRouter wraps every
|
||||
route state update in React.startTransition() by default. In
|
||||
React 19's concurrent renderer, transitions are non-urgent — React
|
||||
can yield mid-render and resume later. When the app is under load
|
||||
|
|
@ -62,9 +62,9 @@ if (winParam === 'overlay') {
|
|||
the route change commit. The session sidebar highlight + main pane
|
||||
both freeze for seconds despite the main thread being free.
|
||||
Disabling transitions makes navigate() commit at default priority. */}
|
||||
<HashRouter useTransitions={false}>
|
||||
<App />
|
||||
</HashRouter>
|
||||
<HashRouter useTransitions={false}>
|
||||
<App />
|
||||
</HashRouter>
|
||||
</RootTooltipProvider>
|
||||
</HapticsProvider>
|
||||
</ThemeProvider>
|
||||
|
|
|
|||
|
|
@ -564,9 +564,7 @@ export const coreCommands: SlashCommand[] = [
|
|||
// `/focus status` reports without writing, matching the CLI surface.
|
||||
if (mode === 'status' || mode === 'show' || mode === '?') {
|
||||
return ctx.transcript.sys(
|
||||
current
|
||||
? 'focus view on — only your prompt and the final response'
|
||||
: 'focus view off'
|
||||
current ? 'focus view on — only your prompt and the final response' : 'focus view off'
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -584,9 +582,7 @@ export const coreCommands: SlashCommand[] = [
|
|||
|
||||
queueMicrotask(() =>
|
||||
ctx.transcript.sys(
|
||||
next
|
||||
? 'focus view enabled — just your prompt and the final response'
|
||||
: 'focus view disabled'
|
||||
next ? 'focus view enabled — just your prompt and the final response' : 'focus view disabled'
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue