From 6840bb02e86a2a44a0fc0ecf0c151be59546c379 Mon Sep 17 00:00:00 2001 From: "hermes-seaeye[bot]" <307254004+hermes-seaeye[bot]@users.noreply.github.com> Date: Wed, 2 Sep 2026 08:42:10 +0000 Subject: [PATCH] fmt(js): `npm run fix` on merge (#101102) Co-authored-by: github-actions[bot] --- apps/desktop/src/api/local-models.ts | 16 ++-- apps/desktop/src/app/agents/index.tsx | 4 +- .../src/app/chat/session-tile-owner.test.ts | 5 +- .../src/app/chat/session-tile-owner.ts | 3 +- .../hooks/use-prompt-actions/index.test.tsx | 8 +- .../hooks/use-session-actions/index.ts | 2 +- .../session/hooks/use-session-list-actions.ts | 6 +- .../app/settings/local-models-settings.tsx | 73 ++++++++----------- .../src/app/shell/model-catalog-menu.tsx | 12 +-- .../app/shell/system-resources-statusbar.tsx | 8 +- .../components/assistant-ui/thread/status.tsx | 2 +- apps/desktop/src/components/model-picker.tsx | 15 +--- .../src/components/onboarding/providers.tsx | 4 +- apps/desktop/src/hermes.test.ts | 4 +- apps/desktop/src/i18n/en.ts | 15 ++-- apps/desktop/src/i18n/ja.ts | 15 ++-- apps/desktop/src/i18n/zh-hant.ts | 15 ++-- apps/desktop/src/i18n/zh.ts | 3 +- .../src/lib/model-status-label.test.ts | 7 +- apps/desktop/src/store/provider-wait.test.ts | 4 +- apps/desktop/src/store/session.test.ts | 12 +-- ui-tui/src/components/thinking.tsx | 2 + 22 files changed, 119 insertions(+), 116 deletions(-) diff --git a/apps/desktop/src/api/local-models.ts b/apps/desktop/src/api/local-models.ts index d2cbce5f2c..39c883e75c 100644 --- a/apps/desktop/src/api/local-models.ts +++ b/apps/desktop/src/api/local-models.ts @@ -1,9 +1,4 @@ -import type { - LocalCatalogModel, - LocalHardware, - LocalModelsStatus, - LocalRuntimeJob -} from '@/types/hermes' +import type { LocalCatalogModel, LocalHardware, LocalModelsStatus, LocalRuntimeJob } from '@/types/hermes' import { hermesApi, profileScoped } from './client' @@ -147,7 +142,10 @@ export function listHFRepoFiles(repo: string): Promise<{ files: HFFileGroup[] }> }) } -export function downloadBrowsedModel(repo: string, paths: string[]): Promise<{ already_downloaded?: boolean; job_id: null | string; model_id: string }> { +export function downloadBrowsedModel( + repo: string, + paths: string[] +): Promise<{ already_downloaded?: boolean; job_id: null | string; model_id: string }> { return hermesApi<{ already_downloaded?: boolean; job_id: null | string; model_id: string }>({ ...profileScoped(), body: { paths, repo }, @@ -156,7 +154,9 @@ export function downloadBrowsedModel(repo: string, paths: string[]): Promise<{ a }) } -export function sideloadLocalModel(path: string): Promise<{ already_present?: boolean; model_id: string; ok: boolean }> { +export function sideloadLocalModel( + path: string +): Promise<{ already_present?: boolean; model_id: string; ok: boolean }> { return hermesApi<{ already_present?: boolean; model_id: string; ok: boolean }>({ ...profileScoped(), body: { path }, diff --git a/apps/desktop/src/app/agents/index.tsx b/apps/desktop/src/app/agents/index.tsx index 364bbb1164..5ac16a71fd 100644 --- a/apps/desktop/src/app/agents/index.tsx +++ b/apps/desktop/src/app/agents/index.tsx @@ -286,7 +286,9 @@ function DelegationGroup({ group, nowMs }: { group: RootGroup; nowMs: number })

{group.delegationIndex > 0 ? t.agents.delegation(group.delegationIndex) : ''} - {group.batchTag ? [{group.batchTag}] : null}{' '} + {group.batchTag ? ( + [{group.batchTag}] + ) : null}{' '} · {t.agents.workers(group.nodes.length)} {activeWorkers > 0 ? · {t.agents.workersActive(activeWorkers)} : null}

diff --git a/apps/desktop/src/app/chat/session-tile-owner.test.ts b/apps/desktop/src/app/chat/session-tile-owner.test.ts index 57df622835..6df849b63a 100644 --- a/apps/desktop/src/app/chat/session-tile-owner.test.ts +++ b/apps/desktop/src/app/chat/session-tile-owner.test.ts @@ -52,8 +52,9 @@ describe('tileOwnerRoute', () => { ) expect(routed).toEqual({ connectionId: 'pandora', profile: 'work', targetProfile: 'ceo' }) - expect(tileOwnerRoute([tile({ ownerRoute: { connectionId: 'p', profile: 'w' }, storedSessionId: 's1' })], [], 's1')) - .not.toHaveProperty('targetProfile') + expect( + tileOwnerRoute([tile({ ownerRoute: { connectionId: 'p', profile: 'w' }, storedSessionId: 's1' })], [], 's1') + ).not.toHaveProperty('targetProfile') }) it('narrows a bare profile owner away', () => { diff --git a/apps/desktop/src/app/chat/session-tile-owner.ts b/apps/desktop/src/app/chat/session-tile-owner.ts index e99a3df896..7b768fd023 100644 --- a/apps/desktop/src/app/chat/session-tile-owner.ts +++ b/apps/desktop/src/app/chat/session-tile-owner.ts @@ -23,8 +23,7 @@ export function tileOwnerRoute( storedSessionId: string ): SessionOwnerRoute | undefined { const owner: SessionOwnerScope = - tiles.find(tile => tile.storedSessionId === storedSessionId)?.ownerRoute ?? - knownSessionOwner(rows, storedSessionId) + tiles.find(tile => tile.storedSessionId === storedSessionId)?.ownerRoute ?? knownSessionOwner(rows, storedSessionId) if (!owner || typeof owner !== 'object' || !owner.connectionId) { return undefined diff --git a/apps/desktop/src/app/session/hooks/use-prompt-actions/index.test.tsx b/apps/desktop/src/app/session/hooks/use-prompt-actions/index.test.tsx index 1b206f9eca..0673798c18 100644 --- a/apps/desktop/src/app/session/hooks/use-prompt-actions/index.test.tsx +++ b/apps/desktop/src/app/session/hooks/use-prompt-actions/index.test.tsx @@ -970,7 +970,9 @@ describe('usePromptActions /compress', () => { act(() => { submitted = handle!.submitTextRaw('/compress') }) - await waitFor(() => expect(requestGateway).toHaveBeenCalledWith('session.compress', expect.anything(), SESSION_COMPRESS_TIMEOUT_MS)) + await waitFor(() => + expect(requestGateway).toHaveBeenCalledWith('session.compress', expect.anything(), SESSION_COMPRESS_TIMEOUT_MS) + ) // Switch to session B before compression resolves. activeSessionIdRef.current = RUNTIME_SESSION_B @@ -1029,7 +1031,9 @@ describe('usePromptActions /compress', () => { act(() => { submitted = handle!.submitTextRaw('/compress') }) - await waitFor(() => expect(requestGateway).toHaveBeenCalledWith('session.compress', expect.anything(), SESSION_COMPRESS_TIMEOUT_MS)) + await waitFor(() => + expect(requestGateway).toHaveBeenCalledWith('session.compress', expect.anything(), SESSION_COMPRESS_TIMEOUT_MS) + ) activeSessionIdRef.current = RUNTIME_SESSION_B storedSessionIdRef.current = 'stored-b' rejectCompress(new Error('compression failed')) diff --git a/apps/desktop/src/app/session/hooks/use-session-actions/index.ts b/apps/desktop/src/app/session/hooks/use-session-actions/index.ts index 46aa5f67ec..2607aa28df 100644 --- a/apps/desktop/src/app/session/hooks/use-session-actions/index.ts +++ b/apps/desktop/src/app/session/hooks/use-session-actions/index.ts @@ -2024,7 +2024,7 @@ export function useSessionActions({ await ensureGatewayProfile(profile) } - const requestBranchGateway = (method: string, params: Record): Promise => + const requestBranchGateway = (method: string, params: Record): Promise => ownerRoute ? requestGatewayForAgent(ownerRoute.connectionId, ownerRoute.profile, method, params) : requestGateway(method, params) diff --git a/apps/desktop/src/app/session/hooks/use-session-list-actions.ts b/apps/desktop/src/app/session/hooks/use-session-list-actions.ts index c343701c18..935fb745e6 100644 --- a/apps/desktop/src/app/session/hooks/use-session-list-actions.ts +++ b/apps/desktop/src/app/session/hooks/use-session-list-actions.ts @@ -303,11 +303,7 @@ export function useSessionListActions({ profileScope }: UseSessionListActionsArg // whole list re-renders once per turn/broadcast for nothing. setSessions(prev => { const incoming = dropTombstoned( - carryForwardFailedProfileSessions( - prev, - recents.sessions ?? [], - recents.errors ?? result.errors - ) + carryForwardFailedProfileSessions(prev, recents.sessions ?? [], recents.errors ?? result.errors) ) const next = mergeSessionPage(prev, incoming, sessionsToKeep()) diff --git a/apps/desktop/src/app/settings/local-models-settings.tsx b/apps/desktop/src/app/settings/local-models-settings.tsx index 840e736aae..f845bfeacd 100644 --- a/apps/desktop/src/app/settings/local-models-settings.tsx +++ b/apps/desktop/src/app/settings/local-models-settings.tsx @@ -24,7 +24,21 @@ import { sideloadLocalModel } from '@/hermes' import { useI18n } from '@/i18n' -import { Check, CheckCircle2, Cpu, Download, Eject, FolderOpen, Loader2, Monitor, Package, Search, StopFilled, Trash2, Zap } from '@/lib/icons' +import { + Check, + CheckCircle2, + Cpu, + Download, + Eject, + FolderOpen, + Loader2, + Monitor, + Package, + Search, + StopFilled, + Trash2, + Zap +} from '@/lib/icons' import { cn } from '@/lib/utils' import { $localRuntimeJobs, @@ -251,9 +265,7 @@ export function LocalModelsSettings() { const navigate = useNavigate() const seenQuickstarts = useRef(new Set()) - const runningQuickstart = jobs.find( - j => j.kind === 'quickstart' && j.status === 'running' - ) + const runningQuickstart = jobs.find(j => j.kind === 'quickstart' && j.status === 'running') useEffect(() => { // Event detection, not value mirroring: the ref only remembers which @@ -298,11 +310,7 @@ export function LocalModelsSettings() { // Stage rail derived from the job phase: engine -> model -> finish. const phase = qJob?.phase ?? '' - const stageIndex = ['starting-server', 'setting-default'].includes(phase) - ? 2 - : phase === 'downloading' - ? 1 - : 0 + const stageIndex = ['starting-server', 'setting-default'].includes(phase) ? 2 : phase === 'downloading' ? 1 : 0 const stages = [copy.quickstartStageEngine, copy.quickstartStageModel, copy.quickstartStageFinish] @@ -334,9 +342,7 @@ export function LocalModelsSettings() { {qJob ? ( <> -

- {liveDetail} -

+

{liveDetail}

@@ -397,8 +403,7 @@ export function LocalModelsSettings() { // Up to date = the authority (status) says the configured tag is what's // serving. Shown whenever true — not only right after an update. - const updateApplied = - status.runtime_installed && !status.update_available && status.tag === status.configured_tag + const updateApplied = status.runtime_installed && !status.update_available && status.tag === status.configured_tag return ( @@ -511,9 +516,7 @@ export function LocalModelsSettings() { /> )} - {lastError?.kind === 'runtime-install' && ( -

{lastError.error}

- )} + {lastError?.kind === 'runtime-install' &&

{lastError.error}

} {/* ── This machine ── */} @@ -571,13 +574,7 @@ export function LocalModelsSettings() { model.downloaded ? (
{isLoaded && livePlacement && ( - + {livePlacement.granted_window_label ?? livePlacement.window_label ?? ''} @@ -701,8 +698,9 @@ export function LocalModelsSettings() { model, so a spilled full window goes gray. Anything starting below its native window gets one quiet 'Up to' pill instead of a start/grow pair. */} - {model.fits && model.start_window_label && ( - model.start_window && model.start_window >= model.native_context ? ( + {model.fits && + model.start_window_label && + (model.start_window && model.start_window >= model.native_context ? ( {copy.pillFullContext(model.native_context_label)} @@ -712,12 +710,9 @@ export function LocalModelsSettings() { {copy.pillUpTo(model.native_context_label)} - ) - )} + ))} - {!model.fits && ( - {copy.pillUpTo(model.native_context_label)} - )} + {!model.fits && {copy.pillUpTo(model.native_context_label)}} {model.vision && {copy.pillVision}} @@ -758,9 +753,7 @@ export function LocalModelsSettings() { const isLoadingNow = residency === 'loading' const livePlacement = status.placement?.[m.id] - const aJob = jobs.find( - j => j.kind === 'model-activate' && j.status === 'running' && j.model_id === m.id - ) + const aJob = jobs.find(j => j.kind === 'model-activate' && j.status === 'running' && j.model_id === m.id) const anyActivateRunning = jobs.some(j => j.kind === 'model-activate' && j.status === 'running') @@ -769,9 +762,7 @@ export function LocalModelsSettings() { action={
{isLoaded && livePlacement && ( - + {livePlacement.granted_window_label ?? livePlacement.window_label ?? ''} @@ -840,9 +831,7 @@ export function LocalModelsSettings() { })}
- {lastError?.kind === 'model-download' && ( -

{lastError.error}

- )} + {lastError?.kind === 'model-download' &&

{lastError.error}

} @@ -1099,7 +1088,9 @@ function BrowseSection({ onChanged }: { onChanged: () => void }) { : copy.browseFitUnknown}
- {gbLabel(group.total_bytes)} + + {gbLabel(group.total_bytes)} + )}
diff --git a/apps/desktop/src/app/shell/model-catalog-menu.tsx b/apps/desktop/src/app/shell/model-catalog-menu.tsx index 351fa24c54..295993918f 100644 --- a/apps/desktop/src/app/shell/model-catalog-menu.tsx +++ b/apps/desktop/src/app/shell/model-catalog-menu.tsx @@ -505,7 +505,8 @@ export function ModelCatalogMenu({ // Managed local model loading into memory right now: // real load percent, keyed by exact model id (remote // providers never collide with GGUF stems). - const loadProgress = loadingModels[family.id] ?? (family.fastId ? loadingModels[family.fastId] : undefined) + const loadProgress = + loadingModels[family.id] ?? (family.fastId ? loadingModels[family.fastId] : undefined) // Effective settings for this row: the live choice when it's // the active model, otherwise its remembered preset. Row @@ -602,7 +603,9 @@ export function ModelCatalogMenu({ })} {!collapsed && slug === LOCAL_PROVIDER_SLUG && - shownDownloads.map(job => )} + shownDownloads.map(job => ( + + ))} ) })} @@ -680,10 +683,7 @@ function DownloadingModelRow({ jobId, target }: { jobId: string; target: string const { t } = useI18n() const copy = t.modelPicker - const percent = useStoreSelector( - $localRuntimeJobs, - jobs => jobs.find(job => job.job_id === jobId)?.percent ?? null - ) + const percent = useStoreSelector($localRuntimeJobs, jobs => jobs.find(job => job.job_id === jobId)?.percent ?? null) return ( +
{/* min-w-0 everywhere a flex/grid child must shrink: grid items default min-width:auto, so a long GPU name's nowrap min-content props the track open past the w-64 box and overflow-x:hidden diff --git a/apps/desktop/src/components/assistant-ui/thread/status.tsx b/apps/desktop/src/components/assistant-ui/thread/status.tsx index 22205b5dad..c3f40ac255 100644 --- a/apps/desktop/src/components/assistant-ui/thread/status.tsx +++ b/apps/desktop/src/components/assistant-ui/thread/status.tsx @@ -62,7 +62,7 @@ const HintText: FC<{ children: ReactNode }> = ({ children }) => ( * call (title generation autoloads the same model), never gets a frame, * and the load looked like nothing was happening. The status route reads * the same SSE snapshot, so this bar carries the identical percent. */ -function useLocalModelLoad(active: boolean): LocalModelLoadProgress & { model: string } | null { +function useLocalModelLoad(active: boolean): (LocalModelLoadProgress & { model: string }) | null { const model = useStore($currentModel) const [progress, setProgress] = useState<(LocalModelLoadProgress & { model: string }) | null>(null) diff --git a/apps/desktop/src/components/model-picker.tsx b/apps/desktop/src/components/model-picker.tsx index 11c34daa9e..f2d7283f17 100644 --- a/apps/desktop/src/components/model-picker.tsx +++ b/apps/desktop/src/components/model-picker.tsx @@ -347,9 +347,7 @@ function ModelResults({ style={{ width: `${Math.max(2, loadProgress.percent)}%` }} /> - - {loadProgress.percent}% - + {loadProgress.percent}% )} {locked && ( @@ -393,17 +391,10 @@ function DownloadingModelRow({ jobId, target }: { jobId: string; target: string const { t } = useI18n() const copy = t.modelPicker - const percent = useStoreSelector( - $localRuntimeJobs, - jobs => jobs.find(job => job.job_id === jobId)?.percent ?? null - ) + const percent = useStoreSelector($localRuntimeJobs, jobs => jobs.find(job => job.job_id === jobId)?.percent ?? null) return ( - + {target} diff --git a/apps/desktop/src/components/onboarding/providers.tsx b/apps/desktop/src/components/onboarding/providers.tsx index d5ab346788..2612989b2e 100644 --- a/apps/desktop/src/components/onboarding/providers.tsx +++ b/apps/desktop/src/components/onboarding/providers.tsx @@ -100,7 +100,9 @@ export function FireworksProviderRow({ onClick }: { onClick: () => void }) { export function LocalModelsProviderRow({ onClick }: { onClick: () => void }) { const { t } = useI18n() - return + return ( + + ) } export function OpenRouterProviderRow({ onClick }: { onClick: () => void }) { diff --git a/apps/desktop/src/hermes.test.ts b/apps/desktop/src/hermes.test.ts index 0876ca53b6..ec9b94ada6 100644 --- a/apps/desktop/src/hermes.test.ts +++ b/apps/desktop/src/hermes.test.ts @@ -296,9 +296,7 @@ describe('Hermes REST helpers', () => { api.mockImplementation(({ path }: { path: string }) => { if (path.startsWith('/api/profiles/sessions/sidebar')) { - return Promise.reject( - new Error('404: {"detail":"No such API endpoint: /api/profiles/sessions/sidebar"}') - ) + return Promise.reject(new Error('404: {"detail":"No such API endpoint: /api/profiles/sessions/sidebar"}')) } if (path.includes('source=cron')) { diff --git a/apps/desktop/src/i18n/en.ts b/apps/desktop/src/i18n/en.ts index a36038c8b8..bd3049a635 100644 --- a/apps/desktop/src/i18n/en.ts +++ b/apps/desktop/src/i18n/en.ts @@ -1153,8 +1153,7 @@ export const en: Translations = { 'A higher-quality model fits this machine but would respond too slowly on its memory bandwidth — this is the best model that stays fast.', 'fastest-resident': 'No model reaches full speed on this hardware; this one comes closest while running entirely in GPU memory.', - 'least-painful-spilled': - 'No model fits entirely in GPU memory here — this one runs best from system RAM.' + 'least-painful-spilled': 'No model fits entirely in GPU memory here — this one runs best from system RAM.' } as Record, downloaded: 'Downloaded', downloadAction: size => `Download · ${size}`, @@ -1164,7 +1163,8 @@ export const en: Translations = { quickstartTitle: 'Run a model on this machine', quickstartDetail: (model, size) => `One click sets everything up: the local engine, ${model} (${size} download), and your default for new chats. Nothing leaves this computer.`, - quickstartDetailReady: model => `One click makes ${model} your default for new chats. Everything runs on this machine.`, + quickstartDetailReady: model => + `One click makes ${model} your default for new chats. Everything runs on this machine.`, quickstartAction: 'Set up for me', quickstartConfigure: 'Configure…', quickstartDoneToast: model => `${model} is set up — new chats run on this machine.`, @@ -1175,7 +1175,8 @@ export const en: Translations = { useAction: 'Use', activePill: 'Default', updateTitle: 'Engine update available', - updateDetail: (next, current) => `A newer llama.cpp build (${next}) is ready to install — you're on ${current}. Models keep working during the download.`, + updateDetail: (next, current) => + `A newer llama.cpp build (${next}) is ready to install — you're on ${current}. Models keep working during the download.`, updateAction: 'Update engine', updating: 'Updating engine…', upToDateTitle: 'Engine up to date', @@ -1195,7 +1196,8 @@ export const en: Translations = { ejectFailed: 'Could not unload the model', stopServer: 'Turn off', startServer: 'Turn on', - runtimeRunningDetail: 'The local server is running. Turning it off frees all GPU memory and stops new chats from using local models until you turn it back on.', + runtimeRunningDetail: + 'The local server is running. Turning it off frees all GPU memory and stops new chats from using local models until you turn it back on.', serverStopped: 'Local server stopped — GPU memory freed.', serverStarted: 'Local server running.', serverStopFailed: 'Could not stop the local server', @@ -1208,7 +1210,8 @@ export const en: Translations = { pillUsesRam: 'Uses system RAM', pillTooBig: 'Too big for this machine', browseTitle: 'Find more models', - browseHint: 'Search all of Hugging Face. Models you download here are sized to your machine automatically, but not tested by us.', + browseHint: + 'Search all of Hugging Face. Models you download here are sized to your machine automatically, but not tested by us.', browsePlaceholder: 'Search models by name or author…', browseSearching: 'Searching Hugging Face', browseListing: 'Reading model files', diff --git a/apps/desktop/src/i18n/ja.ts b/apps/desktop/src/i18n/ja.ts index a94cbbbeb5..aa5d7e06d3 100644 --- a/apps/desktop/src/i18n/ja.ts +++ b/apps/desktop/src/i18n/ja.ts @@ -1067,26 +1067,30 @@ export const ja = defineLocale({ useAction: '使用する', activePill: 'デフォルト', updateTitle: 'エンジンの更新があります', - updateDetail: (next, current) => `新しい llama.cpp ビルド(${next})をインストールできます——現在は ${current} です。ダウンロード中もモデルは引き続き使えます。`, + updateDetail: (next, current) => + `新しい llama.cpp ビルド(${next})をインストールできます——現在は ${current} です。ダウンロード中もモデルは引き続き使えます。`, updateAction: 'エンジンを更新', updating: 'エンジンを更新中…', upToDateTitle: 'エンジンは最新です', upToDateDetail: (tag, backend) => `llama.cpp ${tag}(${backend})で動作中——Hermes が提供する最新ビルドです。`, - updateToast: next => `ローカルエンジンの新しいビルド(${next})があります。設定 → ローカルモデル から更新できます。`, + updateToast: next => + `ローカルエンジンの新しいビルド(${next})があります。設定 → ローカルモデル から更新できます。`, activeDetail: '新しいチャットはこのモデルを使用——最初のメッセージ送信時に読み込みます', activeNotLoaded: '最初のメッセージで読み込みます', loadedPill: '読み込み済み', placementResident: 'すべて GPU 上', placementSpilled: '一部 RAM 上', placementResidentTip: 'このコンテキストウィンドウで GPU メモリ内で完全に動作しています — フルスピード。', - placementSpilledTip: 'モデルの一部がシステム RAM から動作しています — 動作しますが遅くなります。よりコンパクトなビルドか小さいコンテキストなら完全に収まります。', + placementSpilledTip: + 'モデルの一部がシステム RAM から動作しています — 動作しますが遅くなります。よりコンパクトなビルドか小さいコンテキストなら完全に収まります。', loadingPill: '読み込み中…', ejectTip: 'GPU メモリを解放(必要時に再読み込み)', ejected: 'モデルをアンロードしました——GPU メモリを解放しました。', ejectFailed: 'モデルをアンロードできませんでした', stopServer: 'オフにする', startServer: 'オンにする', - runtimeRunningDetail: 'ローカルサーバーが実行中です。オフにすると GPU メモリを全て解放し、再度オンにするまで新しいチャットはローカルモデルを使用しません。', + runtimeRunningDetail: + 'ローカルサーバーが実行中です。オフにすると GPU メモリを全て解放し、再度オンにするまで新しいチャットはローカルモデルを使用しません。', serverStopped: 'ローカルサーバーを停止しました——GPU メモリを解放しました。', serverStarted: 'ローカルサーバー実行中。', serverStopFailed: 'ローカルサーバーを停止できませんでした', @@ -1099,7 +1103,8 @@ export const ja = defineLocale({ pillUsesRam: 'システム RAM を使用', pillTooBig: 'このマシンには大きすぎます', browseTitle: 'さらにモデルを探す', - browseHint: 'Hugging Face 全体を検索できます。ここでダウンロードしたモデルは自動でマシンに合わせて動作しますが、当方でのテストは行われていません。', + browseHint: + 'Hugging Face 全体を検索できます。ここでダウンロードしたモデルは自動でマシンに合わせて動作しますが、当方でのテストは行われていません。', browsePlaceholder: 'モデル名または作者で検索…', browseSearching: 'Hugging Face を検索中', browseListing: 'モデルファイルを読み込み中', diff --git a/apps/desktop/src/i18n/zh-hant.ts b/apps/desktop/src/i18n/zh-hant.ts index f389ed1a15..85a6b3c82c 100644 --- a/apps/desktop/src/i18n/zh-hant.ts +++ b/apps/desktop/src/i18n/zh-hant.ts @@ -705,7 +705,8 @@ export const zhHant = defineLocale({ 'Hermes 執行環境已更新,但桌面應用程式本身仍是舊建置——在應用程式更新之前,新的介面功能(如 Bot Mode)不會顯示。請執行下方的更新以重新建置應用程式。如果此警告仍未消除,請從最新的桌面安裝程式重新安裝。', bundleOutOfSyncAction: '取得安裝程式', bundleSwapPending: '重新啟動以完成更新', - bundleSwapPendingDesc: '更新後的應用程式已安裝完成,只需重新啟動 Hermes 即可載入新版本。聊天記錄和設定不會受到影響。', + bundleSwapPendingDesc: + '更新後的應用程式已安裝完成,只需重新啟動 Hermes 即可載入新版本。聊天記錄和設定不會受到影響。', bundleSwapPendingAction: '重新啟動 Hermes', updates: '更新', checkNow: '立即檢查', @@ -998,8 +999,7 @@ export const zhHant = defineLocale({ runtimeInstalled: '已安裝 llama.cpp 執行環境', runtimeInstalledDetail: (tag, backend) => `組建 ${tag},${backend} 後端。Hermes 會為您啟動並管理伺服器。`, installTitle: '安裝本地執行環境', - installDetail: - '下載 llama.cpp 推理引擎(數百 MB)。下載的模型完全在本機執行——無需帳號,資料不會離開您的電腦。', + installDetail: '下載 llama.cpp 推理引擎(數百 MB)。下載的模型完全在本機執行——無需帳號,資料不會離開您的電腦。', installAction: '安裝執行環境', installing: '正在安裝執行環境…', installFailed: '執行環境安裝失敗', @@ -1012,7 +1012,8 @@ export const zhHant = defineLocale({ recommended: '推薦', recommendedReason: { 'best-quality-resident': '在完全駐留 GPU 且保持全速的模型中品質最高。推薦會在品質與該硬體的預計速度之間權衡。', - 'speed-gated-quality': '有更高品質的模型可以裝入這台機器,但受記憶體頻寬限制回應會太慢——這是保持流暢的最佳模型。', + 'speed-gated-quality': + '有更高品質的模型可以裝入這台機器,但受記憶體頻寬限制回應會太慢——這是保持流暢的最佳模型。', 'fastest-resident': '沒有模型能在該硬體上達到全速;這是完全駐留 GPU 記憶體中最快的一個。', 'least-painful-spilled': '沒有模型能完全裝入 GPU 記憶體——這是從系統記憶體執行表現最好的一個。' } as Record, @@ -1024,7 +1025,8 @@ export const zhHant = defineLocale({ useAction: '使用', activePill: '預設', updateTitle: '引擎有可用更新', - updateDetail: (next, current) => `新的 llama.cpp 組建(${next})可以安裝——目前為 ${current}。下載期間模型仍可正常使用。`, + updateDetail: (next, current) => + `新的 llama.cpp 組建(${next})可以安裝——目前為 ${current}。下載期間模型仍可正常使用。`, updateAction: '更新引擎', updating: '正在更新引擎…', upToDateTitle: '引擎已是最新', @@ -1036,7 +1038,8 @@ export const zhHant = defineLocale({ placementResident: '全部在 GPU', placementSpilled: '部分在記憶體', placementResidentTip: '完全在 GPU 記憶體中以此上下文視窗執行——全速。', - placementSpilledTip: '模型的一部分從系統記憶體執行——可用但較慢。更緊湊的版本或更小的上下文可以完全放入顯示記憶體。', + placementSpilledTip: + '模型的一部分從系統記憶體執行——可用但較慢。更緊湊的版本或更小的上下文可以完全放入顯示記憶體。', loadingPill: '載入中…', ejectTip: '釋放顯示記憶體(需要時重新載入)', ejected: '模型已卸載——顯示記憶體已釋放。', diff --git a/apps/desktop/src/i18n/zh.ts b/apps/desktop/src/i18n/zh.ts index e0437906a8..3da57690f9 100644 --- a/apps/desktop/src/i18n/zh.ts +++ b/apps/desktop/src/i18n/zh.ts @@ -1359,7 +1359,8 @@ export const zh: Translations = { useAction: '使用', activePill: '默认', updateTitle: '引擎有可用更新', - updateDetail: (next, current) => `新的 llama.cpp 构建(${next})可以安装——当前为 ${current}。下载期间模型仍可正常使用。`, + updateDetail: (next, current) => + `新的 llama.cpp 构建(${next})可以安装——当前为 ${current}。下载期间模型仍可正常使用。`, updateAction: '更新引擎', updating: '正在更新引擎…', upToDateTitle: '引擎已是最新', diff --git a/apps/desktop/src/lib/model-status-label.test.ts b/apps/desktop/src/lib/model-status-label.test.ts index 326296dd27..f5dd3143ec 100644 --- a/apps/desktop/src/lib/model-status-label.test.ts +++ b/apps/desktop/src/lib/model-status-label.test.ts @@ -1,6 +1,11 @@ import { describe, expect, it } from 'vitest' -import { currentPickerSelection, displayModelName, formatModelStatusLabel, modelDisplayParts } from './model-status-label' +import { + currentPickerSelection, + displayModelName, + formatModelStatusLabel, + modelDisplayParts +} from './model-status-label' import { reasoningEffortLabel } from './reasoning-effort' describe('model-status-label', () => { diff --git a/apps/desktop/src/store/provider-wait.test.ts b/apps/desktop/src/store/provider-wait.test.ts index f5422fe4a8..9c5e6bc143 100644 --- a/apps/desktop/src/store/provider-wait.test.ts +++ b/apps/desktop/src/store/provider-wait.test.ts @@ -22,7 +22,9 @@ describe('providerWaitText', () => { describe('parseModelLoadWait', () => { it('extracts model and percent from a load frame', () => { expect( - parseModelLoadWait('⏳ loading Qwen3.6-35B-A3B-UD-Q4_K_M into memory — 42% (responses start once the model is loaded)') + parseModelLoadWait( + '⏳ loading Qwen3.6-35B-A3B-UD-Q4_K_M into memory — 42% (responses start once the model is loaded)' + ) ).toEqual({ kind: 'load', model: 'Qwen3.6-35B-A3B-UD-Q4_K_M', percent: 42 }) }) diff --git a/apps/desktop/src/store/session.test.ts b/apps/desktop/src/store/session.test.ts index 983ba7135e..c1c1285c44 100644 --- a/apps/desktop/src/store/session.test.ts +++ b/apps/desktop/src/store/session.test.ts @@ -694,9 +694,7 @@ describe('carryForwardFailedProfileSessions', () => { session({ id: 'week', last_active: 100, profile: 'default', title: 'This week' }) ] - const carried = carryForwardFailedProfileSessions(previous, [], [ - { profile: 'default', error: 'disk I/O error' } - ]) + const carried = carryForwardFailedProfileSessions(previous, [], [{ profile: 'default', error: 'disk I/O error' }]) expect(carried.map(s => s.id)).toEqual(['running', 'yesterday', 'week']) expect(carried[1]).toBe(previous[1]) @@ -724,9 +722,11 @@ describe('carryForwardFailedProfileSessions', () => { const incoming = [session({ id: 'home', last_active: 100, profile: 'default' })] - expect( - carryForwardFailedProfileSessions(previous, incoming, [{ profile: 'work' }]).map(s => s.id) - ).toEqual(['idle-newer', 'home', 'idle-older']) + expect(carryForwardFailedProfileSessions(previous, incoming, [{ profile: 'work' }]).map(s => s.id)).toEqual([ + 'idle-newer', + 'home', + 'idle-older' + ]) }) it('treats a missing profile tag on the error as default', () => { diff --git a/ui-tui/src/components/thinking.tsx b/ui-tui/src/components/thinking.tsx index 07d53f2576..da484a0fa6 100644 --- a/ui-tui/src/components/thinking.tsx +++ b/ui-tui/src/components/thinking.tsx @@ -334,12 +334,14 @@ function SubagentAccordion({ // `[6a66 3/9]` when the gateway tags the batch; `[3/9]` on older gateways. const batchTag = item.delegationId?.split('_').at(-1)?.slice(0, 4) + const prefix = item.taskCount > 1 ? `[${batchTag ? `${batchTag} ` : ''}${item.index + 1}/${item.taskCount}] ` : batchTag ? `[${batchTag}] ` : '' + const goalLabel = item.goal || `Subagent ${item.index + 1}` const title = `${prefix}${open ? goalLabel : compactPreview(goalLabel, 60)}` const summary = compactPreview((item.summary || '').replace(/\s+/g, ' ').trim(), 72)