Files
orca/src/cli/runtime/remote-runtime-compat-gate.ts
T
Brennan Benson cf5f427d43 Keep worktree branches unless CLI deletion is requested (#35948)
* Keep CLI-removed worktree branches unless requested

* Bind branch policy checks to removal connections

* Remove redundant local default removal test row

* Negotiate worktree branch policy on the mutation connection

* Fix removal integration compiler boundaries and type imports

* Use checked annotations in paired removal fixtures

* Reset CLI integration exit status across test runtimes
2026-10-30 01:37:01 -07:00

85 lines
2.8 KiB
TypeScript

import type { PairedRuntimeConnection } from '../../shared/paired-runtime-connection'
import { describeRuntimeCompatBlock, evaluateRuntimeCompat } from '../../shared/protocol-compat'
import {
MIN_COMPATIBLE_RUNTIME_SERVER_VERSION,
RUNTIME_PROTOCOL_VERSION
} from '../../shared/protocol-version'
import type {
RuntimeRequestSelection,
RuntimeOrchestrationEnvelope
} from '../../shared/runtime-rpc-envelope'
import type { RuntimeStatus } from '../../shared/runtime-types'
import { markEnvironmentUsed } from './environments'
import { RuntimeClientError, RuntimeRpcFailureError, type RuntimeRpcResponse } from './types'
import type {
sendWebSocketRequest,
sendWebSocketRequestWithStatusPreflight
} from './websocket-transport'
type WebSocketTransport = {
sendWebSocketRequest: typeof sendWebSocketRequest
sendWebSocketRequestWithStatusPreflight: typeof sendWebSocketRequestWithStatusPreflight
}
export class RemoteRuntimeCompatGate {
private checked = false
constructor(
private readonly userDataPath: string,
private readonly environmentSelector: string | null
) {}
send<TResult>(args: {
transport: WebSocketTransport
connection: PairedRuntimeConnection
method: string
params: unknown
timeoutMs: number
envelope?: RuntimeOrchestrationEnvelope
requestSelection?: RuntimeRequestSelection
}): Promise<RuntimeRpcResponse<TResult>> {
if (!args.requestSelection && (this.checked || args.method === 'status.get')) {
return args.transport.sendWebSocketRequest<TResult>(
args.connection,
args.method,
args.params,
args.timeoutMs,
args.envelope
)
}
return args.transport.sendWebSocketRequestWithStatusPreflight<TResult>(
args.connection,
args.method,
args.params,
args.timeoutMs,
(response) => {
if (response.ok === false) {
throw new RuntimeRpcFailureError(response)
}
this.noteVerifiedStatus(response.result)
if (this.environmentSelector) {
markEnvironmentUsed(this.userDataPath, this.environmentSelector, {
runtimeId: response._meta.runtimeId
})
}
},
args.envelope,
args.requestSelection
)
}
noteVerifiedStatus(status: RuntimeStatus): void {
const verdict = evaluateRuntimeCompat({
clientProtocolVersion: RUNTIME_PROTOCOL_VERSION,
minCompatibleServerProtocolVersion: MIN_COMPATIBLE_RUNTIME_SERVER_VERSION,
serverProtocolVersion: status.runtimeProtocolVersion ?? status.protocolVersion,
serverMinCompatibleClientProtocolVersion:
status.minCompatibleRuntimeClientVersion ?? status.minCompatibleMobileVersion
})
if (verdict.kind === 'blocked') {
throw new RuntimeClientError('incompatible_runtime', describeRuntimeCompatBlock(verdict))
}
this.checked = true
}
}