mirror of
https://github.com/lahfir/agent-desktop.git
synced 2026-08-03 20:56:01 +00:00
Settle the Playwright-grade reliability contract in agent-desktop-core before the Windows/Linux adapters are built, so they inherit it instead of redesigning it. Every command now observes, waits, verifies, and reports honestly instead of firing blindly. Highlights: capability-supertrait split of PlatformAdapter with not_supported() defaults; canonical role/state vocabulary with live `is --property visible`; display enumeration (`list-displays`) and honest `--screen` with scale factor; truthful Automation permission; `native_id` identity spine; window-id-first resolution; serializable `LocatorQuery` with live `find`; default-on auto-wait before every ref action; three-way `hit_test` occlusion gate; `scroll_into_view` in core; core accessible-name precedence; typed `ActionStep` delivery tier; `ProcessState` and `APP_UNRESPONSIVE`; `LaunchOptions`; baseline-diff desktop signals (`wait --event`); typed clipboard (`Text`/`Image`/`FileUrls`); mouse modifier chords and `mouse-wheel`. Hardened through a 35-reviewer pass with independent validation and a green live e2e gate (109/0), plus a head-vs-main performance comparison harness. BREAKING CHANGE: default-on auto-wait changes the timing of every previously-untouched ref-action call (bounded 5000 ms default; `--timeout-ms 0` restores single-shot). `ENVELOPE_VERSION` is now `2.1` (adds the `APP_UNRESPONSIVE` code and process state in error details). FFI ABI major is `3` (append-only struct evolution; `wait --event` is intentionally not exposed over FFI). The legacy string clipboard API is removed in favor of typed content. `key-down`/`key-up` fail closed until daemon-owned held input exists. `close-app` verifies termination and the osascript fallback path is removed. `--text` matching is subtree containment: `find --text X --first` returns the outermost matching container.
112 lines
3.3 KiB
JavaScript
Executable file
112 lines
3.3 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
|
|
const { spawn } = require('child_process');
|
|
const { existsSync, accessSync, chmodSync, constants } = require('fs');
|
|
const { isAbsolute, join } = require('path');
|
|
const { platform, arch } = require('os');
|
|
|
|
const binDir = __dirname;
|
|
const MACOS_HELPER_NAME = 'agent-desktop-macos-helper';
|
|
const MACOS_HELPER_PATH_ENV = 'AGENT_DESKTOP_MACOS_HELPER_PATH';
|
|
|
|
function getBinaryName() {
|
|
const os = platform();
|
|
const cpuArch = arch();
|
|
|
|
const platformMap = {
|
|
'darwin-arm64': 'agent-desktop-darwin-arm64',
|
|
'darwin-x64': 'agent-desktop-darwin-x64',
|
|
'linux-x64': 'agent-desktop-linux-x64',
|
|
'linux-arm64': 'agent-desktop-linux-arm64',
|
|
'win32-x64': 'agent-desktop-win32-x64.exe',
|
|
};
|
|
|
|
return platformMap[`${os}-${cpuArch}`] || null;
|
|
}
|
|
|
|
function main() {
|
|
const binaryName = getBinaryName();
|
|
|
|
if (!binaryName) {
|
|
console.error(`Error: Unsupported platform: ${platform()}-${arch()}`);
|
|
console.error('agent-desktop currently supports: macOS (ARM64, x64)');
|
|
console.error('Windows and Linux support is coming in Phase 2.');
|
|
console.error('See: https://github.com/lahfir/agent-desktop');
|
|
process.exit(1);
|
|
}
|
|
|
|
const binaryPath = join(binDir, binaryName);
|
|
|
|
if (!binaryPath || !existsSync(binaryPath)) {
|
|
console.error(`Error: Native binary not found for ${platform()}-${arch()}`);
|
|
console.error(`Expected: ${binaryPath}`);
|
|
console.error('');
|
|
console.error('Try reinstalling:');
|
|
console.error(' npm install -g agent-desktop');
|
|
console.error('');
|
|
console.error('Or download directly from:');
|
|
console.error(' https://github.com/lahfir/agent-desktop/releases');
|
|
|
|
if (typeof process.versions.bun !== 'undefined') {
|
|
console.error('');
|
|
console.error('Bun detected — postinstall scripts require --trust:');
|
|
console.error(' bun install -g --trust agent-desktop');
|
|
}
|
|
|
|
process.exit(1);
|
|
}
|
|
|
|
if (platform() !== 'win32') {
|
|
try {
|
|
accessSync(binaryPath, constants.X_OK);
|
|
} catch {
|
|
try {
|
|
chmodSync(binaryPath, 0o755);
|
|
} catch (err) {
|
|
console.error(`Error: Cannot make binary executable: ${err.message}`);
|
|
console.error('Try running: chmod +x ' + binaryPath);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (platform() === 'darwin') {
|
|
const override = process.env[MACOS_HELPER_PATH_ENV];
|
|
if (override && !isAbsolute(override)) {
|
|
console.error(`Error: ${MACOS_HELPER_PATH_ENV} must be an absolute path`);
|
|
process.exit(1);
|
|
}
|
|
const helperPath = override || join(binDir, MACOS_HELPER_NAME);
|
|
if (!existsSync(helperPath)) {
|
|
console.error(`Error: macOS helper not found: ${helperPath}`);
|
|
console.error('Reinstall agent-desktop so the CLI and helper come from the same release.');
|
|
process.exit(1);
|
|
}
|
|
try {
|
|
accessSync(helperPath, constants.X_OK);
|
|
} catch {
|
|
try {
|
|
chmodSync(helperPath, 0o755);
|
|
} catch (err) {
|
|
console.error(`Error: Cannot make macOS helper executable: ${err.message}`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
stdio: 'inherit',
|
|
windowsHide: false,
|
|
});
|
|
|
|
child.on('error', (err) => {
|
|
console.error(`Error executing binary: ${err.message}`);
|
|
process.exit(1);
|
|
});
|
|
|
|
child.on('close', (code) => {
|
|
process.exit(code ?? 0);
|
|
});
|
|
}
|
|
|
|
main();
|