diff --git a/apps/desktop/src/components/boot-failure-overlay.test.tsx b/apps/desktop/src/components/boot-failure-overlay.test.tsx index e86f987a63..a0dc71b024 100644 --- a/apps/desktop/src/components/boot-failure-overlay.test.tsx +++ b/apps/desktop/src/components/boot-failure-overlay.test.tsx @@ -98,4 +98,38 @@ describe('BootFailureOverlay', () => { restore() } }) + + it('shows the Nous Cloud down recovery when the backend flags isCloudBackendDown', async () => { + const restore = stubDesktop(remoteToken) + $desktopBoot.set({ + error: 'Nous Cloud agent ares-3009.agents.nousresearch.com is down (HTTP 503: server-side fault).', + fakeMode: false, + isCloudBackendDown: true, + message: 'boot failed', + phase: 'renderer.error', + progress: 40, + running: false, + statusCode: 503, + timestamp: Date.now(), + visible: true + }) + + try { + render() + // Cloud-specific title + actionable portal guidance instead of the + // generic remote-failure copy. + expect(await screen.findByText(/Nous Cloud agent is down/i)).toBeTruthy() + expect(screen.getByText(/portal\.nousresearch\.com/i)).toBeTruthy() + // Cloud-down is a remote failure: local-only Repair is dropped; the + // actionable paths are Gateway settings + Use local gateway. + expect(screen.queryByRole('button', { name: /repair/i })).toBeNull() + expect(screen.getByRole('button', { name: /gateway settings/i })).toBeTruthy() + expect(screen.getByRole('button', { name: /use local gateway/i })).toBeTruthy() + // The electron-built error message (portal / local mode / Discord) is + // still surfaced in the error box. + expect(screen.getByText(/ares-3009\.agents\.nousresearch\.com/i)).toBeTruthy() + } finally { + restore() + } + }) }) diff --git a/apps/desktop/src/components/boot-failure-overlay.tsx b/apps/desktop/src/components/boot-failure-overlay.tsx index e479ce5bb9..246b9525df 100644 --- a/apps/desktop/src/components/boot-failure-overlay.tsx +++ b/apps/desktop/src/components/boot-failure-overlay.tsx @@ -247,6 +247,11 @@ export function BootFailureOverlay() { let actions: RecoveryAction[] let hint: string + // The electron boot path flags a Nous Cloud backend-down (502/503/504) with + // the structured isCloudBackendDown/statusCode it carries through boot + // progress. When set, the recovery screen leads with the cloud-specific + // guidance instead of the generic remote-failure copy (#85335). + const cloudDown = Boolean(boot.isCloudBackendDown) if (remoteReauth) { actions = [ @@ -261,6 +266,12 @@ export function BootFailureOverlay() { localAction ] hint = copy.remoteSignInHint(label) + } else if (cloudDown) { + // A Nous Cloud agent is down — the user cannot restart the managed + // instance and Repair is local-only, so the actionable paths are Gateway + // settings (switch host / use local), a secondary Retry, and open logs. + actions = [settingsAction, { ...retryAction, variant: 'secondary' }, localAction] + hint = copy.cloudDownHint } else if (remoteFailure) { actions = [settingsAction, { ...retryAction, variant: 'secondary' }, localAction] hint = copy.remoteFailureHint @@ -323,10 +334,10 @@ export function BootFailureOverlay() {

- {remoteReauth ? copy.remoteTitle : copy.title} + {remoteReauth ? copy.remoteTitle : cloudDown ? copy.cloudDownTitle : copy.title}

- {remoteReauth ? copy.remoteDescription : copy.description} + {remoteReauth ? copy.remoteDescription : cloudDown ? copy.cloudDownDescription : copy.description}

diff --git a/apps/desktop/src/i18n/ar.ts b/apps/desktop/src/i18n/ar.ts index c8ebdf5e97..43a71123e9 100644 --- a/apps/desktop/src/i18n/ar.ts +++ b/apps/desktop/src/i18n/ar.ts @@ -85,6 +85,9 @@ export const ar = defineLocale({ retry: 'إعادة المحاولة', repairInstall: 'إصلاح التثبيت', useLocalGateway: 'استخدام البوابة المحلية', + cloudDownTitle: 'عامل Nous Cloud معطّل', + cloudDownDescription: 'يعيد عامل السحابة المُدار من Nous الذي يتصل به هذا البوابة خطأً من الخادم. لا يمكن إعادة تشغيله من هنا — تحقق من حالته، أو بدّل إلى البوابة المحلية، أو احصل على الدعم.', + cloudDownHint: 'تحقق من https://portal.nousresearch.com لحالة الخادم، أو استخدم البوابة المحلية أدناه، أو تواصل معنا عبر Discord (discord.gg/NousResearch).', openLogs: 'فتح السجلات', repairHint: 'يعيد الإصلاح تشغيل المثبت وقد يستغرق بضع دقائق على جهاز جديد.', remoteSignInHint: signInLabel => diff --git a/apps/desktop/src/i18n/en.ts b/apps/desktop/src/i18n/en.ts index 64411758e6..6db27de9f7 100644 --- a/apps/desktop/src/i18n/en.ts +++ b/apps/desktop/src/i18n/en.ts @@ -102,6 +102,11 @@ export const en: Translations = { `Signs out of the saved remote browser session, then opens ${signInLabel}. Use local gateway to switch to the bundled backend instead.`, signOutAndSignIn: 'Sign out & sign in', remoteFailureHint: 'Check the gateway URL and sign-in under Gateway settings, or switch to the local gateway.', + cloudDownTitle: 'Nous Cloud agent is down', + cloudDownDescription: + 'The Nous-managed cloud agent this gateway connects to is returning a server error. It cannot be restarted from here — check its status, switch to the local gateway, or get support.', + cloudDownHint: + 'Check https://portal.nousresearch.com for backend status, use the local gateway below, or reach out on Discord (discord.gg/NousResearch).', hideRecentLogs: 'Hide recent logs', showRecentLogs: 'Show recent logs', signedInTitle: 'Signed in', diff --git a/apps/desktop/src/i18n/ja.ts b/apps/desktop/src/i18n/ja.ts index c493562019..2ec6066b74 100644 --- a/apps/desktop/src/i18n/ja.ts +++ b/apps/desktop/src/i18n/ja.ts @@ -103,6 +103,11 @@ export const ja = defineLocale({ signOutAndSignIn: 'サインアウトして再サインイン', remoteFailureHint: '「ゲートウェイ設定」でゲートウェイの URL とサインインを確認するか、ローカルゲートウェイに切り替えてください。', + cloudDownTitle: 'Nous Cloud エージェントが停止しています', + cloudDownDescription: + 'このゲートウェイが接続している Nous 管理のクラウドエージェントがサーバーエラーを返しています。ここから再起動することはできません。ステータスを確認するか、ローカルゲートウェイに切り替えるか、サポートに連絡してください。', + cloudDownHint: + 'https://portal.nousresearch.com でバックエンドのステータスを確認するか、下のローカルゲートウェイを使用するか、Discord (discord.gg/NousResearch) でご連絡ください。', hideRecentLogs: '最近のログを非表示', showRecentLogs: '最近のログを表示', signedInTitle: 'サインインしました', diff --git a/apps/desktop/src/i18n/types.ts b/apps/desktop/src/i18n/types.ts index 1cecefa8a2..a28249ee49 100644 --- a/apps/desktop/src/i18n/types.ts +++ b/apps/desktop/src/i18n/types.ts @@ -145,6 +145,9 @@ export interface Translations { remoteSignInHint: (signInLabel: string) => string signOutAndSignIn: string remoteFailureHint: string + cloudDownTitle: string + cloudDownDescription: string + cloudDownHint: string hideRecentLogs: string showRecentLogs: string signedInTitle: string diff --git a/apps/desktop/src/i18n/zh-hant.ts b/apps/desktop/src/i18n/zh-hant.ts index ff5145efb8..505e799dc1 100644 --- a/apps/desktop/src/i18n/zh-hant.ts +++ b/apps/desktop/src/i18n/zh-hant.ts @@ -100,6 +100,9 @@ export const zhHant = defineLocale({ `先登出已儲存的遠端瀏覽器工作階段,然後開啟${signInLabel}。使用本機閘道可切換至內建後端。`, signOutAndSignIn: '登出並重新登入', remoteFailureHint: '在「閘道設定」中檢查閘道 URL 與登入,或切換至本機閘道。', + cloudDownTitle: 'Nous Cloud 代理已停機', + cloudDownDescription: '此閘道連線的 Nous 託管雲端代理正在回傳伺服器錯誤。無法在此處重新啟動——請檢查其狀態、切換至本機閘道,或取得支援。', + cloudDownHint: '請前往 https://portal.nousresearch.com 查看後端狀態,使用下方的本機閘道,或在 Discord (discord.gg/NousResearch) 上與我們聯繫。', hideRecentLogs: '隱藏最近記錄', showRecentLogs: '顯示最近記錄', signedInTitle: '已登入', diff --git a/apps/desktop/src/i18n/zh.ts b/apps/desktop/src/i18n/zh.ts index b1dbcb07ae..db548684dd 100644 --- a/apps/desktop/src/i18n/zh.ts +++ b/apps/desktop/src/i18n/zh.ts @@ -100,6 +100,9 @@ export const zh: Translations = { `先退出已保存的远程浏览器会话,然后打开${signInLabel}。也可以使用本地网关切换到随应用提供的后端。`, signOutAndSignIn: '退出并重新登录', remoteFailureHint: '在“网关设置”中检查网关 URL 和登录,或切换到本地网关。', + cloudDownTitle: 'Nous Cloud 代理已宕机', + cloudDownDescription: '此网关连接的 Nous 托管云代理正在返回服务器错误。无法在此处重启——请检查其状态、切换到本地网关或获取支持。', + cloudDownHint: '请访问 https://portal.nousresearch.com 查看后端状态,使用下方的本地网关,或在 Discord (discord.gg/NousResearch) 上联系我们。', hideRecentLogs: '隐藏最近日志', showRecentLogs: '显示最近日志', signedInTitle: '已登录',