blob: 6a40a688247fd1178932682828d862dbfcc330f7 [file]
import { createHash } from 'node:crypto';
import {
accessSync,
closeSync,
constants,
fstatSync,
openSync,
readFileSync,
} from 'node:fs';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import type { CuaDriverRoleSnapshot } from '@maka/computer-use';
import type { CuaDriverBackendOptions } from '@maka/computer-use';
import {
selectComputerUseBackend,
type SelectedComputerUseBackend,
} from '@maka/computer-use';
import type { CuOverlayHook } from '@maka/runtime';
export interface ComputerUseHostState {
selected: SelectedComputerUseBackend;
binaryPath?: string;
expectedBinarySha256?: string;
}
function readRegularFile(path: string): Buffer {
const fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW);
try {
if (!fstatSync(fd).isFile()) {
throw new Error('expected a regular file');
}
return readFileSync(fd);
} finally {
closeSync(fd);
}
}
export function createComputerUseHost(input: {
isPackaged: boolean;
resourcesPath: string;
manifestPath?: string;
binaryPath?: string;
compressFrame?: (
base64: string,
mimeType: string,
) => { base64: string; mimeType: 'image/png' | 'image/jpeg' };
physicalInputRecentlyActive?: () => boolean | Promise<boolean>;
onTrace?: CuaDriverBackendOptions['onTrace'];
overlay?: CuOverlayHook;
}): ComputerUseHostState {
const manifestPath = input.manifestPath ?? (input.isPackaged
? join(input.resourcesPath, 'bundled-tools.json')
: resolve(
dirname(fileURLToPath(import.meta.url)),
'..',
'..',
'bundled-tools.json',
));
const binaryPath = input.binaryPath ?? (input.isPackaged
? join(input.resourcesPath, 'bin', 'cua-driver')
: resolve(
dirname(fileURLToPath(import.meta.url)),
'..',
'..',
'resources',
'bin',
'cua-driver',
));
try {
const manifest = JSON.parse(readRegularFile(manifestPath).toString('utf8')) as {
cuaDriver?: {
binarySha256?: string;
distributionReady?: boolean;
expectedVersion?: string;
expectedProtocolVersion?: string;
};
};
const expectedBinarySha256 = manifest.cuaDriver?.binarySha256;
const expectedServerVersion = manifest.cuaDriver?.expectedVersion;
const expectedProtocolVersion =
manifest.cuaDriver?.expectedProtocolVersion;
if (input.isPackaged && manifest.cuaDriver?.distributionReady !== true) {
return { selected: selectComputerUseBackend() };
}
if (!expectedBinarySha256 || !/^[a-f0-9]{64}$/.test(expectedBinarySha256)) {
return { selected: selectComputerUseBackend() };
}
accessSync(binaryPath, constants.R_OK | constants.X_OK);
const actual = createHash('sha256')
.update(readRegularFile(binaryPath))
.digest('hex');
if (actual !== expectedBinarySha256) {
return { selected: selectComputerUseBackend() };
}
return {
selected: selectComputerUseBackend({
binaryPath,
expectedBinarySha256,
expectedServerName: 'cua-driver',
...(expectedServerVersion ? { expectedServerVersion } : {}),
...(expectedProtocolVersion ? { expectedProtocolVersion } : {}),
...(input.compressFrame ? { compressFrame: input.compressFrame } : {}),
...(input.physicalInputRecentlyActive
? { physicalInputRecentlyActive: input.physicalInputRecentlyActive }
: {}),
...(input.onTrace ? { onTrace: input.onTrace } : {}),
...(input.overlay ? { overlay: input.overlay } : {}),
}),
binaryPath,
expectedBinarySha256,
};
} catch {
return { selected: selectComputerUseBackend() };
}
}
export function computerUseServiceHealth(
backendId: SelectedComputerUseBackend['backendId'],
state: {
action: CuaDriverRoleSnapshot;
capture: CuaDriverRoleSnapshot;
} | undefined,
): {
state: 'not_available' | 'not_run' | 'healthy' | 'degraded';
reason: string;
} {
if (backendId === 'none' || !state) {
return {
state: 'not_available',
reason: '未找到通过完整性检查且可分发的 cua-driver artifact。',
};
}
const roles = [state.action, state.capture];
if (roles.some((role) =>
role.state === 'unavailable' || role.state === 'disposed')) {
return {
state: 'not_available',
reason: roles.some((role) => role.state === 'disposed')
? 'cua-driver service 已停止。'
: 'cua-driver service 启动失败或已退出。',
};
}
if (roles.some((role) =>
role.state === 'starting' || role.state === 'backing_off')) {
return {
state: 'degraded',
reason: 'cua-driver service 正在启动或恢复。',
};
}
if (roles.every((role) => role.state === 'ready')) {
return {
state: 'healthy',
reason: 'cua-driver 操作与截图服务已就绪。',
};
}
if (roles.some((role) => role.state === 'ready')) {
return {
state: 'not_run',
reason: 'cua-driver 部分服务已启动,其余服务将在需要时启动。',
};
}
return {
state: 'not_run',
reason: 'cua-driver 已可用,将在首次调用时启动。',
};
}