From 48f2ccb65c641ca0b034a84045defc7a452dcc2e Mon Sep 17 00:00:00 2001 From: HexLab98 Date: Sun, 23 Aug 2026 08:09:08 +0700 Subject: [PATCH] fix(desktop): latch unsigned OAuth boots so the Sign in overlay stays put No token and no cookie cannot self-heal. Tag that throw with isReauthRequired so boot stops retrying and Sign in stays clickable. Leave needsOauthLogin-only ticket 401s retryable for AT/RT rotation. --- apps/desktop/electron/backend-health.ts | 17 +++++++++++++++++ apps/desktop/electron/main.ts | 15 +++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/apps/desktop/electron/backend-health.ts b/apps/desktop/electron/backend-health.ts index ff380f1390..5b08fecefb 100644 --- a/apps/desktop/electron/backend-health.ts +++ b/apps/desktop/electron/backend-health.ts @@ -38,6 +38,10 @@ export interface HermesReadyOptions { export const REMOTE_SESSION_EXPIRED_MESSAGE = 'Your remote gateway session has expired. Open Settings → Gateway and click "Sign in" again.' +export const REMOTE_UNSIGNED_OAUTH_MESSAGE = + 'Remote Hermes gateway uses OAuth, but you are not signed in. ' + + 'Open Settings → Gateway and click "Sign in", or switch back to Local.' + /** * True for HTTP 502/503/504 from the backend — a server-side fault, not a * connectivity or auth issue. These keep polling in the readiness loop but, @@ -200,6 +204,19 @@ export function makeReauthRequiredError(detail?: string): Error { return error } +/** + * No native token and no live cookie: boot cannot self-heal. Must carry + * `isReauthRequired` so startHermes latches; `needsOauthLogin` alone only + * drives Sign in copy and would retry after #88070, hiding the overlay. + */ +export function makeUnsignedOauthError(): Error { + const error = new Error(REMOTE_UNSIGNED_OAUTH_MESSAGE) as any + error.needsOauthLogin = true + error.isReauthRequired = true + + return error +} + export function isReauthRequiredError(error: unknown): boolean { return Boolean((error as any)?.isReauthRequired) } diff --git a/apps/desktop/electron/main.ts b/apps/desktop/electron/main.ts index 04b1db7409..591569b987 100644 --- a/apps/desktop/electron/main.ts +++ b/apps/desktop/electron/main.ts @@ -35,7 +35,12 @@ import { stopBackendChild as stopBackendChildImpl, stopBackendTreesForUpdate } f import { dashboardFallbackArgs, sourceDeclaresServe } from './backend-command' import { createBackendConnectionState } from './backend-connection-state' import { buildDesktopBackendEnv, hermesManagedNodePathEntries, normalizeHermesHomeRoot } from './backend-env' -import { isReauthRequiredError, makeNousCloudBackendDownError, waitForHermesReady } from './backend-health' +import { + isReauthRequiredError, + makeNousCloudBackendDownError, + makeUnsignedOauthError, + waitForHermesReady +} from './backend-health' import { backendCommandMatches, createBackendOwnership, createBackendShutdownCoordinator } from './backend-ownership' import { canImportHermesCli, @@ -9008,13 +9013,7 @@ async function buildRemoteConnection( !oauthSessionIsLive(hasNativeSession(baseUrl), await hasLiveOauthSession(baseUrl)) && oauthGuardMayHardFail(await gatewayAuthProviders(baseUrl, remoteHeaders)) ) { - const err = new Error( - 'Remote Hermes gateway uses OAuth, but you are not signed in. ' + - 'Open Settings → Gateway and click "Sign in", or switch back to Local.' - ) as any - - err.needsOauthLogin = true - throw err + throw makeUnsignedOauthError() } let ticket