mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 09:07:40 +00:00
* fix(browser): switch client-hosted profiles with staged guest replacement Squashed from #30351 by @oliver-mee onto the current main. Fixes #30350 * fix(browser): fence staged profile guests, release switch grants, carry host profile metadata - A fence during automation retirement now revokes and stops the staged guest. - A failed or late-settling switch releases its execution-host grant so the page can be recreated. - Staging cleanup failures before handover stay visible to executor close. - createPage/restorePage carry host-owned profile metadata to profile-switch-v1 desktops, so recovery and restore can rebuild a switched page. * fix(browser): roll back a switch whose replacement died, and report a lost old guest * fix(browser): resolve client-hosted pages before the server-local target path when switching profiles * fix(browser): a staged profile-switch guest owns downloads it starts while loading * fix(browser): keep the original placement until a timed-out switch settles * fix(browser): rebind the original guest before releasing a rolled-back staged guest * test(browser): type the harness guest release mock * fix(browser): release the replaced generation's download transfers when a switch commits * fix(browser): admit file transfers from a staged profile-switch guest while its switch is pending * fix(browser): release only the replaced generation's download transfers after a switch * refactor(shared): import BrowserNetworkExecutionHost from its own module, no re-export * fix(browser): adopt a profile switch the client finished after the caller timed out --------- Co-authored-by: Oliver Mee <102673257+oliver-mee@users.noreply.github.com>
58 lines
1.9 KiB
TypeScript
58 lines
1.9 KiB
TypeScript
import type { BrowserNetworkExecutionHost } from '../../shared/browser-network-execution-host'
|
|
import { parseExecutionHostId, type ExecutionHostId } from '../../shared/execution-host'
|
|
import type { ProjectExecutionRuntimeResolution } from '../../shared/project-execution-runtime'
|
|
import type { SshConnectionState } from '../../shared/ssh-types'
|
|
|
|
type RuntimeBrowserNetworkExecutionHostInput = {
|
|
runtimeId: string
|
|
runtimeRevision: number
|
|
executionHostId: ExecutionHostId
|
|
projectRuntime?: ProjectExecutionRuntimeResolution
|
|
sshState?: SshConnectionState
|
|
}
|
|
|
|
export function resolveRuntimeBrowserNetworkExecutionHost(
|
|
input: RuntimeBrowserNetworkExecutionHostInput
|
|
): BrowserNetworkExecutionHost {
|
|
const host = parseExecutionHostId(input.executionHostId)
|
|
if (host?.kind === 'local') {
|
|
if (input.projectRuntime?.status === 'repair-required') {
|
|
throw new Error('browser_tunnel_execution_host_unavailable')
|
|
}
|
|
if (input.projectRuntime?.runtime.kind === 'wsl') {
|
|
return {
|
|
kind: 'wsl',
|
|
runtimeId: input.runtimeId,
|
|
revision: input.runtimeRevision,
|
|
distro: input.projectRuntime.runtime.distro
|
|
}
|
|
}
|
|
return {
|
|
kind: 'native',
|
|
runtimeId: input.runtimeId,
|
|
revision: input.runtimeRevision
|
|
}
|
|
}
|
|
if (host?.kind === 'ssh') {
|
|
const state = input.sshState
|
|
const connectionGeneration = state?.connectionGeneration
|
|
if (
|
|
state?.targetId !== host.targetId ||
|
|
state.status !== 'connected' ||
|
|
!state.providerEpoch ||
|
|
typeof connectionGeneration !== 'number' ||
|
|
!Number.isSafeInteger(connectionGeneration) ||
|
|
connectionGeneration < 0
|
|
) {
|
|
throw new Error('browser_tunnel_execution_host_unavailable')
|
|
}
|
|
return {
|
|
kind: 'ssh',
|
|
targetId: host.targetId,
|
|
providerEpoch: state.providerEpoch,
|
|
connectionGeneration
|
|
}
|
|
}
|
|
throw new Error('browser_tunnel_execution_host_unavailable')
|
|
}
|