mirror of
https://github.com/stablyai/orca.git
synced 2026-10-02 16:02:15 +00:00
The split silently dropped jira.searchUsers and runtimeEnvironments.retryControlConnection. Neither failed typecheck: the bridge modules carried no satisfies annotation and the composed api object was unannotated, so a missing key was only a runtime TypeError in the renderer. Annotates each module against PreloadApi, the type window.api is already declared as, so the contract supplies the shape rather than a parallel copy. Deleting jira.searchUsers now fails with TS2741 naming the key. Turning this on surfaced 106 places where a bridge locally annotated Promise<unknown> or unknown[] over a contract that declares concrete types -- the bridge was erasing types the renderer relied on. Those annotations are gone. Also exposes app.awaitBeforeUnloadCheckpoint, which was declared and called but never actually on the bridge, so the lazy-chunk recovery reload optional-chained to a no-op and navigated without joining the checkpoint. The missing key was caught by the new annotation rather than by hand.
146 lines
5.8 KiB
TypeScript
146 lines
5.8 KiB
TypeScript
import { ipcRenderer } from 'electron'
|
|
import type { ClientHostedBrowserRowsEvent } from '../../shared/client-hosted-browser-rows'
|
|
import type {
|
|
RuntimeBrowserDriverState,
|
|
RuntimeRendererSyncWindowGraph,
|
|
RuntimeStatus,
|
|
RuntimeSyncWindowGraphResult,
|
|
RuntimeTerminalDriverState
|
|
} from '../../shared/runtime-types'
|
|
import type { RuntimeRpcResponse } from '../../shared/runtime-rpc-envelope'
|
|
import type { RuntimeEnvironmentSubscriptionHandle } from '../runtime-environment-subscriptions'
|
|
import type { PreloadApi } from '../api-types'
|
|
|
|
export const runtimeApi = {
|
|
syncWindowGraph: (graph: RuntimeRendererSyncWindowGraph): Promise<RuntimeSyncWindowGraphResult> =>
|
|
ipcRenderer.invoke('runtime:syncWindowGraph', graph),
|
|
getStatus: (): Promise<RuntimeStatus> => ipcRenderer.invoke('runtime:getStatus'),
|
|
call: (args: { method: string; params?: unknown }): Promise<RuntimeRpcResponse<unknown>> =>
|
|
ipcRenderer.invoke('runtime:call', args),
|
|
subscribe: async (
|
|
args: { method: string; params?: unknown },
|
|
callback: (response: RuntimeRpcResponse<unknown>) => void
|
|
): Promise<RuntimeEnvironmentSubscriptionHandle> => {
|
|
const subscriptionId = `desktop-${crypto.randomUUID()}`
|
|
const channel = `runtime:subscription:${subscriptionId}`
|
|
const listener = (_event: Electron.IpcRendererEvent, response: RuntimeRpcResponse<unknown>) =>
|
|
callback(response)
|
|
ipcRenderer.on(channel, listener)
|
|
try {
|
|
await ipcRenderer.invoke('runtime:subscribe', { subscriptionId, ...args })
|
|
} catch (error) {
|
|
ipcRenderer.removeListener(channel, listener)
|
|
throw error
|
|
}
|
|
return {
|
|
unsubscribe: () => {
|
|
ipcRenderer.removeListener(channel, listener)
|
|
ipcRenderer.send('runtime:unsubscribe', { subscriptionId })
|
|
},
|
|
sendBinary: () => {
|
|
throw new Error('Local runtime subscriptions do not accept binary input')
|
|
}
|
|
}
|
|
},
|
|
getTerminalFitOverrides: (): Promise<
|
|
{ ptyId: string; mode: 'mobile-fit' | 'remote-desktop-fit'; cols: number; rows: number }[]
|
|
> => ipcRenderer.invoke('runtime:getTerminalFitOverrides'),
|
|
getTerminalDrivers: (): Promise<
|
|
{
|
|
ptyId: string
|
|
driver: RuntimeTerminalDriverState
|
|
}[]
|
|
> => ipcRenderer.invoke('runtime:getTerminalDrivers'),
|
|
getBrowserDrivers: (): Promise<
|
|
{
|
|
browserPageId: string
|
|
driver: RuntimeBrowserDriverState
|
|
}[]
|
|
> => ipcRenderer.invoke('runtime:getBrowserDrivers'),
|
|
getBrowserRemoteViewerPages: (): Promise<string[]> =>
|
|
ipcRenderer.invoke('runtime:getBrowserRemoteViewerPages'),
|
|
getClientHostedBrowserRows: (): Promise<ClientHostedBrowserRowsEvent[]> =>
|
|
ipcRenderer.invoke('runtime:getClientHostedBrowserRows'),
|
|
restoreTerminalFit: (ptyId: string): Promise<{ restored: boolean }> =>
|
|
ipcRenderer.invoke('runtime:restoreTerminalFit', { ptyId }),
|
|
reclaimBrowserForDesktop: (browserPageId: string): Promise<{ reclaimed: boolean }> =>
|
|
ipcRenderer.invoke('runtime:reclaimBrowserForDesktop', { browserPageId }),
|
|
onTerminalFitOverrideChanged: (
|
|
callback: (event: {
|
|
ptyId: string
|
|
mode: 'mobile-fit' | 'remote-desktop-fit' | 'desktop-fit'
|
|
cols: number
|
|
rows: number
|
|
}) => void
|
|
): (() => void) => {
|
|
const listener = (
|
|
_event: Electron.IpcRendererEvent,
|
|
data: {
|
|
ptyId: string
|
|
mode: 'mobile-fit' | 'remote-desktop-fit' | 'desktop-fit'
|
|
cols: number
|
|
rows: number
|
|
}
|
|
) => callback(data)
|
|
ipcRenderer.on('runtime:terminalFitOverrideChanged', listener)
|
|
return () => ipcRenderer.removeListener('runtime:terminalFitOverrideChanged', listener)
|
|
},
|
|
onTerminalDriverChanged: (
|
|
callback: (event: { ptyId: string; driver: RuntimeTerminalDriverState }) => void
|
|
): (() => void) => {
|
|
const listener = (
|
|
_event: Electron.IpcRendererEvent,
|
|
data: {
|
|
ptyId: string
|
|
driver: RuntimeTerminalDriverState
|
|
}
|
|
) => callback(data)
|
|
ipcRenderer.on('runtime:terminalDriverChanged', listener)
|
|
return () => ipcRenderer.removeListener('runtime:terminalDriverChanged', listener)
|
|
},
|
|
onNativeChatLaunchDraftResolved: (
|
|
callback: (event: { tabId: string; text: string; createdAt: number }) => void
|
|
): (() => void) => {
|
|
const listener = (
|
|
_event: Electron.IpcRendererEvent,
|
|
data: { tabId: string; text: string; createdAt: number }
|
|
) => callback(data)
|
|
ipcRenderer.on('runtime:nativeChatLaunchDraftResolved', listener)
|
|
return () => ipcRenderer.removeListener('runtime:nativeChatLaunchDraftResolved', listener)
|
|
},
|
|
onBrowserDriverChanged: (
|
|
callback: (event: { browserPageId: string; driver: RuntimeBrowserDriverState }) => void
|
|
): (() => void) => {
|
|
const listener = (
|
|
_event: Electron.IpcRendererEvent,
|
|
data: {
|
|
browserPageId: string
|
|
driver: RuntimeBrowserDriverState
|
|
}
|
|
) => callback(data)
|
|
ipcRenderer.on('runtime:browserDriverChanged', listener)
|
|
return () => ipcRenderer.removeListener('runtime:browserDriverChanged', listener)
|
|
},
|
|
onBrowserRemoteViewersChanged: (
|
|
callback: (event: { browserPageId: string; hasRemoteViewers: boolean }) => void
|
|
): (() => void) => {
|
|
const listener = (
|
|
_event: Electron.IpcRendererEvent,
|
|
data: {
|
|
browserPageId: string
|
|
hasRemoteViewers: boolean
|
|
}
|
|
) => callback(data)
|
|
ipcRenderer.on('runtime:browserRemoteViewersChanged', listener)
|
|
return () => ipcRenderer.removeListener('runtime:browserRemoteViewersChanged', listener)
|
|
},
|
|
onClientHostedBrowserRowsChanged: (
|
|
callback: (event: ClientHostedBrowserRowsEvent) => void
|
|
): (() => void) => {
|
|
const listener = (_event: Electron.IpcRendererEvent, data: ClientHostedBrowserRowsEvent) =>
|
|
callback(data)
|
|
ipcRenderer.on('runtime:clientHostedBrowserRowsChanged', listener)
|
|
return () => ipcRenderer.removeListener('runtime:clientHostedBrowserRowsChanged', listener)
|
|
}
|
|
} satisfies PreloadApi['runtime']
|