chore(desktop): keep the diff surgical

Revert the repo-wide prettier churn the earlier fmt pass pulled into files
unrelated to this work; run prettier/eslint scoped to the touched files only.
This commit is contained in:
Brooklyn Nicholson 2026-06-28 21:30:14 -05:00
parent 6776b2f9b5
commit 5a2906a11b
11 changed files with 55 additions and 30 deletions

View file

@ -2266,7 +2266,9 @@ async function handOffWindowsBootstrapRecovery(reason) {
// --repair (full venv recreate) and drove reinstall loops. The venv interpreter
// and the bootstrap-complete marker are present earlier and are better signals.
const haveRealInstall =
fileExists(venvPython) || fileExists(venvHermes) || fileExists(path.join(updateRoot, '.hermes-bootstrap-complete'))
fileExists(venvPython) ||
fileExists(venvHermes) ||
fileExists(path.join(updateRoot, '.hermes-bootstrap-complete'))
const updaterArgs = haveRealInstall ? ['--update', '--branch', branch] : ['--repair', '--branch', branch]
await releaseBackendLockForUpdate(updateRoot)

View file

@ -14,9 +14,9 @@ const OVERLAY_FALLBACK_WIDTH = 144
* the Electron overlay (Windows, WSLg, and plain Linux KDE/GNOME), so they all
* reserve the fallback width.
*
* @param {{ isMac?: boolean }} opts
* @param {{ isWindows?: boolean, isWsl?: boolean, isMac?: boolean }} opts
*/
function nativeOverlayWidth({ isMac = false } = {}) {
function nativeOverlayWidth({ isWindows = false, isWsl = false, isMac = false } = {}) {
if (isMac) return 0
return OVERLAY_FALLBACK_WIDTH
}

View file

@ -43,13 +43,21 @@ test('findOnPath tries PATHEXT extensions before the bare (empty) name on Window
test('Windows bootstrap recovery chooses --update when any real-install signal is present', () => {
const source = readMain()
assert.match(source, /const haveRealInstall =/, 'recovery must compute haveRealInstall')
assert.match(source, /fileExists\(venvPython\)/, 'recovery must accept the venv interpreter as a real-install signal')
assert.match(
source,
/fileExists\(venvPython\)/,
'recovery must accept the venv interpreter as a real-install signal'
)
assert.match(
source,
/\.hermes-bootstrap-complete/,
'recovery must accept the bootstrap-complete marker as a real-install signal'
)
assert.match(source, /updaterArgs = haveRealInstall \? \['--update'/, 'updaterArgs must gate on haveRealInstall')
assert.match(
source,
/updaterArgs = haveRealInstall \? \['--update'/,
'updaterArgs must gate on haveRealInstall'
)
// The old too-narrow check (only venv\Scripts\hermes.exe) must not return.
assert.doesNotMatch(
source,

View file

@ -1149,7 +1149,8 @@ export function ChatSidebar({
const showSessionSkeletons = sessionsLoading && sortedSessions.length === 0
const showSessionSections = showSessionSkeletons || sortedSessions.length > 0 || projectModel.length > 0
const showSessionSections =
showSessionSkeletons || sortedSessions.length > 0 || projectModel.length > 0
// Each reorderable list reports its OWN new id order; persisting is a direct,
// typed write — no id-prefix sniffing to figure out which level moved.
@ -1627,7 +1628,12 @@ function SidebarBlankState({ onNewProject }: { onNewProject: () => void }) {
<div className="flex flex-col items-center gap-2">
<Codicon className="text-(--ui-text-quaternary)" name="root-folder" size="1.25rem" />
<p className="text-xs text-(--ui-text-tertiary)">{s.noSessions}</p>
<Button className="mt-0.5 text-(--ui-text-secondary)" onClick={onNewProject} size="sm" variant="ghost">
<Button
className="mt-0.5 text-(--ui-text-secondary)"
onClick={onNewProject}
size="sm"
variant="ghost"
>
<Codicon name="add" size="0.75rem" />
{s.projects.newButton}
</Button>

View file

@ -149,7 +149,10 @@ export function ProjectDialog() {
return (
<Dialog onOpenChange={onOpenChange} open={open}>
<DialogContent className="max-w-md" onInteractOutside={event => event.preventDefault()}>
<DialogContent
className="max-w-md"
onInteractOutside={event => event.preventDefault()}
>
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
{mode === 'create' && <DialogDescription>{p.createDesc}</DialogDescription>}

View file

@ -9,7 +9,16 @@ import { getActionStatus, getLogs, getStatus, getUsageAnalytics, restartGateway,
import type { ActionStatusResponse, AnalyticsResponse, StatusResponse } from '@/hermes'
import { useI18n } from '@/i18n'
import { sessionTitle } from '@/lib/chat-runtime'
import { Activity, AlertCircle, BarChart3, Bookmark, BookmarkFilled, Download, MessageCircle, Trash2 } from '@/lib/icons'
import {
Activity,
AlertCircle,
BarChart3,
Bookmark,
BookmarkFilled,
Download,
MessageCircle,
Trash2
} from '@/lib/icons'
import { exportSession } from '@/lib/session-export'
import { cn } from '@/lib/utils'
import { upsertDesktopActionTask } from '@/store/activity'

View file

@ -685,9 +685,7 @@ export function useSessionActions({
if (warmHit) {
const cachedRuntimeId = warmHit.runtimeId
const cachedState = warmHit.state
const stored =
$sessions.get().find(session => sessionMatchesStoredId(session, storedSessionId)) ?? storedForProfile
const stored = $sessions.get().find(session => sessionMatchesStoredId(session, storedSessionId)) ?? storedForProfile
const cachedViewState =
!cachedState.model && stored?.model != null
@ -754,10 +752,7 @@ export function useSessionActions({
setSelectedStoredSessionId(storedSessionId)
selectedStoredSessionIdRef.current = storedSessionId
setSessionStartedAt(Date.now())
const stored =
$sessions.get().find(session => sessionMatchesStoredId(session, storedSessionId)) ?? storedForProfile
const stored = $sessions.get().find(session => sessionMatchesStoredId(session, storedSessionId)) ?? storedForProfile
applyStoredSessionPreviewRuntimeInfo(stored)
if (stored) {

View file

@ -191,7 +191,9 @@ export function ModelSettings({ onMainModelChanged }: ModelSettingsProps) {
// MoA reference/aggregator slots must never be the moa virtual provider —
// that would create a recursive MoA tree (the backend rejects it on save).
// Hide it from the slot selectors so it isn't offered as a dead choice.
const moaSlotProviderOptions = providerOptions.filter(provider => (provider.slug || '').toLowerCase() !== 'moa')
const moaSlotProviderOptions = providerOptions.filter(
provider => (provider.slug || '').toLowerCase() !== 'moa'
)
const selectedProviderRow = useMemo(
() => providers.find(provider => provider.slug === selectedProvider),
@ -781,7 +783,6 @@ export function ModelSettings({ onMainModelChanged }: ModelSettingsProps) {
...moa,
default_preset: selectedMoaPreset || moa.default_preset
}
void saveMoa(next)
}}
size="sm"
@ -799,14 +800,12 @@ export function ModelSettings({ onMainModelChanged }: ModelSettingsProps) {
const presets = { ...moa.presets }
delete presets[selectedMoaPreset]
const fallback = Object.keys(presets)[0]
const next: MoaConfigResponse = {
...moa,
presets,
default_preset: moa.default_preset === selectedMoaPreset ? fallback : moa.default_preset,
active_preset: moa.active_preset === selectedMoaPreset ? '' : moa.active_preset
}
setSelectedMoaPreset(Object.keys(moa.presets).find(name => name !== selectedMoaPreset) || '')
void saveMoa(next)
}}
@ -825,7 +824,6 @@ export function ModelSettings({ onMainModelChanged }: ModelSettingsProps) {
disabled={!newMoaPresetName.trim() || !!moa.presets[newMoaPresetName.trim()] || applying}
onClick={() => {
const name = newMoaPresetName.trim()
const next: MoaConfigResponse = {
...moa,
presets: {
@ -833,7 +831,6 @@ export function ModelSettings({ onMainModelChanged }: ModelSettingsProps) {
[name]: { ...currentMoaPreset, reference_models: [...currentMoaPreset.reference_models] }
}
}
setSelectedMoaPreset(name)
setNewMoaPresetName('')
void saveMoa(next)

View file

@ -9,7 +9,10 @@ describe('withActive', () => {
const curated = ['hermes-4', 'hermes-4-mini']
it('prepends a custom model missing from the curated list', () => {
expect(withActive(curated, 'anthropic/claude-opus-4.7')).toEqual(['anthropic/claude-opus-4.7', ...curated])
expect(withActive(curated, 'anthropic/claude-opus-4.7')).toEqual([
'anthropic/claude-opus-4.7',
...curated
])
})
it('leaves the list untouched when the active model is already curated', () => {

View file

@ -280,11 +280,7 @@ function ClarifyToolPending({ args }: ToolCallMessagePartProps) {
if (loading) {
return (
<ClarifyShell
aria-label={copy.loadingQuestion}
className="grid min-h-12 place-items-center px-2.5 py-3"
role="status"
>
<ClarifyShell aria-label={copy.loadingQuestion} className="grid min-h-12 place-items-center px-2.5 py-3" role="status">
<Loader2 aria-hidden className="size-4 animate-spin text-(--ui-text-tertiary)" />
</ClarifyShell>
)

View file

@ -1540,7 +1540,10 @@ function dynamicTitle(
}
const failed =
part.isError || result.success === false || result.ok === false || Boolean(firstStringField(result, ['error']))
part.isError ||
result.success === false ||
result.ok === false ||
Boolean(firstStringField(result, ['error']))
if (failed) {
const failAction = translateNow('assistant.tool.actions.failedToOpen')
@ -1553,7 +1556,10 @@ function dynamicTitle(
const action = verb(translateNow('assistant.tool.actions.opening'), translateNow('assistant.tool.actions.opened'))
return titledAction(action, translateNow('assistant.tool.titleTemplates.actionTarget', action, hostnameOf(url)))
return titledAction(
action,
translateNow('assistant.tool.titleTemplates.actionTarget', action, hostnameOf(url))
)
}
if (part.toolName === 'web_search') {