mirror of
https://github.com/stablyai/orca.git
synced 2026-10-01 00:02:10 +00:00
145 lines
4.6 KiB
TypeScript
145 lines
4.6 KiB
TypeScript
import {
|
|
addEnvironmentFromPairingCode,
|
|
RuntimeEnvironmentStoreError
|
|
} from '../../shared/runtime-environment-store'
|
|
import { parseHostAccessLink } from '../../shared/remote-pairing-address'
|
|
import {
|
|
verifyRemotePairingRuntimeStatus,
|
|
type VerifyAndAddRuntimeEnvironmentResult
|
|
} from '../../shared/remote-pairing-verification'
|
|
import { RemoteRuntimeClientError } from '../../shared/remote-runtime-client-error'
|
|
import { sendRemoteRuntimeRequest } from '../../shared/remote-runtime-client'
|
|
import { ELECTRON_REMOTE_RUNTIME_CLIENT_CAPABILITIES } from '../../shared/protocol-version'
|
|
import { redactRuntimeEnvironment } from '../../shared/runtime-environments'
|
|
import type { RuntimeStatus } from '../../shared/runtime-types'
|
|
|
|
type VerifyAndAddRuntimeEnvironmentArgs = {
|
|
name: string
|
|
pairingCode: string
|
|
allowLoopback?: boolean
|
|
}
|
|
|
|
export async function verifyAndAddRuntimeEnvironmentFromPairingCode(
|
|
userDataPath: string,
|
|
args: VerifyAndAddRuntimeEnvironmentArgs
|
|
): Promise<VerifyAndAddRuntimeEnvironmentResult> {
|
|
const parsed = parseHostAccessLink(args.pairingCode)
|
|
if (!parsed.ok) {
|
|
return { ok: false, kind: 'access-link-invalid', message: parsed.message }
|
|
}
|
|
if (parsed.value.endpointKind === 'loopback' && !args.allowLoopback) {
|
|
return {
|
|
ok: false,
|
|
kind: 'host-unreachable',
|
|
message: 'This access link points back to this device.'
|
|
}
|
|
}
|
|
|
|
let runtimeStatus: RuntimeStatus
|
|
try {
|
|
const response = await sendRemoteRuntimeRequest<RuntimeStatus>(
|
|
parsed.value.pairing,
|
|
'status.get',
|
|
undefined,
|
|
15_000,
|
|
undefined,
|
|
undefined,
|
|
ELECTRON_REMOTE_RUNTIME_CLIENT_CAPABILITIES
|
|
)
|
|
if (!response.ok) {
|
|
return {
|
|
ok: false,
|
|
kind: 'connection-interrupted',
|
|
message: response.error.message
|
|
}
|
|
}
|
|
const statusVerification = verifyRemotePairingRuntimeStatus(response.result)
|
|
if (!statusVerification.ok) {
|
|
return statusVerification
|
|
}
|
|
runtimeStatus = statusVerification.runtimeStatus
|
|
} catch (error) {
|
|
return classifyPairingVerificationError(error, parsed.value.displayEndpoint)
|
|
}
|
|
|
|
const usesSshTunnel = parsed.value.endpointKind === 'loopback' && args.allowLoopback === true
|
|
let environment: ReturnType<typeof addEnvironmentFromPairingCode>
|
|
try {
|
|
environment = addEnvironmentFromPairingCode(userDataPath, {
|
|
...args,
|
|
...(usesSshTunnel ? { connectionDependency: 'ssh-tunnel' as const } : {})
|
|
})
|
|
} catch (error) {
|
|
return {
|
|
ok: false,
|
|
kind: 'environment-save-failed',
|
|
message:
|
|
error instanceof RuntimeEnvironmentStoreError && error.code === 'invalid_argument'
|
|
? error.message
|
|
: 'Orca verified the host but could not save it. Check local settings storage and try again.'
|
|
}
|
|
}
|
|
return {
|
|
ok: true,
|
|
environment: redactRuntimeEnvironment(environment),
|
|
runtimeStatus
|
|
}
|
|
}
|
|
|
|
function classifyPairingVerificationError(
|
|
error: unknown,
|
|
endpoint: string
|
|
): VerifyAndAddRuntimeEnvironmentResult {
|
|
if (error instanceof RemoteRuntimeClientError) {
|
|
if (error.code === 'invalid_argument') {
|
|
return invalidAccessLinkResult()
|
|
}
|
|
if (error.code === 'unauthorized' || error.pairingStage === 'access-grant') {
|
|
return {
|
|
ok: false,
|
|
kind: 'access-link-invalid',
|
|
message: 'This access link is no longer valid. Generate a new link on the other host.'
|
|
}
|
|
}
|
|
if (error.pairingStage === 'host-identity') {
|
|
return {
|
|
ok: false,
|
|
kind: 'host-identity-mismatch',
|
|
message: `Orca reached ${endpoint}, but that host does not match this access link.`
|
|
}
|
|
}
|
|
if (error.pairingStage === 'runtime') {
|
|
return {
|
|
ok: false,
|
|
kind: 'connection-interrupted',
|
|
message: `The connection to ${endpoint} was interrupted during verification.`
|
|
}
|
|
}
|
|
if (error.pairingStage === 'connect') {
|
|
return unreachableHostResult(endpoint)
|
|
}
|
|
}
|
|
if (error instanceof Error) {
|
|
return error.message.startsWith('Invalid public key')
|
|
? invalidAccessLinkResult()
|
|
: { ok: false, kind: 'connection-interrupted', message: error.message }
|
|
}
|
|
return unreachableHostResult(endpoint)
|
|
}
|
|
|
|
function invalidAccessLinkResult(): VerifyAndAddRuntimeEnvironmentResult {
|
|
return {
|
|
ok: false,
|
|
kind: 'access-link-invalid',
|
|
message: 'This access link contains invalid connection details.'
|
|
}
|
|
}
|
|
|
|
function unreachableHostResult(endpoint: string): VerifyAndAddRuntimeEnvironmentResult {
|
|
return {
|
|
ok: false,
|
|
kind: 'host-unreachable',
|
|
message: `Cannot reach Orca at ${endpoint}. Confirm the other host is running and reachable.`
|
|
}
|
|
}
|