@cydm/pie 2.7.3 → 2.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builtin/extensions/ask-user/index.js +3 -3
- package/dist/builtin/extensions/plan-mode/index.js +3 -3
- package/dist/builtin/extensions/subagent/index.js +8 -7
- package/dist/builtin/extensions/todo/index.js +17 -24
- package/dist/builtin/skills/computer-use-axi/SKILL.md +7 -2
- package/dist/builtin/skills/computer-use-axi/computer-use-axi-broker.js +376 -220
- package/dist/builtin/skills/computer-use-axi/computer-use-axi-runtime.js +92 -15
- package/dist/chunks/{chunk-F3U2TYDT.js → chunk-BFHCZVNO.js} +8381 -7666
- package/dist/chunks/{chunk-MPTME6HX.js → chunk-MLRF72MK.js} +57 -38
- package/dist/chunks/{chunk-WLLZTG4W.js → chunk-OOUL3DRE.js} +2 -2
- package/dist/chunks/{chunk-E5JQ5SVA.js → chunk-SUPAWIKP.js} +601 -64
- package/dist/chunks/{src-TOJ3HCEX.js → src-DV4UYUNJ.js} +2 -2
- package/dist/chunks/{test-stream-6426JXLY.js → test-stream-SWO34GSS.js} +1 -1
- package/dist/cli.js +179 -533
- package/package.json +2 -2
|
@@ -48,6 +48,31 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
48
48
|
mod
|
|
49
49
|
));
|
|
50
50
|
|
|
51
|
+
// vendor/computer-use-axi/src/test-backend-guard.ts
|
|
52
|
+
function requireFakeBackend(env = process.env) {
|
|
53
|
+
return env.PIE_COMPUTER_USE_REQUIRE_FAKE_BACKEND === "1";
|
|
54
|
+
}
|
|
55
|
+
function assertNativeBackendAllowed() {
|
|
56
|
+
if (requireFakeBackend()) throw new Error("Required fake backend: native desktop access is forbidden (backend not installed in this module instance).");
|
|
57
|
+
}
|
|
58
|
+
function resolveTestOnlyBackend(env = process.env) {
|
|
59
|
+
if (requireFakeBackend(env) && (env.PIE_COMPUTER_USE_FAKE_BACKEND !== "1" || env.PIE_COMPUTER_USE_ENABLE_TEST_COMMANDS !== "1")) {
|
|
60
|
+
throw new Error("Required fake backend needs PIE_COMPUTER_USE_FAKE_BACKEND=1 and PIE_COMPUTER_USE_ENABLE_TEST_COMMANDS=1.");
|
|
61
|
+
}
|
|
62
|
+
if (env.PIE_COMPUTER_USE_FAKE_BACKEND !== "1") return { enabled: false };
|
|
63
|
+
if (env.PIE_COMPUTER_USE_ENABLE_TEST_COMMANDS !== "1") {
|
|
64
|
+
return {
|
|
65
|
+
enabled: false,
|
|
66
|
+
warning: "PIE_COMPUTER_USE_FAKE_BACKEND is test-only and was ignored: it requires PIE_COMPUTER_USE_ENABLE_TEST_COMMANDS=1 as well."
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return { enabled: true };
|
|
70
|
+
}
|
|
71
|
+
var init_test_backend_guard = __esm({
|
|
72
|
+
"vendor/computer-use-axi/src/test-backend-guard.ts"() {
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
51
76
|
// vendor/computer-use-axi/src/platform/coerce.ts
|
|
52
77
|
function toBoolean(value) {
|
|
53
78
|
return value === true || value === "true" || value === 1;
|
|
@@ -2307,7 +2332,7 @@ var require_websocket = __commonJS({
|
|
|
2307
2332
|
var http = __require("http");
|
|
2308
2333
|
var net4 = __require("net");
|
|
2309
2334
|
var tls = __require("tls");
|
|
2310
|
-
var { randomBytes, createHash:
|
|
2335
|
+
var { randomBytes, createHash: createHash5 } = __require("crypto");
|
|
2311
2336
|
var { Duplex, Readable } = __require("stream");
|
|
2312
2337
|
var { URL: URL2 } = __require("url");
|
|
2313
2338
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -2988,7 +3013,7 @@ var require_websocket = __commonJS({
|
|
|
2988
3013
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
2989
3014
|
return;
|
|
2990
3015
|
}
|
|
2991
|
-
const digest =
|
|
3016
|
+
const digest = createHash5("sha1").update(key + GUID).digest("base64");
|
|
2992
3017
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
2993
3018
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
2994
3019
|
return;
|
|
@@ -3357,7 +3382,7 @@ var require_websocket_server = __commonJS({
|
|
|
3357
3382
|
var EventEmitter = __require("events");
|
|
3358
3383
|
var http = __require("http");
|
|
3359
3384
|
var { Duplex } = __require("stream");
|
|
3360
|
-
var { createHash:
|
|
3385
|
+
var { createHash: createHash5 } = __require("crypto");
|
|
3361
3386
|
var extension2 = require_extension();
|
|
3362
3387
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
3363
3388
|
var subprotocol2 = require_subprotocol();
|
|
@@ -3664,7 +3689,7 @@ var require_websocket_server = __commonJS({
|
|
|
3664
3689
|
);
|
|
3665
3690
|
}
|
|
3666
3691
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
3667
|
-
const digest =
|
|
3692
|
+
const digest = createHash5("sha1").update(key + GUID).digest("base64");
|
|
3668
3693
|
const headers = [
|
|
3669
3694
|
"HTTP/1.1 101 Switching Protocols",
|
|
3670
3695
|
"Upgrade: websocket",
|
|
@@ -3852,6 +3877,7 @@ async function isResolvedHelperExecutable(filePath) {
|
|
|
3852
3877
|
return actualPath === expectedPath;
|
|
3853
3878
|
}
|
|
3854
3879
|
async function runProcess(command, args, timeoutMs, signal, env) {
|
|
3880
|
+
assertNativeBackendAllowed();
|
|
3855
3881
|
throwIfAborted(signal);
|
|
3856
3882
|
await new Promise((resolve2, reject) => {
|
|
3857
3883
|
const child = spawn(command, args, {
|
|
@@ -3900,6 +3926,7 @@ ${output}`.trim()));
|
|
|
3900
3926
|
var COMMAND_TIMEOUT_MS2, HELPER_PROTOCOL_VERSION, HELPER_SETUP_TIMEOUT_MS, HELPER_APP_PATH, HELPER_APP_EXECUTABLE_PATH, DEFAULT_HELPER_SOCKET_PATH, HELPER_SOCKET_PATH, usingExternalHelperSocket, PACKAGE_ROOT, SETUP_HELPER_SCRIPT, HelperTransportError, HelperCommandError, MacosHelperClient, macosHelper;
|
|
3901
3927
|
var init_helper = __esm({
|
|
3902
3928
|
"vendor/computer-use-axi/src/platform/macos/helper.ts"() {
|
|
3929
|
+
init_test_backend_guard();
|
|
3903
3930
|
init_coerce();
|
|
3904
3931
|
init_helper_path();
|
|
3905
3932
|
init_package_root();
|
|
@@ -3935,6 +3962,7 @@ var init_helper = __esm({
|
|
|
3935
3962
|
return this.diagnosticsCache;
|
|
3936
3963
|
}
|
|
3937
3964
|
async ensureInstalled(signal) {
|
|
3965
|
+
assertNativeBackendAllowed();
|
|
3938
3966
|
if (usingExternalHelperSocket) return;
|
|
3939
3967
|
if (await isExecutable(HELPER_APP_EXECUTABLE_PATH)) {
|
|
3940
3968
|
return;
|
|
@@ -3949,11 +3977,13 @@ var init_helper = __esm({
|
|
|
3949
3977
|
}
|
|
3950
3978
|
}
|
|
3951
3979
|
async launchDaemon(signal) {
|
|
3980
|
+
assertNativeBackendAllowed();
|
|
3952
3981
|
if (usingExternalHelperSocket) throw new HelperTransportError(`External helper socket is unavailable at ${HELPER_SOCKET_PATH}.`);
|
|
3953
3982
|
await mkdir(path9.dirname(HELPER_SOCKET_PATH), { recursive: true });
|
|
3954
3983
|
await runProcess("open", ["-n", "-g", HELPER_APP_PATH, "--args", "serve", "--socket", HELPER_SOCKET_PATH], COMMAND_TIMEOUT_MS2, signal);
|
|
3955
3984
|
}
|
|
3956
3985
|
async daemonCommand(cmd, args, timeoutMs, signal) {
|
|
3986
|
+
assertNativeBackendAllowed();
|
|
3957
3987
|
return await new Promise((resolve2, reject) => {
|
|
3958
3988
|
const id = `req_${++this.requestSequence}`;
|
|
3959
3989
|
const socket = net.createConnection(HELPER_SOCKET_PATH);
|
|
@@ -3996,6 +4026,7 @@ var init_helper = __esm({
|
|
|
3996
4026
|
});
|
|
3997
4027
|
}
|
|
3998
4028
|
async ensureDaemon(signal) {
|
|
4029
|
+
assertNativeBackendAllowed();
|
|
3999
4030
|
if (this.daemonAvailable) return true;
|
|
4000
4031
|
try {
|
|
4001
4032
|
await this.daemonCommand("diagnostics", {}, 1e3, signal);
|
|
@@ -4028,6 +4059,7 @@ var init_helper = __esm({
|
|
|
4028
4059
|
}
|
|
4029
4060
|
}
|
|
4030
4061
|
async restart(signal) {
|
|
4062
|
+
assertNativeBackendAllowed();
|
|
4031
4063
|
await this.command("shutdown", {}, { signal, timeoutMs: 2e3 }).catch(() => void 0);
|
|
4032
4064
|
this.daemonAvailable = false;
|
|
4033
4065
|
await sleep(400, signal);
|
|
@@ -4310,23 +4342,25 @@ var init_permissions2 = __esm({
|
|
|
4310
4342
|
});
|
|
4311
4343
|
|
|
4312
4344
|
// vendor/computer-use-axi/src/broker-server.ts
|
|
4313
|
-
|
|
4345
|
+
init_test_backend_guard();
|
|
4346
|
+
import { createHash as createHash4, randomUUID as randomUUID8 } from "node:crypto";
|
|
4314
4347
|
import { chmodSync as chmodSync2, lstatSync as lstatSync4, readFileSync as readFileSync4, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
4315
4348
|
import net3 from "node:net";
|
|
4316
4349
|
import path14 from "node:path";
|
|
4317
4350
|
|
|
4318
4351
|
// vendor/computer-use-axi/src/artifact-store.ts
|
|
4319
4352
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
|
|
4320
|
-
import { closeSync, existsSync as
|
|
4321
|
-
import
|
|
4353
|
+
import { closeSync, existsSync as existsSync3, lstatSync as lstatSync3, mkdirSync as mkdirSync4, openSync, readdirSync as readdirSync2, rmdirSync as rmdirSync2, unlinkSync as unlinkSync2, writeSync } from "node:fs";
|
|
4354
|
+
import path4 from "node:path";
|
|
4322
4355
|
|
|
4323
4356
|
// vendor/computer-use-axi/src/broker-protocol.ts
|
|
4324
4357
|
import { createHash, randomUUID } from "node:crypto";
|
|
4325
4358
|
import { chmodSync, lstatSync as lstatSync2, mkdirSync as mkdirSync3 } from "node:fs";
|
|
4326
|
-
import
|
|
4359
|
+
import path3 from "node:path";
|
|
4327
4360
|
|
|
4328
|
-
// vendor/computer-use-axi/src/
|
|
4329
|
-
import {
|
|
4361
|
+
// vendor/computer-use-axi/src/config.ts
|
|
4362
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
4363
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
4330
4364
|
import path from "node:path";
|
|
4331
4365
|
|
|
4332
4366
|
// src/config.ts
|
|
@@ -4370,26 +4404,151 @@ function getConfigDir() {
|
|
|
4370
4404
|
return join(homedir(), CONFIG_DIR_NAME);
|
|
4371
4405
|
}
|
|
4372
4406
|
|
|
4407
|
+
// vendor/computer-use-axi/host.ts
|
|
4408
|
+
function getAgentDir() {
|
|
4409
|
+
return getConfigDir();
|
|
4410
|
+
}
|
|
4411
|
+
|
|
4412
|
+
// vendor/computer-use-axi/src/config.ts
|
|
4413
|
+
var DEFAULT_CONFIG = {
|
|
4414
|
+
browser_use: true,
|
|
4415
|
+
headless: false,
|
|
4416
|
+
cursor_overlay: true,
|
|
4417
|
+
managed_browser: "chrome"
|
|
4418
|
+
};
|
|
4419
|
+
var REQUEST_ENV_KEYS = ["PIE_COMPUTER_USE_BROWSER_USE", "PIE_COMPUTER_USE_HEADLESS", "PIE_COMPUTER_USE_CURSOR_OVERLAY", "PIE_COMPUTER_USE_MANAGED_BROWSER", "PIE_COMPUTER_USE_HELIUM_EXECUTABLE", "PIE_COMPUTER_USE_CHROME_EXECUTABLE", "PIE_COMPUTER_USE_CDP_PORT", "PIE_COMPUTER_USE_DELIVERY_POLICY", "PIE_COMPUTER_USE_EVENT_DELIVERY"];
|
|
4420
|
+
function captureComputerUseEnvironment(env = process.env) {
|
|
4421
|
+
const out = {};
|
|
4422
|
+
for (const key of REQUEST_ENV_KEYS) {
|
|
4423
|
+
const value = env[key]?.trim();
|
|
4424
|
+
if (!value) continue;
|
|
4425
|
+
if (Buffer.byteLength(value) > 4096 || value.includes("\0")) throw new Error(`Invalid ${key}`);
|
|
4426
|
+
if (["PIE_COMPUTER_USE_BROWSER_USE", "PIE_COMPUTER_USE_HEADLESS", "PIE_COMPUTER_USE_CURSOR_OVERLAY"].includes(key)) {
|
|
4427
|
+
const parsed = parseBoolean(value);
|
|
4428
|
+
if (parsed === void 0) throw new Error(`Invalid ${key}`);
|
|
4429
|
+
out[key] = String(parsed);
|
|
4430
|
+
} else if (key === "PIE_COMPUTER_USE_MANAGED_BROWSER") {
|
|
4431
|
+
if (value !== "helium" && value !== "chrome") throw new Error(`Invalid ${key}`);
|
|
4432
|
+
out[key] = value;
|
|
4433
|
+
} else if (key === "PIE_COMPUTER_USE_DELIVERY_POLICY" || key === "PIE_COMPUTER_USE_EVENT_DELIVERY") {
|
|
4434
|
+
const policy = value.toLowerCase();
|
|
4435
|
+
if (!["default", "background", "pid", "foreground", "hid", "ax_only", "ax-only"].includes(policy)) throw new Error(`Invalid ${key}`);
|
|
4436
|
+
out[key] = policy;
|
|
4437
|
+
} else if (key === "PIE_COMPUTER_USE_CDP_PORT") {
|
|
4438
|
+
if (!/^\d+$/.test(value) || Number(value) < 1 || Number(value) > 65535) throw new Error(`Invalid ${key}`);
|
|
4439
|
+
out[key] = String(Number(value));
|
|
4440
|
+
} else {
|
|
4441
|
+
if (!path.isAbsolute(value)) throw new Error(`Invalid ${key}: expected absolute path`);
|
|
4442
|
+
out[key] = value;
|
|
4443
|
+
}
|
|
4444
|
+
}
|
|
4445
|
+
return Object.freeze(out);
|
|
4446
|
+
}
|
|
4447
|
+
var managedCdpPort;
|
|
4448
|
+
function setManagedCdpPort(port) {
|
|
4449
|
+
managedCdpPort = port;
|
|
4450
|
+
}
|
|
4451
|
+
function getComputerUseEnvironmentValue(key) {
|
|
4452
|
+
return operationConfig.getStore()?.environment[key] ?? (key === "PIE_COMPUTER_USE_CDP_PORT" ? managedCdpPort : void 0);
|
|
4453
|
+
}
|
|
4454
|
+
var operationConfig = new AsyncLocalStorage();
|
|
4455
|
+
var defaultLoaded = Object.freeze({ config: Object.freeze({ ...DEFAULT_CONFIG }), sources: [], env: {}, environment: {} });
|
|
4456
|
+
function withComputerUseConfig(cwd, run, environment) {
|
|
4457
|
+
return operationConfig.run(loadComputerUseConfig(cwd, environment), run);
|
|
4458
|
+
}
|
|
4459
|
+
function parseBoolean(value) {
|
|
4460
|
+
if (typeof value === "boolean") return value;
|
|
4461
|
+
if (typeof value === "number") return value === 1 ? true : value === 0 ? false : void 0;
|
|
4462
|
+
if (typeof value !== "string") return void 0;
|
|
4463
|
+
const normalized = value.trim().toLowerCase();
|
|
4464
|
+
if (["1", "true", "yes", "on", "enabled"].includes(normalized)) return true;
|
|
4465
|
+
if (["0", "false", "no", "off", "disabled"].includes(normalized)) return false;
|
|
4466
|
+
return void 0;
|
|
4467
|
+
}
|
|
4468
|
+
function normalizePartial(raw) {
|
|
4469
|
+
if (!raw || typeof raw !== "object") return {};
|
|
4470
|
+
const source = raw.computer_use && typeof raw.computer_use === "object" ? raw.computer_use : raw;
|
|
4471
|
+
const out = {};
|
|
4472
|
+
const browserUse = parseBoolean(source.browser_use);
|
|
4473
|
+
const headless = parseBoolean(source.headless);
|
|
4474
|
+
const cursorOverlay = parseBoolean(source.cursor_overlay);
|
|
4475
|
+
if (browserUse !== void 0) out.browser_use = browserUse;
|
|
4476
|
+
if (headless !== void 0) out.headless = headless;
|
|
4477
|
+
if (cursorOverlay !== void 0) out.cursor_overlay = cursorOverlay;
|
|
4478
|
+
const managedBrowser = source.managed_browser;
|
|
4479
|
+
if (managedBrowser === "helium" || managedBrowser === "chrome") out.managed_browser = managedBrowser;
|
|
4480
|
+
return out;
|
|
4481
|
+
}
|
|
4482
|
+
function readConfigFile(filePath) {
|
|
4483
|
+
if (!existsSync2(filePath)) return { path: filePath, exists: false };
|
|
4484
|
+
try {
|
|
4485
|
+
const parsed = JSON.parse(readFileSync2(filePath, "utf-8"));
|
|
4486
|
+
return { path: filePath, exists: true, values: normalizePartial(parsed) };
|
|
4487
|
+
} catch (error) {
|
|
4488
|
+
return { path: filePath, exists: true, error: error instanceof Error ? error.message : String(error) };
|
|
4489
|
+
}
|
|
4490
|
+
}
|
|
4491
|
+
function readEnv(environment) {
|
|
4492
|
+
const out = {};
|
|
4493
|
+
const browserUse = parseBoolean(environment.PIE_COMPUTER_USE_BROWSER_USE);
|
|
4494
|
+
const headless = parseBoolean(environment.PIE_COMPUTER_USE_HEADLESS);
|
|
4495
|
+
const cursorOverlay = parseBoolean(environment.PIE_COMPUTER_USE_CURSOR_OVERLAY);
|
|
4496
|
+
if (browserUse !== void 0) out.browser_use = browserUse;
|
|
4497
|
+
if (headless !== void 0) out.headless = headless;
|
|
4498
|
+
if (cursorOverlay !== void 0) out.cursor_overlay = cursorOverlay;
|
|
4499
|
+
const managedBrowser = environment.PIE_COMPUTER_USE_MANAGED_BROWSER;
|
|
4500
|
+
if (managedBrowser === "helium" || managedBrowser === "chrome") out.managed_browser = managedBrowser;
|
|
4501
|
+
return out;
|
|
4502
|
+
}
|
|
4503
|
+
function loadComputerUseConfig(cwd, environment = captureComputerUseEnvironment()) {
|
|
4504
|
+
const sources = [
|
|
4505
|
+
readConfigFile(path.join(getAgentDir(), "extensions", "computer-use.json")),
|
|
4506
|
+
readConfigFile(path.join(cwd, ".pie", "computer-use.json"))
|
|
4507
|
+
];
|
|
4508
|
+
environment = captureComputerUseEnvironment(environment);
|
|
4509
|
+
const env = readEnv(environment);
|
|
4510
|
+
const config = { ...DEFAULT_CONFIG };
|
|
4511
|
+
for (const source of sources) {
|
|
4512
|
+
if (source.values) Object.assign(config, source.values);
|
|
4513
|
+
}
|
|
4514
|
+
Object.assign(config, env);
|
|
4515
|
+
return Object.freeze({ config: Object.freeze(config), sources, env, environment });
|
|
4516
|
+
}
|
|
4517
|
+
function getComputerUseConfig() {
|
|
4518
|
+
return getLoadedComputerUseConfig().config;
|
|
4519
|
+
}
|
|
4520
|
+
function getLoadedComputerUseConfig() {
|
|
4521
|
+
return operationConfig.getStore() ?? defaultLoaded;
|
|
4522
|
+
}
|
|
4523
|
+
function isHeadlessMode() {
|
|
4524
|
+
return getComputerUseConfig().headless;
|
|
4525
|
+
}
|
|
4526
|
+
function isBrowserUseEnabled() {
|
|
4527
|
+
return getComputerUseConfig().browser_use;
|
|
4528
|
+
}
|
|
4529
|
+
|
|
4373
4530
|
// vendor/computer-use-axi/src/persist.ts
|
|
4531
|
+
import { lstatSync, mkdirSync as mkdirSync2, opendirSync, readdirSync, readFileSync as readFileSync3, renameSync as renameSync2, rmdirSync, unlinkSync, writeFileSync } from "node:fs";
|
|
4532
|
+
import path2 from "node:path";
|
|
4374
4533
|
function stateRootDir(env = process.env) {
|
|
4375
4534
|
const override = env.PIE_COMPUTER_USE_STATE_DIR?.trim();
|
|
4376
4535
|
if (override) return override;
|
|
4377
|
-
return
|
|
4536
|
+
return path2.join(getConfigDir(), "computer-use");
|
|
4378
4537
|
}
|
|
4379
4538
|
function statesDir(env = process.env) {
|
|
4380
|
-
return
|
|
4539
|
+
return path2.join(stateRootDir(env), "states");
|
|
4381
4540
|
}
|
|
4382
4541
|
function outputsDir(env = process.env) {
|
|
4383
|
-
return
|
|
4542
|
+
return path2.join(stateRootDir(env), "outputs");
|
|
4384
4543
|
}
|
|
4385
4544
|
function runtimeStatePath(env = process.env) {
|
|
4386
|
-
return
|
|
4545
|
+
return path2.join(stateRootDir(env), "runtime.json");
|
|
4387
4546
|
}
|
|
4388
4547
|
function brokerStateDir(env = process.env) {
|
|
4389
|
-
return
|
|
4548
|
+
return path2.join(stateRootDir(env), "broker");
|
|
4390
4549
|
}
|
|
4391
4550
|
function brokerManifestPath(env = process.env) {
|
|
4392
|
-
return
|
|
4551
|
+
return path2.join(brokerStateDir(env), "manifest.json");
|
|
4393
4552
|
}
|
|
4394
4553
|
function loadBrokerManifest(env = process.env) {
|
|
4395
4554
|
const manifest = readJsonFile(brokerManifestPath(env));
|
|
@@ -4406,7 +4565,7 @@ function saveBrokerManifest(manifest, env = process.env) {
|
|
|
4406
4565
|
writeJsonAtomic(brokerManifestPath(env), { ...manifest, stateIds: manifest.stateIds.slice(0, 256) });
|
|
4407
4566
|
}
|
|
4408
4567
|
function brokerDrainMarkerPath(env = process.env) {
|
|
4409
|
-
return
|
|
4568
|
+
return path2.join(brokerStateDir(env), "draining.json");
|
|
4410
4569
|
}
|
|
4411
4570
|
function loadDrainMarker(env = process.env) {
|
|
4412
4571
|
const marker = readJsonFile(brokerDrainMarkerPath(env));
|
|
@@ -4445,7 +4604,7 @@ function cleanupLegacyBrokerCache(env = process.env) {
|
|
|
4445
4604
|
try {
|
|
4446
4605
|
for (const name of readdirSync(statesDirPath).slice(0, 512)) {
|
|
4447
4606
|
if (!/^[A-Za-z0-9-]+\.json$/.test(name)) continue;
|
|
4448
|
-
const target =
|
|
4607
|
+
const target = path2.join(statesDirPath, name);
|
|
4449
4608
|
try {
|
|
4450
4609
|
const stats = lstatSync(target);
|
|
4451
4610
|
if (!stats.isFile() || stats.isSymbolicLink()) continue;
|
|
@@ -4460,7 +4619,7 @@ function cleanupLegacyBrokerCache(env = process.env) {
|
|
|
4460
4619
|
try {
|
|
4461
4620
|
for (const name of readdirSync(oldOutputs).slice(0, 512)) {
|
|
4462
4621
|
if (!/^o\d+\.(txt|meta\.json)$/.test(name)) continue;
|
|
4463
|
-
const target =
|
|
4622
|
+
const target = path2.join(oldOutputs, name);
|
|
4464
4623
|
try {
|
|
4465
4624
|
const stats = lstatSync(target);
|
|
4466
4625
|
if (!stats.isFile() || stats.isSymbolicLink()) continue;
|
|
@@ -4471,17 +4630,54 @@ function cleanupLegacyBrokerCache(env = process.env) {
|
|
|
4471
4630
|
}
|
|
4472
4631
|
} catch {
|
|
4473
4632
|
}
|
|
4633
|
+
outputs2 += cleanupOrphanOwnerOutputs(path2.join(oldOutputs, "owners"));
|
|
4474
4634
|
return { runtimeFile, states, outputs: outputs2 };
|
|
4475
4635
|
}
|
|
4636
|
+
function cleanupOrphanOwnerOutputs(root) {
|
|
4637
|
+
try {
|
|
4638
|
+
const stat = lstatSync(root);
|
|
4639
|
+
if (!stat.isDirectory() || stat.isSymbolicLink()) throw new Error("Unsafe computer-use outputs directory");
|
|
4640
|
+
} catch (error) {
|
|
4641
|
+
if (error.code === "ENOENT") return 0;
|
|
4642
|
+
throw error;
|
|
4643
|
+
}
|
|
4644
|
+
let remaining = 65536;
|
|
4645
|
+
let removed = 0;
|
|
4646
|
+
const visit = (directory, depth) => {
|
|
4647
|
+
const handle = opendirSync(directory);
|
|
4648
|
+
try {
|
|
4649
|
+
for (let entry = handle.readSync(); entry; entry = handle.readSync()) {
|
|
4650
|
+
if (--remaining < 0) throw new Error("Computer-use stale output cleanup budget exceeded; refusing unaccounted output storage");
|
|
4651
|
+
const target = path2.join(directory, entry.name);
|
|
4652
|
+
const stat = lstatSync(target);
|
|
4653
|
+
if (stat.isSymbolicLink()) {
|
|
4654
|
+
unlinkSync(target);
|
|
4655
|
+
continue;
|
|
4656
|
+
}
|
|
4657
|
+
if (stat.isDirectory() && depth === 0) {
|
|
4658
|
+
visit(target, 1);
|
|
4659
|
+
rmdirSync(target);
|
|
4660
|
+
} else if (stat.isFile() && depth === 1 && /^\d+\.txt$/.test(entry.name)) {
|
|
4661
|
+
unlinkSync(target);
|
|
4662
|
+
removed++;
|
|
4663
|
+
} else throw new Error(`Unexpected computer-use output entry: ${target}`);
|
|
4664
|
+
}
|
|
4665
|
+
} finally {
|
|
4666
|
+
handle.closeSync();
|
|
4667
|
+
}
|
|
4668
|
+
};
|
|
4669
|
+
visit(root, 0);
|
|
4670
|
+
return removed;
|
|
4671
|
+
}
|
|
4476
4672
|
function writeJsonAtomic(filePath, value) {
|
|
4477
|
-
mkdirSync2(
|
|
4673
|
+
mkdirSync2(path2.dirname(filePath), { recursive: true });
|
|
4478
4674
|
const temp = `${filePath}.${process.pid}.tmp`;
|
|
4479
4675
|
writeFileSync(temp, JSON.stringify(value), "utf8");
|
|
4480
4676
|
renameSync2(temp, filePath);
|
|
4481
4677
|
}
|
|
4482
4678
|
function readJsonFile(filePath) {
|
|
4483
4679
|
try {
|
|
4484
|
-
return JSON.parse(
|
|
4680
|
+
return JSON.parse(readFileSync3(filePath, "utf8"));
|
|
4485
4681
|
} catch {
|
|
4486
4682
|
return void 0;
|
|
4487
4683
|
}
|
|
@@ -4498,8 +4694,8 @@ function normalizeComputerUseOwner(value) {
|
|
|
4498
4694
|
}
|
|
4499
4695
|
|
|
4500
4696
|
// vendor/computer-use-axi/src/broker-protocol.ts
|
|
4501
|
-
var BROKER_PROTOCOL_VERSION =
|
|
4502
|
-
var BROKER_ENGINE_VERSION =
|
|
4697
|
+
var BROKER_PROTOCOL_VERSION = 3;
|
|
4698
|
+
var BROKER_ENGINE_VERSION = 4;
|
|
4503
4699
|
var BROKER_PACKAGE_VERSION = "0.5.1-pie.1";
|
|
4504
4700
|
var BROKER_RESULT_CACHE_MAX_ENTRIES = 256;
|
|
4505
4701
|
var BROKER_REPLAY_LEDGER_MAX_IDS = 65536;
|
|
@@ -4825,7 +5021,19 @@ function validateRequest(value) {
|
|
|
4825
5021
|
}
|
|
4826
5022
|
const params = validateCommandParams(command, value.params);
|
|
4827
5023
|
const cwd = value.cwd === void 0 ? process.cwd() : boundedString(value.cwd, "cwd", 4096);
|
|
4828
|
-
if (!
|
|
5024
|
+
if (!path3.isAbsolute(cwd)) throw new BrokerProtocolError("invalid_request", "cwd must be absolute.");
|
|
5025
|
+
const rawEnvironment = value.environment ?? {};
|
|
5026
|
+
assertPlainRecord(rawEnvironment, "environment");
|
|
5027
|
+
assertKeys(rawEnvironment, "environment", REQUEST_ENV_KEYS);
|
|
5028
|
+
for (const entry of Object.values(rawEnvironment)) {
|
|
5029
|
+
if (typeof entry !== "string") throw new BrokerProtocolError("invalid_request", "environment values must be strings.");
|
|
5030
|
+
}
|
|
5031
|
+
let environment;
|
|
5032
|
+
try {
|
|
5033
|
+
environment = captureComputerUseEnvironment(rawEnvironment);
|
|
5034
|
+
} catch (error) {
|
|
5035
|
+
throw new BrokerProtocolError("invalid_request", String(error));
|
|
5036
|
+
}
|
|
4829
5037
|
const budgetMs = value.budgetMs === void 0 ? BROKER_DEFAULT_REQUEST_BUDGET_MS : Math.trunc(boundedNumber(value.budgetMs, "budgetMs", BROKER_MIN_REQUEST_BUDGET_MS, BROKER_MAX_REQUEST_BUDGET_MS));
|
|
4830
5038
|
return {
|
|
4831
5039
|
requestId: value.requestId,
|
|
@@ -4835,6 +5043,7 @@ function validateRequest(value) {
|
|
|
4835
5043
|
command,
|
|
4836
5044
|
params,
|
|
4837
5045
|
cwd,
|
|
5046
|
+
environment,
|
|
4838
5047
|
budgetMs
|
|
4839
5048
|
};
|
|
4840
5049
|
}
|
|
@@ -4844,8 +5053,10 @@ function validateHello(value) {
|
|
|
4844
5053
|
if (value.protocolVersion !== BROKER_PROTOCOL_VERSION) {
|
|
4845
5054
|
throw new BrokerProtocolError("protocol_mismatch", `Protocol mismatch: broker ${BROKER_PROTOCOL_VERSION}, client ${String(value.protocolVersion)}.`);
|
|
4846
5055
|
}
|
|
5056
|
+
if (value.buildIdentity !== BROKER_BUILD.identity) throw new BrokerProtocolError("build_mismatch", "Broker engine build identity differs.");
|
|
4847
5057
|
return {
|
|
4848
5058
|
type: "hello",
|
|
5059
|
+
buildIdentity: value.buildIdentity,
|
|
4849
5060
|
protocolVersion: value.protocolVersion,
|
|
4850
5061
|
clientVersion: value.clientVersion === void 0 ? void 0 : boundedString(value.clientVersion, "clientVersion", 128)
|
|
4851
5062
|
};
|
|
@@ -4874,6 +5085,7 @@ var FrameDecoder = class {
|
|
|
4874
5085
|
for (; ; ) {
|
|
4875
5086
|
const newline = this.buffer.indexOf(10);
|
|
4876
5087
|
if (newline < 0) break;
|
|
5088
|
+
if (newline > this.maxBytes) throw new BrokerProtocolError("frame_too_large", `Frame exceeds the ${this.maxBytes}-byte limit.`);
|
|
4877
5089
|
const line = this.buffer.subarray(0, newline).toString("utf8").trim();
|
|
4878
5090
|
this.buffer = this.buffer.subarray(newline + 1);
|
|
4879
5091
|
if (!line) continue;
|
|
@@ -4898,11 +5110,11 @@ function resolveBrokerEndpoint(env = process.env) {
|
|
|
4898
5110
|
const key = createHash("sha256").update(seed).digest("hex").slice(0, 16);
|
|
4899
5111
|
return { kind: "named-pipe", path: `\\\\.\\pipe\\pie-computer-use-axi-${key}` };
|
|
4900
5112
|
}
|
|
4901
|
-
const socketPath = socketOverride ||
|
|
5113
|
+
const socketPath = socketOverride || path3.join(stateRootDir(env), "run", "broker.sock");
|
|
4902
5114
|
if (Buffer.byteLength(socketPath, "utf8") > 100) {
|
|
4903
5115
|
throw new BrokerProtocolError("endpoint_too_long", `Unix socket path is ${Buffer.byteLength(socketPath)} bytes (limit ~104): ${socketPath}. Set PIE_COMPUTER_USE_BROKER_SOCKET to a shorter path.`);
|
|
4904
5116
|
}
|
|
4905
|
-
return { kind: "unix-socket", path: socketPath, directory:
|
|
5117
|
+
return { kind: "unix-socket", path: socketPath, directory: path3.dirname(socketPath) };
|
|
4906
5118
|
}
|
|
4907
5119
|
function ensurePrivateDirectory(directory) {
|
|
4908
5120
|
mkdirSync3(directory, { recursive: true, mode: 448 });
|
|
@@ -4921,8 +5133,8 @@ function canonicalize(value) {
|
|
|
4921
5133
|
}
|
|
4922
5134
|
return value;
|
|
4923
5135
|
}
|
|
4924
|
-
function requestFingerprint(command, params, cwd) {
|
|
4925
|
-
const seed = JSON.stringify({ command, params: canonicalize(params), cwd });
|
|
5136
|
+
function requestFingerprint(command, params, cwd, environment = {}) {
|
|
5137
|
+
const seed = JSON.stringify({ command, params: canonicalize(params), cwd, environment: canonicalize(environment) });
|
|
4926
5138
|
return createHash("sha256").update(seed).digest("hex").slice(0, 32);
|
|
4927
5139
|
}
|
|
4928
5140
|
|
|
@@ -4953,8 +5165,9 @@ var ArtifactStore = class {
|
|
|
4953
5165
|
totalBytes = 0;
|
|
4954
5166
|
/** Absolute path for one owner/generation, created 0700 and symlink-checked. */
|
|
4955
5167
|
directoryFor(owner, generation = this.options.generation) {
|
|
4956
|
-
const root =
|
|
4957
|
-
const
|
|
5168
|
+
const root = path4.join(this.options.root, safeComponent(generation, "generation"));
|
|
5169
|
+
const ownerKey = `owner-${createHash2("sha256").update(normalizeComputerUseOwner(owner)).digest("hex")}`;
|
|
5170
|
+
const ownerDir = path4.join(root, ownerKey);
|
|
4958
5171
|
ensurePrivateDirectory(this.options.root);
|
|
4959
5172
|
ensurePrivateDirectory(root);
|
|
4960
5173
|
ensurePrivateDirectory(ownerDir);
|
|
@@ -4964,7 +5177,7 @@ var ArtifactStore = class {
|
|
|
4964
5177
|
const generation = input.generation ?? this.options.generation;
|
|
4965
5178
|
const directory = this.directoryFor(input.owner, generation);
|
|
4966
5179
|
const artifactId = randomUUID2();
|
|
4967
|
-
const absolutePath =
|
|
5180
|
+
const absolutePath = path4.join(directory, `${artifactId}.${extensionFor(input.mimeType)}`);
|
|
4968
5181
|
const fd = openSync(absolutePath, "wx", 384);
|
|
4969
5182
|
try {
|
|
4970
5183
|
let offset = 0;
|
|
@@ -4993,6 +5206,16 @@ var ArtifactStore = class {
|
|
|
4993
5206
|
this.sweep();
|
|
4994
5207
|
return record;
|
|
4995
5208
|
}
|
|
5209
|
+
/** Hold existing evidence while a hydrated observation is used. */
|
|
5210
|
+
pinForState(stateId2) {
|
|
5211
|
+
const ids = [];
|
|
5212
|
+
for (const record of this.records.values()) {
|
|
5213
|
+
if (record.stateId !== stateId2) continue;
|
|
5214
|
+
this.pin(record.artifactId);
|
|
5215
|
+
ids.push(record.artifactId);
|
|
5216
|
+
}
|
|
5217
|
+
return ids;
|
|
5218
|
+
}
|
|
4996
5219
|
pin(artifactId) {
|
|
4997
5220
|
this.pins.set(artifactId, (this.pins.get(artifactId) ?? 0) + 1);
|
|
4998
5221
|
}
|
|
@@ -5044,13 +5267,13 @@ var ArtifactStore = class {
|
|
|
5044
5267
|
/** Remove files for a generation that no longer owns the broker. */
|
|
5045
5268
|
cleanupGeneration(generation) {
|
|
5046
5269
|
if (!SAFE_COMPONENT.test(generation)) return 0;
|
|
5047
|
-
const directory =
|
|
5048
|
-
if (!
|
|
5270
|
+
const directory = path4.join(this.options.root, generation);
|
|
5271
|
+
if (!existsSync3(directory)) return 0;
|
|
5049
5272
|
const stats = lstatSync3(directory);
|
|
5050
5273
|
if (stats.isSymbolicLink() || !stats.isDirectory()) return 0;
|
|
5051
5274
|
let removed = 0;
|
|
5052
5275
|
for (const name of readdirSync2(directory)) {
|
|
5053
|
-
const ownerDir =
|
|
5276
|
+
const ownerDir = path4.join(directory, name);
|
|
5054
5277
|
let ownerStats;
|
|
5055
5278
|
try {
|
|
5056
5279
|
ownerStats = lstatSync3(ownerDir);
|
|
@@ -5059,7 +5282,7 @@ var ArtifactStore = class {
|
|
|
5059
5282
|
}
|
|
5060
5283
|
if (ownerStats.isSymbolicLink() || !ownerStats.isDirectory()) continue;
|
|
5061
5284
|
for (const file of readdirSync2(ownerDir)) {
|
|
5062
|
-
const target =
|
|
5285
|
+
const target = path4.join(ownerDir, file);
|
|
5063
5286
|
let fileStats;
|
|
5064
5287
|
try {
|
|
5065
5288
|
fileStats = lstatSync3(target);
|
|
@@ -5071,12 +5294,12 @@ var ArtifactStore = class {
|
|
|
5071
5294
|
removed += 1;
|
|
5072
5295
|
}
|
|
5073
5296
|
try {
|
|
5074
|
-
|
|
5297
|
+
rmdirSync2(ownerDir);
|
|
5075
5298
|
} catch {
|
|
5076
5299
|
}
|
|
5077
5300
|
}
|
|
5078
5301
|
try {
|
|
5079
|
-
|
|
5302
|
+
rmdirSync2(directory);
|
|
5080
5303
|
} catch {
|
|
5081
5304
|
}
|
|
5082
5305
|
return removed;
|
|
@@ -5100,7 +5323,7 @@ var ArtifactStore = class {
|
|
|
5100
5323
|
for (const name of names) {
|
|
5101
5324
|
if (scanned >= maxGenerations) break;
|
|
5102
5325
|
if (name === current || !SAFE_COMPONENT.test(name)) continue;
|
|
5103
|
-
const directory =
|
|
5326
|
+
const directory = path4.join(this.options.root, name);
|
|
5104
5327
|
let stats;
|
|
5105
5328
|
try {
|
|
5106
5329
|
stats = lstatSync3(directory);
|
|
@@ -5132,11 +5355,12 @@ var ArtifactStore = class {
|
|
|
5132
5355
|
};
|
|
5133
5356
|
function artifactsRoot(env = process.env) {
|
|
5134
5357
|
const base = env.PIE_COMPUTER_USE_ARTIFACTS_DIR?.trim();
|
|
5135
|
-
if (base) return
|
|
5136
|
-
return
|
|
5358
|
+
if (base) return path4.resolve(base);
|
|
5359
|
+
return path4.join(stateRootDir(env), "artifacts");
|
|
5137
5360
|
}
|
|
5138
5361
|
|
|
5139
5362
|
// vendor/computer-use-axi/src/bridge.ts
|
|
5363
|
+
init_test_backend_guard();
|
|
5140
5364
|
import { spawn as spawn4 } from "node:child_process";
|
|
5141
5365
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
5142
5366
|
import { constants as fsConstants5, mkdtempSync } from "node:fs";
|
|
@@ -5160,7 +5384,7 @@ function keys(value) {
|
|
|
5160
5384
|
if (!Array.isArray(value) || value.length === 0) throw new Error("keypress.keys must contain at least one key.");
|
|
5161
5385
|
return value.map((key) => String(key));
|
|
5162
5386
|
}
|
|
5163
|
-
function
|
|
5387
|
+
function path5(value, env) {
|
|
5164
5388
|
if (!Array.isArray(value) || value.length < 2) throw new Error("drag.path must contain at least two points.");
|
|
5165
5389
|
return value.map((point, index) => {
|
|
5166
5390
|
const x = Array.isArray(point) ? toFiniteNumber(point[0], NaN) : toFiniteNumber(point?.x, NaN);
|
|
@@ -5192,7 +5416,7 @@ function nativeTarget(action, operation, env) {
|
|
|
5192
5416
|
env.validatePoint(x, y);
|
|
5193
5417
|
return { x, y };
|
|
5194
5418
|
}
|
|
5195
|
-
if (operation === "drag" && action.path?.length) return
|
|
5419
|
+
if (operation === "drag" && action.path?.length) return path5(action.path, env)[0];
|
|
5196
5420
|
throw new Error(`${operation} requires either ref or both x and y.`);
|
|
5197
5421
|
}
|
|
5198
5422
|
function focusedTarget(env) {
|
|
@@ -5262,7 +5486,7 @@ function prepareAction(action, state, env) {
|
|
|
5262
5486
|
case "scroll":
|
|
5263
5487
|
return { action: operation, target, params: { scrollX: scrollDelta(action.scrollX), scrollY: scrollDelta(action.scrollY) }, usesCurrentFocus: false, needsForeground: false };
|
|
5264
5488
|
case "drag":
|
|
5265
|
-
return { action: operation, target, params: { path:
|
|
5489
|
+
return { action: operation, target, params: { path: path5(action.path, env) }, usesCurrentFocus: false, needsForeground: false };
|
|
5266
5490
|
case "moveMouse":
|
|
5267
5491
|
return { action: operation, target, params: {}, usesCurrentFocus: false, needsForeground: false };
|
|
5268
5492
|
}
|
|
@@ -5288,6 +5512,7 @@ function outcomeAfterObservedValues(current, actions, valueForRef) {
|
|
|
5288
5512
|
}
|
|
5289
5513
|
|
|
5290
5514
|
// vendor/computer-use-axi/src/cdp.ts
|
|
5515
|
+
init_test_backend_guard();
|
|
5291
5516
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
5292
5517
|
|
|
5293
5518
|
// ../../node_modules/ws/wrapper.mjs
|
|
@@ -5791,6 +6016,7 @@ var CdpTab = class _CdpTab {
|
|
|
5791
6016
|
loadFired;
|
|
5792
6017
|
static async connect(wsUrl, targetId, title, epoch = connectionEpoch) {
|
|
5793
6018
|
assertConnectionEpoch(epoch);
|
|
6019
|
+
assertNativeBackendAllowed();
|
|
5794
6020
|
const ws = new wrapper_default(wsUrl);
|
|
5795
6021
|
connectingSockets.add(ws);
|
|
5796
6022
|
try {
|
|
@@ -5950,6 +6176,7 @@ var CdpTab = class _CdpTab {
|
|
|
5950
6176
|
return entries;
|
|
5951
6177
|
}
|
|
5952
6178
|
send(method, params = {}) {
|
|
6179
|
+
assertNativeBackendAllowed();
|
|
5953
6180
|
const id = this.nextId++;
|
|
5954
6181
|
return new Promise((resolve2, reject) => {
|
|
5955
6182
|
const timer = setTimeout(() => {
|
|
@@ -6027,7 +6254,7 @@ var CdpTab = class _CdpTab {
|
|
|
6027
6254
|
};
|
|
6028
6255
|
var connectedTabs = /* @__PURE__ */ new Map();
|
|
6029
6256
|
var connectingTabs = /* @__PURE__ */ new Map();
|
|
6030
|
-
var lastConnectFailureAt =
|
|
6257
|
+
var lastConnectFailureAt = /* @__PURE__ */ new Map();
|
|
6031
6258
|
function disconnectCdp() {
|
|
6032
6259
|
if (disconnecting) return disconnecting;
|
|
6033
6260
|
connectionEpoch++;
|
|
@@ -6036,62 +6263,64 @@ function disconnectCdp() {
|
|
|
6036
6263
|
connectingSockets.clear();
|
|
6037
6264
|
connectedTabs.clear();
|
|
6038
6265
|
connectingTabs.clear();
|
|
6039
|
-
lastConnectFailureAt
|
|
6266
|
+
lastConnectFailureAt.clear();
|
|
6040
6267
|
disconnecting = Promise.all(tabs.map((tab) => tab.close())).then(() => void 0).finally(() => {
|
|
6041
6268
|
disconnecting = void 0;
|
|
6042
6269
|
});
|
|
6043
6270
|
return disconnecting;
|
|
6044
6271
|
}
|
|
6045
|
-
function cdpEnabled() {
|
|
6046
|
-
const rawPort = process.env.PIE_COMPUTER_USE_CDP_PORT ?? "";
|
|
6272
|
+
function cdpEnabled(rawPort = getComputerUseEnvironmentValue("PIE_COMPUTER_USE_CDP_PORT") ?? "") {
|
|
6047
6273
|
if (!/^\d+$/.test(rawPort)) return false;
|
|
6048
6274
|
const port = Number(rawPort);
|
|
6049
6275
|
return Number.isInteger(port) && port > 0 && port <= 65535 && typeof wrapper_default !== "undefined";
|
|
6050
6276
|
}
|
|
6051
6277
|
async function cdpTabForWindow(windowTitle, frame) {
|
|
6052
6278
|
const epoch = connectionEpoch;
|
|
6053
|
-
|
|
6054
|
-
if (
|
|
6279
|
+
const port = getComputerUseEnvironmentValue("PIE_COMPUTER_USE_CDP_PORT") ?? "";
|
|
6280
|
+
if (!cdpEnabled(port)) return void 0;
|
|
6281
|
+
if (Date.now() - (lastConnectFailureAt.get(port) ?? 0) < CONNECT_FAILURE_RETRY_MS) return void 0;
|
|
6055
6282
|
try {
|
|
6056
6283
|
assertConnectionEpoch(epoch);
|
|
6057
|
-
for (const tab of connectedTabs
|
|
6284
|
+
for (const [key2, tab] of connectedTabs) {
|
|
6285
|
+
if (!key2.startsWith(`${port}:`)) continue;
|
|
6058
6286
|
if (tab.isOpen && titlesMatch(tab.title, windowTitle) && await tabMatchesFrame(tab, frame)) {
|
|
6059
6287
|
assertConnectionEpoch(epoch);
|
|
6060
6288
|
if (tab.isOpen) return tab;
|
|
6061
6289
|
}
|
|
6062
6290
|
}
|
|
6063
|
-
const pages = await cdpPages(epoch);
|
|
6291
|
+
const pages = await cdpPages(epoch, port);
|
|
6064
6292
|
const match = await pickTab(pages, windowTitle, frame, epoch);
|
|
6065
6293
|
assertConnectionEpoch(epoch);
|
|
6066
6294
|
if (!match) return void 0;
|
|
6067
|
-
const
|
|
6295
|
+
const key = `${port}:${match.id}`;
|
|
6296
|
+
const existing = connectedTabs.get(key);
|
|
6068
6297
|
if (existing?.isOpen) {
|
|
6069
6298
|
existing.title = match.title;
|
|
6070
6299
|
return existing;
|
|
6071
6300
|
}
|
|
6072
|
-
let connecting = connectingTabs.get(
|
|
6301
|
+
let connecting = connectingTabs.get(key);
|
|
6073
6302
|
if (!connecting) {
|
|
6074
6303
|
connecting = CdpTab.connect(match.webSocketDebuggerUrl, match.id, match.title, epoch);
|
|
6075
|
-
connectingTabs.set(
|
|
6304
|
+
connectingTabs.set(key, connecting);
|
|
6076
6305
|
}
|
|
6077
6306
|
let connected;
|
|
6078
6307
|
try {
|
|
6079
6308
|
connected = await connecting;
|
|
6080
6309
|
} finally {
|
|
6081
|
-
if (connectingTabs.get(
|
|
6310
|
+
if (connectingTabs.get(key) === connecting) connectingTabs.delete(key);
|
|
6082
6311
|
}
|
|
6083
6312
|
assertConnectionEpoch(epoch);
|
|
6084
|
-
connectedTabs.set(
|
|
6313
|
+
connectedTabs.set(key, connected);
|
|
6085
6314
|
return connected;
|
|
6086
6315
|
} catch {
|
|
6087
|
-
if (epoch === connectionEpoch && !disconnecting) lastConnectFailureAt
|
|
6316
|
+
if (epoch === connectionEpoch && !disconnecting) lastConnectFailureAt.set(port, Date.now());
|
|
6088
6317
|
return void 0;
|
|
6089
6318
|
}
|
|
6090
6319
|
}
|
|
6091
|
-
async function listCdpPageContexts() {
|
|
6092
|
-
const pages = await cdpPages();
|
|
6320
|
+
async function listCdpPageContexts(port = getComputerUseEnvironmentValue("PIE_COMPUTER_USE_CDP_PORT")) {
|
|
6321
|
+
const pages = await cdpPages(connectionEpoch, port);
|
|
6093
6322
|
return pages.map((page) => ({
|
|
6094
|
-
contextId: cdpContextId(page.id),
|
|
6323
|
+
contextId: cdpContextId(page.id, port),
|
|
6095
6324
|
targetId: page.id,
|
|
6096
6325
|
title: page.title,
|
|
6097
6326
|
url: page.url ?? ""
|
|
@@ -6208,14 +6437,18 @@ async function withCdpContextTab(contextId, run) {
|
|
|
6208
6437
|
}
|
|
6209
6438
|
async function cdpPageForContext(contextId, epoch) {
|
|
6210
6439
|
if (!contextId.startsWith(CDP_CONTEXT_PREFIX)) return void 0;
|
|
6211
|
-
const
|
|
6212
|
-
const
|
|
6440
|
+
const identity = contextId.slice(CDP_CONTEXT_PREFIX.length);
|
|
6441
|
+
const separator = identity.indexOf(":");
|
|
6442
|
+
if (separator < 1) return void 0;
|
|
6443
|
+
const port = identity.slice(0, separator);
|
|
6444
|
+
const targetId = identity.slice(separator + 1);
|
|
6445
|
+
const pages = await cdpPages(epoch, port);
|
|
6213
6446
|
return pages.find((candidate) => candidate.id === targetId);
|
|
6214
6447
|
}
|
|
6215
|
-
async function cdpPages(epoch = connectionEpoch) {
|
|
6448
|
+
async function cdpPages(epoch = connectionEpoch, port = getComputerUseEnvironmentValue("PIE_COMPUTER_USE_CDP_PORT")) {
|
|
6216
6449
|
assertConnectionEpoch(epoch);
|
|
6217
|
-
if (!cdpEnabled()) return [];
|
|
6218
|
-
|
|
6450
|
+
if (!port || !cdpEnabled(port)) return [];
|
|
6451
|
+
assertNativeBackendAllowed();
|
|
6219
6452
|
const response = await fetch(`http://127.0.0.1:${port}/json/list`, { signal: AbortSignal.timeout(2e3) });
|
|
6220
6453
|
const targets = await response.json();
|
|
6221
6454
|
assertConnectionEpoch(epoch);
|
|
@@ -6223,8 +6456,8 @@ async function cdpPages(epoch = connectionEpoch) {
|
|
|
6223
6456
|
(target) => target.type === "page" && target.webSocketDebuggerUrl && isLocalDebuggerWebSocket(target.webSocketDebuggerUrl, port)
|
|
6224
6457
|
);
|
|
6225
6458
|
}
|
|
6226
|
-
function cdpContextId(targetId) {
|
|
6227
|
-
return `${CDP_CONTEXT_PREFIX}${targetId}`;
|
|
6459
|
+
function cdpContextId(targetId, port) {
|
|
6460
|
+
return `${CDP_CONTEXT_PREFIX}${port}:${targetId}`;
|
|
6228
6461
|
}
|
|
6229
6462
|
function axString(raw) {
|
|
6230
6463
|
const value = raw?.value ?? raw;
|
|
@@ -6371,98 +6604,6 @@ function titlesMatch(tabTitle, windowTitle) {
|
|
|
6371
6604
|
return tab === win || win.startsWith(tab) || tab.startsWith(win);
|
|
6372
6605
|
}
|
|
6373
6606
|
|
|
6374
|
-
// vendor/computer-use-axi/src/config.ts
|
|
6375
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
|
|
6376
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6377
|
-
import path5 from "node:path";
|
|
6378
|
-
|
|
6379
|
-
// vendor/computer-use-axi/host.ts
|
|
6380
|
-
function getAgentDir() {
|
|
6381
|
-
return getConfigDir();
|
|
6382
|
-
}
|
|
6383
|
-
|
|
6384
|
-
// vendor/computer-use-axi/src/config.ts
|
|
6385
|
-
var DEFAULT_CONFIG = {
|
|
6386
|
-
browser_use: true,
|
|
6387
|
-
headless: false,
|
|
6388
|
-
cursor_overlay: true,
|
|
6389
|
-
managed_browser: "chrome"
|
|
6390
|
-
};
|
|
6391
|
-
var operationConfig = new AsyncLocalStorage();
|
|
6392
|
-
var defaultLoaded = Object.freeze({ config: Object.freeze({ ...DEFAULT_CONFIG }), sources: [], env: {} });
|
|
6393
|
-
function withComputerUseConfig(cwd, run) {
|
|
6394
|
-
return operationConfig.run(loadComputerUseConfig(cwd), run);
|
|
6395
|
-
}
|
|
6396
|
-
function parseBoolean(value) {
|
|
6397
|
-
if (typeof value === "boolean") return value;
|
|
6398
|
-
if (typeof value === "number") return value === 1 ? true : value === 0 ? false : void 0;
|
|
6399
|
-
if (typeof value !== "string") return void 0;
|
|
6400
|
-
const normalized = value.trim().toLowerCase();
|
|
6401
|
-
if (["1", "true", "yes", "on", "enabled"].includes(normalized)) return true;
|
|
6402
|
-
if (["0", "false", "no", "off", "disabled"].includes(normalized)) return false;
|
|
6403
|
-
return void 0;
|
|
6404
|
-
}
|
|
6405
|
-
function normalizePartial(raw) {
|
|
6406
|
-
if (!raw || typeof raw !== "object") return {};
|
|
6407
|
-
const source = raw.computer_use && typeof raw.computer_use === "object" ? raw.computer_use : raw;
|
|
6408
|
-
const out = {};
|
|
6409
|
-
const browserUse = parseBoolean(source.browser_use);
|
|
6410
|
-
const headless = parseBoolean(source.headless);
|
|
6411
|
-
const cursorOverlay = parseBoolean(source.cursor_overlay);
|
|
6412
|
-
if (browserUse !== void 0) out.browser_use = browserUse;
|
|
6413
|
-
if (headless !== void 0) out.headless = headless;
|
|
6414
|
-
if (cursorOverlay !== void 0) out.cursor_overlay = cursorOverlay;
|
|
6415
|
-
const managedBrowser = source.managed_browser;
|
|
6416
|
-
if (managedBrowser === "helium" || managedBrowser === "chrome") out.managed_browser = managedBrowser;
|
|
6417
|
-
return out;
|
|
6418
|
-
}
|
|
6419
|
-
function readConfigFile(filePath) {
|
|
6420
|
-
if (!existsSync3(filePath)) return { path: filePath, exists: false };
|
|
6421
|
-
try {
|
|
6422
|
-
const parsed = JSON.parse(readFileSync3(filePath, "utf-8"));
|
|
6423
|
-
return { path: filePath, exists: true, values: normalizePartial(parsed) };
|
|
6424
|
-
} catch (error) {
|
|
6425
|
-
return { path: filePath, exists: true, error: error instanceof Error ? error.message : String(error) };
|
|
6426
|
-
}
|
|
6427
|
-
}
|
|
6428
|
-
function readEnv() {
|
|
6429
|
-
const out = {};
|
|
6430
|
-
const browserUse = parseBoolean(process.env.PIE_COMPUTER_USE_BROWSER_USE);
|
|
6431
|
-
const headless = parseBoolean(process.env.PIE_COMPUTER_USE_HEADLESS);
|
|
6432
|
-
const cursorOverlay = parseBoolean(process.env.PIE_COMPUTER_USE_CURSOR_OVERLAY);
|
|
6433
|
-
if (browserUse !== void 0) out.browser_use = browserUse;
|
|
6434
|
-
if (headless !== void 0) out.headless = headless;
|
|
6435
|
-
if (cursorOverlay !== void 0) out.cursor_overlay = cursorOverlay;
|
|
6436
|
-
const managedBrowser = process.env.PIE_COMPUTER_USE_MANAGED_BROWSER;
|
|
6437
|
-
if (managedBrowser === "helium" || managedBrowser === "chrome") out.managed_browser = managedBrowser;
|
|
6438
|
-
return out;
|
|
6439
|
-
}
|
|
6440
|
-
function loadComputerUseConfig(cwd) {
|
|
6441
|
-
const sources = [
|
|
6442
|
-
readConfigFile(path5.join(getAgentDir(), "extensions", "computer-use.json")),
|
|
6443
|
-
readConfigFile(path5.join(cwd, ".pie", "computer-use.json"))
|
|
6444
|
-
];
|
|
6445
|
-
const env = readEnv();
|
|
6446
|
-
const config = { ...DEFAULT_CONFIG };
|
|
6447
|
-
for (const source of sources) {
|
|
6448
|
-
if (source.values) Object.assign(config, source.values);
|
|
6449
|
-
}
|
|
6450
|
-
Object.assign(config, env);
|
|
6451
|
-
return Object.freeze({ config: Object.freeze(config), sources, env });
|
|
6452
|
-
}
|
|
6453
|
-
function getComputerUseConfig() {
|
|
6454
|
-
return getLoadedComputerUseConfig().config;
|
|
6455
|
-
}
|
|
6456
|
-
function getLoadedComputerUseConfig() {
|
|
6457
|
-
return operationConfig.getStore() ?? defaultLoaded;
|
|
6458
|
-
}
|
|
6459
|
-
function isHeadlessMode() {
|
|
6460
|
-
return getComputerUseConfig().headless;
|
|
6461
|
-
}
|
|
6462
|
-
function isBrowserUseEnabled() {
|
|
6463
|
-
return getComputerUseConfig().browser_use;
|
|
6464
|
-
}
|
|
6465
|
-
|
|
6466
6607
|
// vendor/computer-use-axi/src/note.ts
|
|
6467
6608
|
function normalizedLabel(value) {
|
|
6468
6609
|
return value.toLowerCase().replace(/\s+/g, " ").trim();
|
|
@@ -6616,8 +6757,9 @@ function renderNote(note) {
|
|
|
6616
6757
|
}
|
|
6617
6758
|
|
|
6618
6759
|
// vendor/computer-use-axi/src/output.ts
|
|
6619
|
-
import { closeSync as closeSync2,
|
|
6760
|
+
import { closeSync as closeSync2, openSync as openSync2, readSync, readdirSync as readdirSync3, statSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
6620
6761
|
import path6 from "node:path";
|
|
6762
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
6621
6763
|
var MODEL_TEXT_MAX_BYTES = 48 * 1024;
|
|
6622
6764
|
var MODEL_TEXT_MAX_LINES = 2e3;
|
|
6623
6765
|
var OUTPUT_PAGE_BYTES = 16 * 1024;
|
|
@@ -6629,8 +6771,13 @@ var outputs = /* @__PURE__ */ new Map();
|
|
|
6629
6771
|
var nextOutputId = 1;
|
|
6630
6772
|
var outputBytes = 0;
|
|
6631
6773
|
function outputDirectoryFor(owner) {
|
|
6632
|
-
const
|
|
6633
|
-
|
|
6774
|
+
const root = outputsDir();
|
|
6775
|
+
const owners = path6.join(root, "owners");
|
|
6776
|
+
const ownerKey = `owner-${createHash3("sha256").update(normalizeComputerUseOwner(owner)).digest("hex")}`;
|
|
6777
|
+
const dir = path6.join(owners, ownerKey);
|
|
6778
|
+
ensurePrivateDirectory(root);
|
|
6779
|
+
ensurePrivateDirectory(owners);
|
|
6780
|
+
ensurePrivateDirectory(dir);
|
|
6634
6781
|
return dir;
|
|
6635
6782
|
}
|
|
6636
6783
|
function utf8Prefix(bytes, maxBytes) {
|
|
@@ -6762,6 +6909,9 @@ function clearStoredOutputs(owner) {
|
|
|
6762
6909
|
// vendor/computer-use-axi/src/bridge.ts
|
|
6763
6910
|
init_coerce();
|
|
6764
6911
|
|
|
6912
|
+
// vendor/computer-use-axi/src/platform/index.ts
|
|
6913
|
+
init_test_backend_guard();
|
|
6914
|
+
|
|
6765
6915
|
// vendor/computer-use-axi/src/platform/macos/backend.ts
|
|
6766
6916
|
init_coerce();
|
|
6767
6917
|
init_helper();
|
|
@@ -6982,6 +7132,7 @@ init_architecture();
|
|
|
6982
7132
|
init_coerce();
|
|
6983
7133
|
|
|
6984
7134
|
// vendor/computer-use-axi/src/platform/linux/helper.ts
|
|
7135
|
+
init_test_backend_guard();
|
|
6985
7136
|
init_package_root();
|
|
6986
7137
|
import { spawn as spawn2 } from "node:child_process";
|
|
6987
7138
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
@@ -7005,6 +7156,7 @@ async function isExecutable2(filePath) {
|
|
|
7005
7156
|
async function runProcess2(command, args, timeoutMs, signal, env) {
|
|
7006
7157
|
if (signal?.aborted) throw new Error("Operation aborted.");
|
|
7007
7158
|
await new Promise((resolve2, reject) => {
|
|
7159
|
+
assertNativeBackendAllowed();
|
|
7008
7160
|
const child = spawn2(command, args, { stdio: ["ignore", "pipe", "pipe"], env });
|
|
7009
7161
|
let stdout = "";
|
|
7010
7162
|
let stderr = "";
|
|
@@ -7092,6 +7244,7 @@ var LinuxHelperClient = class {
|
|
|
7092
7244
|
this.buffer = "";
|
|
7093
7245
|
}
|
|
7094
7246
|
async ensureInstalled(signal) {
|
|
7247
|
+
assertNativeBackendAllowed();
|
|
7095
7248
|
if (await isExecutable2(this.helperPath) && this.installChecked) return;
|
|
7096
7249
|
if (!this.installPromise) {
|
|
7097
7250
|
const installPromise = (async () => {
|
|
@@ -7135,6 +7288,7 @@ var LinuxHelperClient = class {
|
|
|
7135
7288
|
return await waitForShared(this.processPromise, signal);
|
|
7136
7289
|
}
|
|
7137
7290
|
async startProcess() {
|
|
7291
|
+
assertNativeBackendAllowed();
|
|
7138
7292
|
const child = spawn2(this.helperPath, [], { stdio: ["pipe", "pipe", "pipe"] });
|
|
7139
7293
|
child.stdout.setEncoding("utf8");
|
|
7140
7294
|
child.stderr.setEncoding("utf8");
|
|
@@ -7187,6 +7341,7 @@ var LinuxHelperClient = class {
|
|
|
7187
7341
|
}
|
|
7188
7342
|
}
|
|
7189
7343
|
async command(cmd, args = {}, options) {
|
|
7344
|
+
assertNativeBackendAllowed();
|
|
7190
7345
|
const child = await this.process(options?.signal);
|
|
7191
7346
|
const id = randomUUID4();
|
|
7192
7347
|
const timeoutMs = options?.timeoutMs ?? COMMAND_TIMEOUT_MS3;
|
|
@@ -7386,6 +7541,7 @@ var linuxBackend = {
|
|
|
7386
7541
|
init_coerce();
|
|
7387
7542
|
|
|
7388
7543
|
// vendor/computer-use-axi/src/platform/windows/helper.ts
|
|
7544
|
+
init_test_backend_guard();
|
|
7389
7545
|
init_package_root();
|
|
7390
7546
|
import { spawn as spawn3 } from "node:child_process";
|
|
7391
7547
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
@@ -7409,6 +7565,7 @@ async function isExecutable3(filePath) {
|
|
|
7409
7565
|
async function runProcess3(command, args, timeoutMs, signal, env) {
|
|
7410
7566
|
if (signal?.aborted) throw new Error("Operation aborted.");
|
|
7411
7567
|
await new Promise((resolve2, reject) => {
|
|
7568
|
+
assertNativeBackendAllowed();
|
|
7412
7569
|
const child = spawn3(command, args, { stdio: ["ignore", "pipe", "pipe"], env });
|
|
7413
7570
|
let stdout = "";
|
|
7414
7571
|
let stderr = "";
|
|
@@ -7469,6 +7626,7 @@ var WindowsHelperClient = class {
|
|
|
7469
7626
|
child.unref();
|
|
7470
7627
|
}
|
|
7471
7628
|
async ensureInstalled(signal) {
|
|
7629
|
+
assertNativeBackendAllowed();
|
|
7472
7630
|
if (await isExecutable3(WINDOWS_HELPER_PATH) && this.installChecked) return;
|
|
7473
7631
|
await runProcess3(process.execPath, [SETUP_HELPER_SCRIPT3, "--platform", "windows", "--runtime"], HELPER_SETUP_TIMEOUT_MS3, signal, { ...process.env, ELECTRON_RUN_AS_NODE: "1", BUN_BE_BUN: "1" });
|
|
7474
7632
|
this.installChecked = true;
|
|
@@ -7477,6 +7635,7 @@ var WindowsHelperClient = class {
|
|
|
7477
7635
|
async process(signal) {
|
|
7478
7636
|
await this.ensureInstalled(signal);
|
|
7479
7637
|
if (this.child && this.child.exitCode === null && !this.child.killed) return this.child;
|
|
7638
|
+
assertNativeBackendAllowed();
|
|
7480
7639
|
const child = spawn3(WINDOWS_HELPER_PATH, [], { stdio: ["pipe", "pipe", "pipe"] });
|
|
7481
7640
|
child.stdout.setEncoding("utf8");
|
|
7482
7641
|
child.stderr.setEncoding("utf8");
|
|
@@ -7522,6 +7681,7 @@ var WindowsHelperClient = class {
|
|
|
7522
7681
|
}
|
|
7523
7682
|
}
|
|
7524
7683
|
async command(cmd, args = {}, options) {
|
|
7684
|
+
assertNativeBackendAllowed();
|
|
7525
7685
|
const child = await this.process(options?.signal);
|
|
7526
7686
|
const id = randomUUID5();
|
|
7527
7687
|
const timeoutMs = options?.timeoutMs ?? COMMAND_TIMEOUT_MS4;
|
|
@@ -7745,10 +7905,17 @@ var UnsupportedPlatformBackend = class {
|
|
|
7745
7905
|
}
|
|
7746
7906
|
};
|
|
7747
7907
|
function platformBackendForRuntime(platform = process.platform) {
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7908
|
+
const backend = platform === "darwin" ? macosPlatformBackend : platform === "win32" ? windowsBackend : platform === "linux" ? linuxBackend : new UnsupportedPlatformBackend(platform);
|
|
7909
|
+
return new Proxy(backend, {
|
|
7910
|
+
get(target, property, receiver) {
|
|
7911
|
+
const value = Reflect.get(target, property, receiver);
|
|
7912
|
+
if (typeof value !== "function") return value;
|
|
7913
|
+
return (...args) => {
|
|
7914
|
+
assertNativeBackendAllowed();
|
|
7915
|
+
return Reflect.apply(value, target, args);
|
|
7916
|
+
};
|
|
7917
|
+
}
|
|
7918
|
+
});
|
|
7752
7919
|
}
|
|
7753
7920
|
var currentPlatformBackend = platformBackendForRuntime();
|
|
7754
7921
|
var backendOverrideInstalled = false;
|
|
@@ -8377,6 +8544,7 @@ function desktopResourceKey(target) {
|
|
|
8377
8544
|
}
|
|
8378
8545
|
function persistOperation(state) {
|
|
8379
8546
|
if (!state.currentTarget || !state.currentCapture || !state.currentLook || !state.currentOutline) return;
|
|
8547
|
+
if (expiredStateReasons.has(state.currentCapture.stateId) || state.helperGeneration !== helperGeneration) return;
|
|
8380
8548
|
const resourceKey = state.resourceKey ?? desktopResourceKey(state.currentTarget);
|
|
8381
8549
|
const epoch = state.epoch ?? resourceScheduler.epoch(resourceKey);
|
|
8382
8550
|
savedStates.saveDesktop(state, resourceKey, epoch);
|
|
@@ -8400,10 +8568,7 @@ async function releaseComputerUseSession() {
|
|
|
8400
8568
|
});
|
|
8401
8569
|
await attempt("drain scheduler", () => drain);
|
|
8402
8570
|
await attempt("release owned browser", () => releaseOwnedBrowserState(runtimeState));
|
|
8403
|
-
|
|
8404
|
-
if (runtimeState.previousCdpPort === void 0) delete process.env.PIE_COMPUTER_USE_CDP_PORT;
|
|
8405
|
-
else process.env.PIE_COMPUTER_USE_CDP_PORT = runtimeState.previousCdpPort;
|
|
8406
|
-
}
|
|
8571
|
+
setManagedCdpPort(void 0);
|
|
8407
8572
|
runtimeState.previousCdpPort = void 0;
|
|
8408
8573
|
if (runtimeState.managedBrowser === void 0) {
|
|
8409
8574
|
runtimeState.managedBrowserCdpPort = void 0;
|
|
@@ -8427,7 +8592,7 @@ function currentRuntimeMode() {
|
|
|
8427
8592
|
}
|
|
8428
8593
|
function currentDeliveryPolicy() {
|
|
8429
8594
|
if (isHeadlessMode()) return "background";
|
|
8430
|
-
const value = (
|
|
8595
|
+
const value = (getComputerUseEnvironmentValue("PIE_COMPUTER_USE_DELIVERY_POLICY") ?? getComputerUseEnvironmentValue("PIE_COMPUTER_USE_EVENT_DELIVERY") ?? "default").toLowerCase();
|
|
8431
8596
|
return value === "background" || value === "pid" ? "background" : value === "foreground" || value === "hid" ? "foreground" : value === "ax_only" || value === "ax-only" ? "ax_only" : "default";
|
|
8432
8597
|
}
|
|
8433
8598
|
function nativeInputDelivery(policy = currentDeliveryPolicy()) {
|
|
@@ -9358,7 +9523,7 @@ async function refreshBrowserSnapshot(contextId, tool, base) {
|
|
|
9358
9523
|
const browser = await cdpSnapshotForContext(contextId);
|
|
9359
9524
|
if (!browser) throw new Error(`Browser root '${contextId}' is no longer available. Call find_roots and observe_ui again.`);
|
|
9360
9525
|
const state = operationState();
|
|
9361
|
-
const resourceKey = state.resourceKey ?? `cdp:${browser.
|
|
9526
|
+
const resourceKey = state.resourceKey ?? `cdp:${browser.contextId.slice(BROWSER_CONTEXT_PREFIX.length)}`;
|
|
9362
9527
|
return browserObservationResult(browser, resourceKey, state.epoch ?? resourceScheduler.epoch(resourceKey), tool, base);
|
|
9363
9528
|
}
|
|
9364
9529
|
function sliceText(value, offsetValue, _limitValue) {
|
|
@@ -9997,7 +10162,7 @@ async function performAct(params, signal) {
|
|
|
9997
10162
|
}
|
|
9998
10163
|
function managedBrowserExecutableCandidates(browser) {
|
|
9999
10164
|
const overrideName = browser === "helium" ? "PIE_COMPUTER_USE_HELIUM_EXECUTABLE" : "PIE_COMPUTER_USE_CHROME_EXECUTABLE";
|
|
10000
|
-
const override = trimOrUndefined(
|
|
10165
|
+
const override = trimOrUndefined(getComputerUseEnvironmentValue(overrideName));
|
|
10001
10166
|
if (override) return [path13.resolve(override)];
|
|
10002
10167
|
const platformCandidates = process.platform === "darwin" ? browser === "helium" ? [
|
|
10003
10168
|
"/Applications/Helium.app/Contents/MacOS/Helium",
|
|
@@ -10038,7 +10203,7 @@ async function managedBrowserExecutable(browser) {
|
|
|
10038
10203
|
}
|
|
10039
10204
|
}
|
|
10040
10205
|
const overrideName = browser === "helium" ? "PIE_COMPUTER_USE_HELIUM_EXECUTABLE" : "PIE_COMPUTER_USE_CHROME_EXECUTABLE";
|
|
10041
|
-
if (trimOrUndefined(
|
|
10206
|
+
if (trimOrUndefined(getComputerUseEnvironmentValue(overrideName))) {
|
|
10042
10207
|
throw new Error(`${browser} executable from ${overrideName} was not found or is not executable: ${candidates[0]}.`);
|
|
10043
10208
|
}
|
|
10044
10209
|
throw new Error(`${browser} executable was not found. Set ${overrideName} to its absolute path.`);
|
|
@@ -10068,6 +10233,7 @@ async function waitForCdpPort(port, signal) {
|
|
|
10068
10233
|
throw new Error(`Managed browser did not expose CDP on port ${port} within ${MANAGED_BROWSER_READY_TIMEOUT_MS}ms.`);
|
|
10069
10234
|
}
|
|
10070
10235
|
async function performLaunchBrowser(params, signal) {
|
|
10236
|
+
assertNativeBackendAllowed();
|
|
10071
10237
|
const browser = getComputerUseConfig().managed_browser;
|
|
10072
10238
|
const executable = await managedBrowserExecutable(browser);
|
|
10073
10239
|
const port = await freeTcpPort();
|
|
@@ -10084,9 +10250,6 @@ async function performLaunchBrowser(params, signal) {
|
|
|
10084
10250
|
"--no-default-browser-check",
|
|
10085
10251
|
url
|
|
10086
10252
|
];
|
|
10087
|
-
if (runtimeState.previousCdpPort === void 0 && runtimeState.managedBrowserCdpPort === void 0) {
|
|
10088
|
-
runtimeState.previousCdpPort = process.env.PIE_COMPUTER_USE_CDP_PORT;
|
|
10089
|
-
}
|
|
10090
10253
|
const managedBrowser = spawn4(executable, args, { stdio: "ignore", detached: true });
|
|
10091
10254
|
managedBrowser.unref();
|
|
10092
10255
|
const stalePid = runtimeState.managedBrowserPid;
|
|
@@ -10101,22 +10264,21 @@ async function performLaunchBrowser(params, signal) {
|
|
|
10101
10264
|
runtimeState.managedBrowserPid = managedBrowser.pid;
|
|
10102
10265
|
runtimeState.managedBrowserProfileDir = profileDir;
|
|
10103
10266
|
persistRuntimeBridgeState();
|
|
10104
|
-
|
|
10267
|
+
setManagedCdpPort(String(port));
|
|
10105
10268
|
try {
|
|
10106
10269
|
await waitForCdpPort(port, signal);
|
|
10107
10270
|
} catch (error) {
|
|
10108
10271
|
if (runtimeState.managedBrowser === managedBrowser) {
|
|
10109
10272
|
await releaseOwnedBrowserState(runtimeState);
|
|
10110
|
-
|
|
10111
|
-
else process.env.PIE_COMPUTER_USE_CDP_PORT = runtimeState.previousCdpPort;
|
|
10273
|
+
setManagedCdpPort(void 0);
|
|
10112
10274
|
runtimeState.managedBrowserCdpPort = void 0;
|
|
10113
10275
|
runtimeState.previousCdpPort = void 0;
|
|
10114
10276
|
}
|
|
10115
10277
|
throw error;
|
|
10116
10278
|
}
|
|
10117
|
-
const page = (await listCdpPageContexts())[0];
|
|
10279
|
+
const page = (await listCdpPageContexts(String(port)))[0];
|
|
10118
10280
|
if (!page) throw new Error("Managed browser launched without a CDP page context.");
|
|
10119
|
-
const resourceKey = `cdp:${page.
|
|
10281
|
+
const resourceKey = `cdp:${page.contextId.slice(BROWSER_CONTEXT_PREFIX.length)}`;
|
|
10120
10282
|
const scheduled = await resourceScheduler.read(resourceKey, async () => await cdpSnapshotForContext(page.contextId));
|
|
10121
10283
|
if (!scheduled.value) throw new Error("Managed browser page could not be observed after launch.");
|
|
10122
10284
|
return browserObservationResult(scheduled.value, resourceKey, scheduled.epoch, "launch_browser");
|
|
@@ -10177,6 +10339,9 @@ async function executeTool(tool, ctx, params, signal, run, runtime) {
|
|
|
10177
10339
|
const outputRef = tool === "read_text" && trimOrUndefined(params?.ref)?.startsWith("@o") === true;
|
|
10178
10340
|
const requestedStateId = outputRef ? void 0 : trimOrUndefined(params?.stateId);
|
|
10179
10341
|
const stateRecord = requestedStateId ? savedStates.get(requestedStateId) : void 0;
|
|
10342
|
+
if (requestedStateId && expiredStateReasons.has(requestedStateId)) {
|
|
10343
|
+
throw new Error(`State '${requestedStateId}' expired because ${expiredStateReasons.get(requestedStateId)}. Observe the root again.`);
|
|
10344
|
+
}
|
|
10180
10345
|
if (requestedStateId && !stateRecord) {
|
|
10181
10346
|
const reason = expiredStateReasons.get(requestedStateId);
|
|
10182
10347
|
if (reason) {
|
|
@@ -10196,6 +10361,7 @@ async function executeTool(tool, ctx, params, signal, run, runtime) {
|
|
|
10196
10361
|
operation.onDispatch = runtime?.onDispatch;
|
|
10197
10362
|
if (requestedStateId && stateRecord) assertStateAccess(requestedStateId, stateRecord, operation);
|
|
10198
10363
|
return await withComputerUseConfig(ctx.cwd, () => savedStates.operations.run(operation, async () => {
|
|
10364
|
+
if (requestedStateId) operation.artifactIds = engineArtifacts?.pinForState(requestedStateId) ?? [];
|
|
10199
10365
|
try {
|
|
10200
10366
|
const browserOnly = operation.contextId || ["launch_browser", "navigate_browser", "evaluate_browser"].includes(tool) || tool === "find_roots" && params.kind === "browser_page" || tool === "observe_ui" && runtimeState.browserContextByRoot.has(params.root ?? "");
|
|
10201
10367
|
await resourceScheduler.read("session-lifecycle", async () => {
|
|
@@ -10212,7 +10378,7 @@ async function executeTool(tool, ctx, params, signal, run, runtime) {
|
|
|
10212
10378
|
} finally {
|
|
10213
10379
|
for (const artifactId of operation.artifactIds ?? []) engineArtifacts?.unpin(artifactId);
|
|
10214
10380
|
}
|
|
10215
|
-
}));
|
|
10381
|
+
}), runtime?.environment);
|
|
10216
10382
|
}
|
|
10217
10383
|
var BROKER_PERFORMERS = {
|
|
10218
10384
|
find_roots: performListWindows,
|
|
@@ -10317,7 +10483,7 @@ async function probeBroker(endpoint, timeoutMs = 800) {
|
|
|
10317
10483
|
};
|
|
10318
10484
|
socket.setTimeout(timeoutMs, () => finish({ error: "timeout" }));
|
|
10319
10485
|
socket.on("connect", () => {
|
|
10320
|
-
socket.write(encodeFrame({ type: "hello", protocolVersion: BROKER_PROTOCOL_VERSION, clientVersion: "probe" }));
|
|
10486
|
+
socket.write(encodeFrame({ type: "hello", protocolVersion: BROKER_PROTOCOL_VERSION, clientVersion: "probe", buildIdentity: BROKER_BUILD.identity }));
|
|
10321
10487
|
});
|
|
10322
10488
|
socket.on("data", (chunk) => {
|
|
10323
10489
|
try {
|
|
@@ -10364,8 +10530,7 @@ async function startBroker(options = {}) {
|
|
|
10364
10530
|
const helperGeneration2 = randomUUID8();
|
|
10365
10531
|
let liveHelperGeneration = helperGeneration2;
|
|
10366
10532
|
const startedAt = Date.now();
|
|
10367
|
-
|
|
10368
|
-
const prior = loadBrokerManifest();
|
|
10533
|
+
let legacyCache;
|
|
10369
10534
|
const artifacts = new ArtifactStore({
|
|
10370
10535
|
root: artifactsRoot(),
|
|
10371
10536
|
generation,
|
|
@@ -10374,18 +10539,6 @@ async function startBroker(options = {}) {
|
|
|
10374
10539
|
expireStateForArtifactEviction(stateId2);
|
|
10375
10540
|
}
|
|
10376
10541
|
});
|
|
10377
|
-
try {
|
|
10378
|
-
artifacts.cleanupOtherGenerations(generation);
|
|
10379
|
-
} catch {
|
|
10380
|
-
}
|
|
10381
|
-
configureEngineRuntime({
|
|
10382
|
-
generation,
|
|
10383
|
-
helperGeneration: helperGeneration2,
|
|
10384
|
-
artifacts,
|
|
10385
|
-
expiredStateIds: prior?.stateIds ?? [],
|
|
10386
|
-
previousGeneration: prior?.generation
|
|
10387
|
-
});
|
|
10388
|
-
saveBrokerManifest({ generation, helperGeneration: helperGeneration2, stateIds: [], updatedAt: Date.now() });
|
|
10389
10542
|
const entries = /* @__PURE__ */ new Map();
|
|
10390
10543
|
const acceptedIds = /* @__PURE__ */ new Set();
|
|
10391
10544
|
const resultCacheLimit = options.resultCacheLimit ?? BROKER_RESULT_CACHE_MAX_ENTRIES;
|
|
@@ -10506,6 +10659,7 @@ async function startBroker(options = {}) {
|
|
|
10506
10659
|
helperGeneration: currentHelperGenerationSafe(),
|
|
10507
10660
|
requestId: request.requestId,
|
|
10508
10661
|
cwd: request.cwd,
|
|
10662
|
+
environment: request.environment,
|
|
10509
10663
|
signal: entry.controller.signal,
|
|
10510
10664
|
onDispatch: () => {
|
|
10511
10665
|
entry.dispatched = true;
|
|
@@ -10529,7 +10683,7 @@ async function startBroker(options = {}) {
|
|
|
10529
10683
|
return;
|
|
10530
10684
|
}
|
|
10531
10685
|
const key = request.requestId;
|
|
10532
|
-
const fingerprint = requestFingerprint(request.command, request.params, request.cwd);
|
|
10686
|
+
const fingerprint = requestFingerprint(request.command, request.params, request.cwd, request.environment);
|
|
10533
10687
|
const existing = entries.get(key);
|
|
10534
10688
|
if (existing) {
|
|
10535
10689
|
if (existing.ownerId !== request.ownerId || existing.command !== request.command || existing.fingerprint !== fingerprint) {
|
|
@@ -10741,7 +10895,8 @@ async function startBroker(options = {}) {
|
|
|
10741
10895
|
pid: process.pid,
|
|
10742
10896
|
startedAt,
|
|
10743
10897
|
platform: process.platform,
|
|
10744
|
-
transport: endpoint.kind
|
|
10898
|
+
transport: endpoint.kind,
|
|
10899
|
+
backend: { fakeInstalled: options.fakeBackendInstalled === true, requireFake: requireFakeBackend() }
|
|
10745
10900
|
});
|
|
10746
10901
|
} catch (error) {
|
|
10747
10902
|
helloRejected = true;
|
|
@@ -10829,6 +10984,23 @@ async function startBroker(options = {}) {
|
|
|
10829
10984
|
throw new Error(`Computer-use endpoint ${endpoint.path} is in use and its owner cannot be proven stale (${probe.error ?? "no response"}). Refusing to steal it.`);
|
|
10830
10985
|
}
|
|
10831
10986
|
}
|
|
10987
|
+
legacyCache = cleanupLegacyBrokerCache();
|
|
10988
|
+
const prior = loadBrokerManifest();
|
|
10989
|
+
try {
|
|
10990
|
+
artifacts.cleanupOtherGenerations(generation);
|
|
10991
|
+
} catch {
|
|
10992
|
+
}
|
|
10993
|
+
configureEngineRuntime({
|
|
10994
|
+
generation,
|
|
10995
|
+
helperGeneration: helperGeneration2,
|
|
10996
|
+
artifacts,
|
|
10997
|
+
expiredStateIds: prior?.stateIds ?? [],
|
|
10998
|
+
previousGeneration: prior?.generation
|
|
10999
|
+
});
|
|
11000
|
+
saveBrokerManifest({ generation, helperGeneration: helperGeneration2, stateIds: [], updatedAt: Date.now() });
|
|
11001
|
+
} catch (error) {
|
|
11002
|
+
if (server.listening) server.close();
|
|
11003
|
+
throw error;
|
|
10832
11004
|
} finally {
|
|
10833
11005
|
bootstrapLock();
|
|
10834
11006
|
}
|
|
@@ -10881,13 +11053,6 @@ async function startBroker(options = {}) {
|
|
|
10881
11053
|
clearDrainMarker();
|
|
10882
11054
|
} catch {
|
|
10883
11055
|
}
|
|
10884
|
-
if (endpoint.kind === "unix-socket") {
|
|
10885
|
-
try {
|
|
10886
|
-
const stats = lstatSync4(endpoint.path);
|
|
10887
|
-
if (stats.isSocket()) unlinkSync4(endpoint.path);
|
|
10888
|
-
} catch {
|
|
10889
|
-
}
|
|
10890
|
-
}
|
|
10891
11056
|
options.onShutdown?.();
|
|
10892
11057
|
void reason;
|
|
10893
11058
|
};
|
|
@@ -10913,7 +11078,7 @@ async function startBroker(options = {}) {
|
|
|
10913
11078
|
uncertain,
|
|
10914
11079
|
requests: entries.size,
|
|
10915
11080
|
ownerCount: owners.size,
|
|
10916
|
-
ownerFingerprints: [...owners].map((owner) =>
|
|
11081
|
+
ownerFingerprints: [...owners].map((owner) => createHash4("sha256").update(owner).digest("hex").slice(0, 12)),
|
|
10917
11082
|
artifacts: artifacts.stats(),
|
|
10918
11083
|
legacyCache,
|
|
10919
11084
|
idleExitMs
|
|
@@ -10934,19 +11099,8 @@ async function startBroker(options = {}) {
|
|
|
10934
11099
|
return statusHandle;
|
|
10935
11100
|
}
|
|
10936
11101
|
|
|
10937
|
-
// vendor/computer-use-axi/src/test-backend-guard.ts
|
|
10938
|
-
function resolveTestOnlyBackend(env = process.env) {
|
|
10939
|
-
if (env.PIE_COMPUTER_USE_FAKE_BACKEND !== "1") return { enabled: false };
|
|
10940
|
-
if (env.PIE_COMPUTER_USE_ENABLE_TEST_COMMANDS !== "1") {
|
|
10941
|
-
return {
|
|
10942
|
-
enabled: false,
|
|
10943
|
-
warning: "PIE_COMPUTER_USE_FAKE_BACKEND is test-only and was ignored: it requires PIE_COMPUTER_USE_ENABLE_TEST_COMMANDS=1 as well."
|
|
10944
|
-
};
|
|
10945
|
-
}
|
|
10946
|
-
return { enabled: true };
|
|
10947
|
-
}
|
|
10948
|
-
|
|
10949
11102
|
// vendor/computer-use-axi/src/broker-main.ts
|
|
11103
|
+
init_test_backend_guard();
|
|
10950
11104
|
async function loadTestOnlyBackend() {
|
|
10951
11105
|
const decision = resolveTestOnlyBackend();
|
|
10952
11106
|
if (decision.warning) process.stderr.write(`computer-use-axi broker: ${decision.warning}
|
|
@@ -10959,6 +11113,7 @@ async function loadTestOnlyBackend() {
|
|
|
10959
11113
|
setPlatformBackend(fake);
|
|
10960
11114
|
return fake;
|
|
10961
11115
|
} catch (error) {
|
|
11116
|
+
if (requireFakeBackend()) throw new Error("Required fake backend failed to load; refusing native fallback.", { cause: error });
|
|
10962
11117
|
process.stderr.write(
|
|
10963
11118
|
`computer-use-axi broker: the test-only fake backend is not available in this build (${error instanceof Error ? error.message : String(error)}); continuing with the real platform backend.
|
|
10964
11119
|
`
|
|
@@ -10971,6 +11126,7 @@ async function main() {
|
|
|
10971
11126
|
const testCommands = process.env.PIE_COMPUTER_USE_ENABLE_TEST_COMMANDS === "1";
|
|
10972
11127
|
const handle = await startBroker({
|
|
10973
11128
|
testCommands,
|
|
11129
|
+
fakeBackendInstalled: Boolean(fake),
|
|
10974
11130
|
// Fail-closed capacity contract hooks (tests only; both require the
|
|
10975
11131
|
// explicit test-command switch and are ignored in every other build).
|
|
10976
11132
|
resultCacheLimit: testCommands && Number.isFinite(Number(process.env.PIE_COMPUTER_USE_TEST_RESULT_CACHE_LIMIT)) ? Math.trunc(Number(process.env.PIE_COMPUTER_USE_TEST_RESULT_CACHE_LIMIT)) : void 0,
|