Files
orca/src/preload/api/app-bridge.ts
T
Jinwoo Hong 5e342d7e1a fix(orchestration): a worker report during an Orca restart is not rejected as a changed identity (#41014)
* fix(orchestration): a worker report during an Orca restart is not rejected as a changed identity

* refactor(orchestration): share the startup bounded wait; skip long-poll checks

* chore(orchestration): drop casts in the restart identity wait

* fix(orchestration): only long-poll checks skip the restart identity wait

* fix(orchestration): ordinary mail never waits for the restart identity restore
2026-11-11 00:59:18 -05:00

117 lines
6.0 KiB
TypeScript

import { ipcRenderer } from 'electron'
import type { AppIdentity } from '../../shared/app-identity'
import type { MacosUpgradeSupport } from '../../shared/macos-upgrade-support'
import type { FloatingTerminalCwdRequest } from '../../shared/ui-chrome-types'
import type { MacCapturedDigitRowChord } from '../../shared/macos-symbolic-hotkeys'
import type { MarkdownDocument } from '../../shared/file-listing/file-document'
import type { WriteTerminalRenderDesyncEvidenceArgs } from '../../shared/terminal/diagnostics/terminal-render-desync-evidence'
import {
KEYBOARD_LAYOUT_CHANGED_CHANNEL,
type KeyboardLayoutChangeEvent
} from '../../shared/keyboard-layout-events'
import { prepareAndInvokeAppRestart } from '../renderer-restart-wiring'
import { awaitBeforeUnloadCheckpoint, startupDiagnosticsEnabled } from '../preload-runtime-support'
import type { PreloadApi } from '../api-types'
export const appApi = {
getSystemLanguageDetection: (browserPreferences?: readonly string[]) =>
ipcRenderer.invoke('app:getSystemLanguageDetection', browserPreferences),
isProfileStateSaveDelayed: (): Promise<boolean> =>
ipcRenderer.invoke('app:isProfileStateSaveDelayed'),
onProfileStateSaveDelayChanged: (callback: (delayed: boolean) => void): (() => void) => {
const listener = (_event: Electron.IpcRendererEvent, delayed: boolean): void =>
callback(delayed === true)
ipcRenderer.on('app:profileStateSaveDelayChanged', listener)
return () => ipcRenderer.removeListener('app:profileStateSaveDelayChanged', listener)
},
getIdentity: (): Promise<AppIdentity> => ipcRenderer.invoke('app:getIdentity'),
getWindowsAdministratorStatus: (): Promise<boolean | null> =>
ipcRenderer.invoke('app:getWindowsAdministratorStatus'),
getMacosUpgradeSupport: (minimumMacosVersion: string): Promise<MacosUpgradeSupport> =>
ipcRenderer.invoke('app:getMacosUpgradeSupport', minimumMacosVersion),
restartAsAdministrator: (): Promise<void> =>
prepareAndInvokeAppRestart(
window,
() => ipcRenderer.invoke('app:restartAsAdministrator'),
awaitBeforeUnloadCheckpoint
),
getFeatureWallAssetBaseUrl: (): Promise<string> =>
ipcRenderer.invoke('app:getFeatureWallAssetBaseUrl'),
setWindowMaterialSuppressed: (suppressed: boolean): Promise<void> =>
ipcRenderer.invoke('app:setWindowMaterialSuppressed', suppressed),
relaunch: (): Promise<void> =>
prepareAndInvokeAppRestart(
window,
() => ipcRenderer.invoke('app:relaunch'),
awaitBeforeUnloadCheckpoint
),
restart: (): Promise<void> =>
prepareAndInvokeAppRestart(
window,
() => ipcRenderer.invoke('app:restart'),
awaitBeforeUnloadCheckpoint
),
reload: (): Promise<void> =>
prepareAndInvokeAppRestart(
window,
() => ipcRenderer.invoke('app:reload'),
awaitBeforeUnloadCheckpoint
),
stageBeforeUnloadSync: (args: Parameters<PreloadApi['app']['stageBeforeUnloadSync']>[0]) => {
const result: { ok?: unknown; error?: unknown } | null | undefined = ipcRenderer.sendSync(
'app:stage-before-unload-sync',
args
)
if (result?.ok !== true) {
const reason = typeof result?.error === 'string' ? `: ${result.error}` : '.'
throw new Error(`Failed to stage renderer state before unload${reason}`)
}
},
awaitBeforeUnloadCheckpoint: () => awaitBeforeUnloadCheckpoint(),
awaitFirstWindowStartupServices: (): Promise<void> =>
ipcRenderer.invoke('app:awaitFirstWindowStartupServices'),
awaitGitEnvironmentStartupBarrier: (): Promise<void> =>
ipcRenderer.invoke('app:awaitGitEnvironmentStartupBarrier'),
prepareTerminalStartupRestoration: (): Promise<void> =>
ipcRenderer.invoke('app:prepareTerminalStartupRestoration'),
holdsStructuredAgentSessions: (): Promise<boolean> =>
ipcRenderer.invoke('app:holdsStructuredAgentSessions'),
onStructuredAgentSessionsHeldChanged: (callback: (held: boolean) => void): (() => void) => {
const listener = (_event: Electron.IpcRendererEvent, held: boolean): void =>
callback(held === true)
ipcRenderer.on('app:structuredAgentSessionsHeldChanged', listener)
return () => ipcRenderer.removeListener('app:structuredAgentSessionsHeldChanged', listener)
},
recoverLegacyWorkerTerminalsForRendererStartup: (options?: {
afterReconnect?: boolean
}): Promise<void> =>
ipcRenderer.invoke('app:recoverLegacyWorkerTerminalsForRendererStartup', options),
startupDiagnostic: (event: string, details?: Record<string, unknown>): Promise<void> =>
startupDiagnosticsEnabled
? ipcRenderer.invoke('app:startupDiagnostic', event, details)
: Promise.resolve(),
getKeyboardInputSourceId: (): Promise<string | null> =>
ipcRenderer.invoke('app:getKeyboardInputSourceId'),
getMacCapturedDigitRowChords: (): Promise<MacCapturedDigitRowChord[]> =>
ipcRenderer.invoke('app:getMacCapturedDigitRowChords'),
getKeyboardLayoutSnapshot: () => ipcRenderer.invoke('app:getKeyboardLayoutSnapshot'),
onKeyboardLayoutChanged: (callback: (event: KeyboardLayoutChangeEvent) => void): (() => void) => {
const listener = (_event: Electron.IpcRendererEvent, event: KeyboardLayoutChangeEvent): void =>
callback(event)
ipcRenderer.on(KEYBOARD_LAYOUT_CHANGED_CHANNEL, listener)
return () => ipcRenderer.removeListener(KEYBOARD_LAYOUT_CHANGED_CHANNEL, listener)
},
setUnreadDockBadgeCount: (count: number): Promise<void> =>
ipcRenderer.invoke('app:setUnreadDockBadgeCount', count),
getFloatingTerminalCwd: (args?: FloatingTerminalCwdRequest): Promise<string> =>
ipcRenderer.invoke('app:getFloatingTerminalCwd', args),
getFloatingMarkdownDirectory: (): Promise<string> =>
ipcRenderer.invoke('app:getFloatingMarkdownDirectory'),
pickFloatingMarkdownDocument: (): Promise<MarkdownDocument | null> =>
ipcRenderer.invoke('app:pickFloatingMarkdownDocument'),
pickFloatingWorkspaceDirectory: (): Promise<string | null> =>
ipcRenderer.invoke('app:pickFloatingWorkspaceDirectory'),
writeTerminalRenderDesyncEvidence: (args: WriteTerminalRenderDesyncEvidenceArgs) =>
ipcRenderer.invoke('terminal:writeRenderDesyncEvidence', args)
} satisfies PreloadApi['app']