mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-09 08:21:50 +00:00
fix(desktop): close the backend update overlay on success; error on no-return
Three rough edges in the remote backend apply flow: - On success the overlay dropped to IDLE, briefly re-rendering the pre-install 'update available' view and then the generic 'you're all set' before settling. Close the overlay outright once the backend is confirmed back instead of bouncing through the idle view. - If the backend never came back (a failed restart), the flow still reported success. waitForBackendReturn now returns whether the backend answered; finishBackendApply surfaces an error when it didn't. - The up-to-date copy said 'you're running the latest version', conflating client and backend. Backend target now reads 'the backend is running the latest version' — the client's own version is a separate pill.
This commit is contained in:
parent
81647458c7
commit
cd030f5f40
8 changed files with 45 additions and 11 deletions
|
|
@ -189,7 +189,7 @@ function IdleView({
|
|||
if (behind === 0) {
|
||||
return (
|
||||
<CenteredStatus
|
||||
body={u.latestBody}
|
||||
body={target === 'backend' ? u.latestBodyBackend : u.latestBody}
|
||||
icon={<CheckCircle2 className="size-7 text-emerald-600 dark:text-emerald-400" />}
|
||||
title={u.allSetTitle}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1237,6 +1237,7 @@ export const en: Translations = {
|
|||
unsupportedMessage: 'This version of Hermes can’t update itself from inside the app.',
|
||||
connectionRetry: 'Check your connection and try again.',
|
||||
latestBody: 'You’re running the latest version.',
|
||||
latestBodyBackend: 'The backend is running the latest version.',
|
||||
allSetTitle: 'You’re all set',
|
||||
availableTitle: 'New update available',
|
||||
availableBody: 'A new version of Hermes is ready to install.',
|
||||
|
|
|
|||
|
|
@ -1378,6 +1378,7 @@ export const ja = defineLocale({
|
|||
unsupportedMessage: 'このバージョンの Hermes はアプリ内から自分を更新できません。',
|
||||
connectionRetry: '接続を確認してもう一度試してください。',
|
||||
latestBody: '最新バージョンを実行しています。',
|
||||
latestBodyBackend: 'バックエンドは最新バージョンを実行しています。',
|
||||
allSetTitle: '準備完了',
|
||||
availableTitle: '新しい更新が利用可能',
|
||||
availableBody: '新しいバージョンの Hermes をインストールする準備ができています。',
|
||||
|
|
|
|||
|
|
@ -937,6 +937,7 @@ export interface Translations {
|
|||
unsupportedMessage: string
|
||||
connectionRetry: string
|
||||
latestBody: string
|
||||
latestBodyBackend: string
|
||||
allSetTitle: string
|
||||
availableTitle: string
|
||||
availableBody: string
|
||||
|
|
|
|||
|
|
@ -1344,6 +1344,7 @@ export const zhHant = defineLocale({
|
|||
unsupportedMessage: '此版本的 Hermes 無法在應用程式內自行更新。',
|
||||
connectionRetry: '請檢查網路連線後重試。',
|
||||
latestBody: '您正在執行最新版本。',
|
||||
latestBodyBackend: '後端正在執行最新版本。',
|
||||
allSetTitle: '已是最新版本',
|
||||
availableTitle: '有可用更新',
|
||||
availableBody: '新版 Hermes 已可安裝。',
|
||||
|
|
|
|||
|
|
@ -1424,6 +1424,7 @@ export const zh: Translations = {
|
|||
unsupportedMessage: '此版本的 Hermes 无法在应用内自行更新。',
|
||||
connectionRetry: '请检查网络连接后重试。',
|
||||
latestBody: '你正在运行最新版本。',
|
||||
latestBodyBackend: '后端正在运行最新版本。',
|
||||
allSetTitle: '已是最新',
|
||||
availableTitle: '有可用更新',
|
||||
availableBody: '新版 Hermes 已可安装。',
|
||||
|
|
|
|||
|
|
@ -182,5 +182,18 @@ describe('applyBackendUpdate recovery', () => {
|
|||
expect($backendUpdateApply.get().stage).toBe('idle')
|
||||
expect($backendUpdateApply.get().applying).toBe(false)
|
||||
})
|
||||
|
||||
it('surfaces an error when the backend never comes back after the restart', async () => {
|
||||
updateHermesSpy.mockResolvedValue({ ok: true, name: 'update', pid: 1 })
|
||||
getActionStatusSpy.mockRejectedValue(new Error('ECONNREFUSED'))
|
||||
checkHermesUpdateSpy.mockRejectedValue(new Error('ECONNREFUSED'))
|
||||
|
||||
const promise = applyBackendUpdate()
|
||||
await vi.advanceTimersByTimeAsync(70000)
|
||||
const result = await promise
|
||||
|
||||
expect(result.ok).toBe(false)
|
||||
expect($backendUpdateApply.get().stage).toBe('error')
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -307,17 +307,39 @@ export async function applyUpdates(opts: DesktopUpdateApplyOptions = {}): Promis
|
|||
const BACKEND_RETURN_POLL_MS = 1500
|
||||
const BACKEND_RETURN_MAX_ATTEMPTS = 40
|
||||
|
||||
async function waitForBackendReturn(): Promise<void> {
|
||||
async function waitForBackendReturn(): Promise<boolean> {
|
||||
for (let attempt = 0; attempt < BACKEND_RETURN_MAX_ATTEMPTS; attempt += 1) {
|
||||
await new Promise(resolve => globalThis.setTimeout(resolve, BACKEND_RETURN_POLL_MS))
|
||||
try {
|
||||
await checkHermesUpdate()
|
||||
|
||||
return
|
||||
return true
|
||||
} catch {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
function finishBackendApply(returned: boolean): DesktopUpdateApplyResult {
|
||||
if (returned) {
|
||||
$backendUpdateApply.set(IDLE)
|
||||
setUpdateOverlayOpen(false)
|
||||
void checkBackendUpdates()
|
||||
|
||||
return { ok: true, message: 'Backend update applied.' }
|
||||
}
|
||||
|
||||
$backendUpdateApply.set({
|
||||
...$backendUpdateApply.get(),
|
||||
applying: false,
|
||||
stage: 'error',
|
||||
error: 'apply-failed',
|
||||
message: 'Backend updated but did not come back online. Check the backend host.'
|
||||
})
|
||||
|
||||
return { ok: false, error: 'apply-failed', message: 'Backend did not come back online.' }
|
||||
}
|
||||
|
||||
export async function applyBackendUpdate(): Promise<DesktopUpdateApplyResult> {
|
||||
|
|
@ -350,11 +372,8 @@ export async function applyBackendUpdate(): Promise<DesktopUpdateApplyResult> {
|
|||
stage: 'restart',
|
||||
message: 'Backend restarting to load the update…'
|
||||
})
|
||||
await waitForBackendReturn()
|
||||
$backendUpdateApply.set(IDLE)
|
||||
void checkBackendUpdates()
|
||||
|
||||
return { ok: true, message: 'Backend update applied; backend is back online.' }
|
||||
return finishBackendApply(await waitForBackendReturn())
|
||||
}
|
||||
|
||||
if (last && !last.running) {
|
||||
|
|
@ -365,11 +384,8 @@ export async function applyBackendUpdate(): Promise<DesktopUpdateApplyResult> {
|
|||
const ok = !!last && (last.exit_code ?? 1) === 0
|
||||
if (ok) {
|
||||
$backendUpdateApply.set({ ...$backendUpdateApply.get(), applying: true, stage: 'restart', message: 'Backend restarting to load the update…' })
|
||||
await waitForBackendReturn()
|
||||
$backendUpdateApply.set(IDLE)
|
||||
void checkBackendUpdates()
|
||||
|
||||
return { ok: true, message: 'Backend update applied.' }
|
||||
return finishBackendApply(await waitForBackendReturn())
|
||||
}
|
||||
|
||||
$backendUpdateApply.set({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue