@cydm/pie 2.7.4 → 2.7.6
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 +357 -206
- package/dist/builtin/skills/computer-use-axi/computer-use-axi-runtime.js +92 -15
- package/dist/chunks/{chunk-P2B62ZPU.js → chunk-5YWEUFLM.js} +57 -38
- package/dist/chunks/{chunk-VGVCDW7P.js → chunk-GAUIKMBA.js} +2 -2
- package/dist/chunks/{chunk-FIE3SSLW.js → chunk-YWWLRZSG.js} +8358 -7630
- package/dist/chunks/{chunk-Z4EIBY2E.js → chunk-ZF5FHTES.js} +750 -92
- package/dist/chunks/{src-EVCOTFBU.js → src-6WK5KYWQ.js} +2 -2
- package/dist/chunks/{test-stream-24BCZPP5.js → test-stream-7EH7BGY6.js} +1 -1
- package/dist/cli.js +177 -531
- 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,9 +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 =
|
|
5168
|
+
const root = path4.join(this.options.root, safeComponent(generation, "generation"));
|
|
4957
5169
|
const ownerKey = `owner-${createHash2("sha256").update(normalizeComputerUseOwner(owner)).digest("hex")}`;
|
|
4958
|
-
const ownerDir =
|
|
5170
|
+
const ownerDir = path4.join(root, ownerKey);
|
|
4959
5171
|
ensurePrivateDirectory(this.options.root);
|
|
4960
5172
|
ensurePrivateDirectory(root);
|
|
4961
5173
|
ensurePrivateDirectory(ownerDir);
|
|
@@ -4965,7 +5177,7 @@ var ArtifactStore = class {
|
|
|
4965
5177
|
const generation = input.generation ?? this.options.generation;
|
|
4966
5178
|
const directory = this.directoryFor(input.owner, generation);
|
|
4967
5179
|
const artifactId = randomUUID2();
|
|
4968
|
-
const absolutePath =
|
|
5180
|
+
const absolutePath = path4.join(directory, `${artifactId}.${extensionFor(input.mimeType)}`);
|
|
4969
5181
|
const fd = openSync(absolutePath, "wx", 384);
|
|
4970
5182
|
try {
|
|
4971
5183
|
let offset = 0;
|
|
@@ -4994,6 +5206,16 @@ var ArtifactStore = class {
|
|
|
4994
5206
|
this.sweep();
|
|
4995
5207
|
return record;
|
|
4996
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
|
+
}
|
|
4997
5219
|
pin(artifactId) {
|
|
4998
5220
|
this.pins.set(artifactId, (this.pins.get(artifactId) ?? 0) + 1);
|
|
4999
5221
|
}
|
|
@@ -5045,13 +5267,13 @@ var ArtifactStore = class {
|
|
|
5045
5267
|
/** Remove files for a generation that no longer owns the broker. */
|
|
5046
5268
|
cleanupGeneration(generation) {
|
|
5047
5269
|
if (!SAFE_COMPONENT.test(generation)) return 0;
|
|
5048
|
-
const directory =
|
|
5049
|
-
if (!
|
|
5270
|
+
const directory = path4.join(this.options.root, generation);
|
|
5271
|
+
if (!existsSync3(directory)) return 0;
|
|
5050
5272
|
const stats = lstatSync3(directory);
|
|
5051
5273
|
if (stats.isSymbolicLink() || !stats.isDirectory()) return 0;
|
|
5052
5274
|
let removed = 0;
|
|
5053
5275
|
for (const name of readdirSync2(directory)) {
|
|
5054
|
-
const ownerDir =
|
|
5276
|
+
const ownerDir = path4.join(directory, name);
|
|
5055
5277
|
let ownerStats;
|
|
5056
5278
|
try {
|
|
5057
5279
|
ownerStats = lstatSync3(ownerDir);
|
|
@@ -5060,7 +5282,7 @@ var ArtifactStore = class {
|
|
|
5060
5282
|
}
|
|
5061
5283
|
if (ownerStats.isSymbolicLink() || !ownerStats.isDirectory()) continue;
|
|
5062
5284
|
for (const file of readdirSync2(ownerDir)) {
|
|
5063
|
-
const target =
|
|
5285
|
+
const target = path4.join(ownerDir, file);
|
|
5064
5286
|
let fileStats;
|
|
5065
5287
|
try {
|
|
5066
5288
|
fileStats = lstatSync3(target);
|
|
@@ -5072,12 +5294,12 @@ var ArtifactStore = class {
|
|
|
5072
5294
|
removed += 1;
|
|
5073
5295
|
}
|
|
5074
5296
|
try {
|
|
5075
|
-
|
|
5297
|
+
rmdirSync2(ownerDir);
|
|
5076
5298
|
} catch {
|
|
5077
5299
|
}
|
|
5078
5300
|
}
|
|
5079
5301
|
try {
|
|
5080
|
-
|
|
5302
|
+
rmdirSync2(directory);
|
|
5081
5303
|
} catch {
|
|
5082
5304
|
}
|
|
5083
5305
|
return removed;
|
|
@@ -5101,7 +5323,7 @@ var ArtifactStore = class {
|
|
|
5101
5323
|
for (const name of names) {
|
|
5102
5324
|
if (scanned >= maxGenerations) break;
|
|
5103
5325
|
if (name === current || !SAFE_COMPONENT.test(name)) continue;
|
|
5104
|
-
const directory =
|
|
5326
|
+
const directory = path4.join(this.options.root, name);
|
|
5105
5327
|
let stats;
|
|
5106
5328
|
try {
|
|
5107
5329
|
stats = lstatSync3(directory);
|
|
@@ -5133,11 +5355,12 @@ var ArtifactStore = class {
|
|
|
5133
5355
|
};
|
|
5134
5356
|
function artifactsRoot(env = process.env) {
|
|
5135
5357
|
const base = env.PIE_COMPUTER_USE_ARTIFACTS_DIR?.trim();
|
|
5136
|
-
if (base) return
|
|
5137
|
-
return
|
|
5358
|
+
if (base) return path4.resolve(base);
|
|
5359
|
+
return path4.join(stateRootDir(env), "artifacts");
|
|
5138
5360
|
}
|
|
5139
5361
|
|
|
5140
5362
|
// vendor/computer-use-axi/src/bridge.ts
|
|
5363
|
+
init_test_backend_guard();
|
|
5141
5364
|
import { spawn as spawn4 } from "node:child_process";
|
|
5142
5365
|
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
5143
5366
|
import { constants as fsConstants5, mkdtempSync } from "node:fs";
|
|
@@ -5161,7 +5384,7 @@ function keys(value) {
|
|
|
5161
5384
|
if (!Array.isArray(value) || value.length === 0) throw new Error("keypress.keys must contain at least one key.");
|
|
5162
5385
|
return value.map((key) => String(key));
|
|
5163
5386
|
}
|
|
5164
|
-
function
|
|
5387
|
+
function path5(value, env) {
|
|
5165
5388
|
if (!Array.isArray(value) || value.length < 2) throw new Error("drag.path must contain at least two points.");
|
|
5166
5389
|
return value.map((point, index) => {
|
|
5167
5390
|
const x = Array.isArray(point) ? toFiniteNumber(point[0], NaN) : toFiniteNumber(point?.x, NaN);
|
|
@@ -5193,7 +5416,7 @@ function nativeTarget(action, operation, env) {
|
|
|
5193
5416
|
env.validatePoint(x, y);
|
|
5194
5417
|
return { x, y };
|
|
5195
5418
|
}
|
|
5196
|
-
if (operation === "drag" && action.path?.length) return
|
|
5419
|
+
if (operation === "drag" && action.path?.length) return path5(action.path, env)[0];
|
|
5197
5420
|
throw new Error(`${operation} requires either ref or both x and y.`);
|
|
5198
5421
|
}
|
|
5199
5422
|
function focusedTarget(env) {
|
|
@@ -5263,7 +5486,7 @@ function prepareAction(action, state, env) {
|
|
|
5263
5486
|
case "scroll":
|
|
5264
5487
|
return { action: operation, target, params: { scrollX: scrollDelta(action.scrollX), scrollY: scrollDelta(action.scrollY) }, usesCurrentFocus: false, needsForeground: false };
|
|
5265
5488
|
case "drag":
|
|
5266
|
-
return { action: operation, target, params: { path:
|
|
5489
|
+
return { action: operation, target, params: { path: path5(action.path, env) }, usesCurrentFocus: false, needsForeground: false };
|
|
5267
5490
|
case "moveMouse":
|
|
5268
5491
|
return { action: operation, target, params: {}, usesCurrentFocus: false, needsForeground: false };
|
|
5269
5492
|
}
|
|
@@ -5289,6 +5512,7 @@ function outcomeAfterObservedValues(current, actions, valueForRef) {
|
|
|
5289
5512
|
}
|
|
5290
5513
|
|
|
5291
5514
|
// vendor/computer-use-axi/src/cdp.ts
|
|
5515
|
+
init_test_backend_guard();
|
|
5292
5516
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
5293
5517
|
|
|
5294
5518
|
// ../../node_modules/ws/wrapper.mjs
|
|
@@ -5792,6 +6016,7 @@ var CdpTab = class _CdpTab {
|
|
|
5792
6016
|
loadFired;
|
|
5793
6017
|
static async connect(wsUrl, targetId, title, epoch = connectionEpoch) {
|
|
5794
6018
|
assertConnectionEpoch(epoch);
|
|
6019
|
+
assertNativeBackendAllowed();
|
|
5795
6020
|
const ws = new wrapper_default(wsUrl);
|
|
5796
6021
|
connectingSockets.add(ws);
|
|
5797
6022
|
try {
|
|
@@ -5951,6 +6176,7 @@ var CdpTab = class _CdpTab {
|
|
|
5951
6176
|
return entries;
|
|
5952
6177
|
}
|
|
5953
6178
|
send(method, params = {}) {
|
|
6179
|
+
assertNativeBackendAllowed();
|
|
5954
6180
|
const id = this.nextId++;
|
|
5955
6181
|
return new Promise((resolve2, reject) => {
|
|
5956
6182
|
const timer = setTimeout(() => {
|
|
@@ -6028,7 +6254,7 @@ var CdpTab = class _CdpTab {
|
|
|
6028
6254
|
};
|
|
6029
6255
|
var connectedTabs = /* @__PURE__ */ new Map();
|
|
6030
6256
|
var connectingTabs = /* @__PURE__ */ new Map();
|
|
6031
|
-
var lastConnectFailureAt =
|
|
6257
|
+
var lastConnectFailureAt = /* @__PURE__ */ new Map();
|
|
6032
6258
|
function disconnectCdp() {
|
|
6033
6259
|
if (disconnecting) return disconnecting;
|
|
6034
6260
|
connectionEpoch++;
|
|
@@ -6037,62 +6263,64 @@ function disconnectCdp() {
|
|
|
6037
6263
|
connectingSockets.clear();
|
|
6038
6264
|
connectedTabs.clear();
|
|
6039
6265
|
connectingTabs.clear();
|
|
6040
|
-
lastConnectFailureAt
|
|
6266
|
+
lastConnectFailureAt.clear();
|
|
6041
6267
|
disconnecting = Promise.all(tabs.map((tab) => tab.close())).then(() => void 0).finally(() => {
|
|
6042
6268
|
disconnecting = void 0;
|
|
6043
6269
|
});
|
|
6044
6270
|
return disconnecting;
|
|
6045
6271
|
}
|
|
6046
|
-
function cdpEnabled() {
|
|
6047
|
-
const rawPort = process.env.PIE_COMPUTER_USE_CDP_PORT ?? "";
|
|
6272
|
+
function cdpEnabled(rawPort = getComputerUseEnvironmentValue("PIE_COMPUTER_USE_CDP_PORT") ?? "") {
|
|
6048
6273
|
if (!/^\d+$/.test(rawPort)) return false;
|
|
6049
6274
|
const port = Number(rawPort);
|
|
6050
6275
|
return Number.isInteger(port) && port > 0 && port <= 65535 && typeof wrapper_default !== "undefined";
|
|
6051
6276
|
}
|
|
6052
6277
|
async function cdpTabForWindow(windowTitle, frame) {
|
|
6053
6278
|
const epoch = connectionEpoch;
|
|
6054
|
-
|
|
6055
|
-
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;
|
|
6056
6282
|
try {
|
|
6057
6283
|
assertConnectionEpoch(epoch);
|
|
6058
|
-
for (const tab of connectedTabs
|
|
6284
|
+
for (const [key2, tab] of connectedTabs) {
|
|
6285
|
+
if (!key2.startsWith(`${port}:`)) continue;
|
|
6059
6286
|
if (tab.isOpen && titlesMatch(tab.title, windowTitle) && await tabMatchesFrame(tab, frame)) {
|
|
6060
6287
|
assertConnectionEpoch(epoch);
|
|
6061
6288
|
if (tab.isOpen) return tab;
|
|
6062
6289
|
}
|
|
6063
6290
|
}
|
|
6064
|
-
const pages = await cdpPages(epoch);
|
|
6291
|
+
const pages = await cdpPages(epoch, port);
|
|
6065
6292
|
const match = await pickTab(pages, windowTitle, frame, epoch);
|
|
6066
6293
|
assertConnectionEpoch(epoch);
|
|
6067
6294
|
if (!match) return void 0;
|
|
6068
|
-
const
|
|
6295
|
+
const key = `${port}:${match.id}`;
|
|
6296
|
+
const existing = connectedTabs.get(key);
|
|
6069
6297
|
if (existing?.isOpen) {
|
|
6070
6298
|
existing.title = match.title;
|
|
6071
6299
|
return existing;
|
|
6072
6300
|
}
|
|
6073
|
-
let connecting = connectingTabs.get(
|
|
6301
|
+
let connecting = connectingTabs.get(key);
|
|
6074
6302
|
if (!connecting) {
|
|
6075
6303
|
connecting = CdpTab.connect(match.webSocketDebuggerUrl, match.id, match.title, epoch);
|
|
6076
|
-
connectingTabs.set(
|
|
6304
|
+
connectingTabs.set(key, connecting);
|
|
6077
6305
|
}
|
|
6078
6306
|
let connected;
|
|
6079
6307
|
try {
|
|
6080
6308
|
connected = await connecting;
|
|
6081
6309
|
} finally {
|
|
6082
|
-
if (connectingTabs.get(
|
|
6310
|
+
if (connectingTabs.get(key) === connecting) connectingTabs.delete(key);
|
|
6083
6311
|
}
|
|
6084
6312
|
assertConnectionEpoch(epoch);
|
|
6085
|
-
connectedTabs.set(
|
|
6313
|
+
connectedTabs.set(key, connected);
|
|
6086
6314
|
return connected;
|
|
6087
6315
|
} catch {
|
|
6088
|
-
if (epoch === connectionEpoch && !disconnecting) lastConnectFailureAt
|
|
6316
|
+
if (epoch === connectionEpoch && !disconnecting) lastConnectFailureAt.set(port, Date.now());
|
|
6089
6317
|
return void 0;
|
|
6090
6318
|
}
|
|
6091
6319
|
}
|
|
6092
|
-
async function listCdpPageContexts() {
|
|
6093
|
-
const pages = await cdpPages();
|
|
6320
|
+
async function listCdpPageContexts(port = getComputerUseEnvironmentValue("PIE_COMPUTER_USE_CDP_PORT")) {
|
|
6321
|
+
const pages = await cdpPages(connectionEpoch, port);
|
|
6094
6322
|
return pages.map((page) => ({
|
|
6095
|
-
contextId: cdpContextId(page.id),
|
|
6323
|
+
contextId: cdpContextId(page.id, port),
|
|
6096
6324
|
targetId: page.id,
|
|
6097
6325
|
title: page.title,
|
|
6098
6326
|
url: page.url ?? ""
|
|
@@ -6209,14 +6437,18 @@ async function withCdpContextTab(contextId, run) {
|
|
|
6209
6437
|
}
|
|
6210
6438
|
async function cdpPageForContext(contextId, epoch) {
|
|
6211
6439
|
if (!contextId.startsWith(CDP_CONTEXT_PREFIX)) return void 0;
|
|
6212
|
-
const
|
|
6213
|
-
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);
|
|
6214
6446
|
return pages.find((candidate) => candidate.id === targetId);
|
|
6215
6447
|
}
|
|
6216
|
-
async function cdpPages(epoch = connectionEpoch) {
|
|
6448
|
+
async function cdpPages(epoch = connectionEpoch, port = getComputerUseEnvironmentValue("PIE_COMPUTER_USE_CDP_PORT")) {
|
|
6217
6449
|
assertConnectionEpoch(epoch);
|
|
6218
|
-
if (!cdpEnabled()) return [];
|
|
6219
|
-
|
|
6450
|
+
if (!port || !cdpEnabled(port)) return [];
|
|
6451
|
+
assertNativeBackendAllowed();
|
|
6220
6452
|
const response = await fetch(`http://127.0.0.1:${port}/json/list`, { signal: AbortSignal.timeout(2e3) });
|
|
6221
6453
|
const targets = await response.json();
|
|
6222
6454
|
assertConnectionEpoch(epoch);
|
|
@@ -6224,8 +6456,8 @@ async function cdpPages(epoch = connectionEpoch) {
|
|
|
6224
6456
|
(target) => target.type === "page" && target.webSocketDebuggerUrl && isLocalDebuggerWebSocket(target.webSocketDebuggerUrl, port)
|
|
6225
6457
|
);
|
|
6226
6458
|
}
|
|
6227
|
-
function cdpContextId(targetId) {
|
|
6228
|
-
return `${CDP_CONTEXT_PREFIX}${targetId}`;
|
|
6459
|
+
function cdpContextId(targetId, port) {
|
|
6460
|
+
return `${CDP_CONTEXT_PREFIX}${port}:${targetId}`;
|
|
6229
6461
|
}
|
|
6230
6462
|
function axString(raw) {
|
|
6231
6463
|
const value = raw?.value ?? raw;
|
|
@@ -6372,98 +6604,6 @@ function titlesMatch(tabTitle, windowTitle) {
|
|
|
6372
6604
|
return tab === win || win.startsWith(tab) || tab.startsWith(win);
|
|
6373
6605
|
}
|
|
6374
6606
|
|
|
6375
|
-
// vendor/computer-use-axi/src/config.ts
|
|
6376
|
-
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
|
|
6377
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6378
|
-
import path5 from "node:path";
|
|
6379
|
-
|
|
6380
|
-
// vendor/computer-use-axi/host.ts
|
|
6381
|
-
function getAgentDir() {
|
|
6382
|
-
return getConfigDir();
|
|
6383
|
-
}
|
|
6384
|
-
|
|
6385
|
-
// vendor/computer-use-axi/src/config.ts
|
|
6386
|
-
var DEFAULT_CONFIG = {
|
|
6387
|
-
browser_use: true,
|
|
6388
|
-
headless: false,
|
|
6389
|
-
cursor_overlay: true,
|
|
6390
|
-
managed_browser: "chrome"
|
|
6391
|
-
};
|
|
6392
|
-
var operationConfig = new AsyncLocalStorage();
|
|
6393
|
-
var defaultLoaded = Object.freeze({ config: Object.freeze({ ...DEFAULT_CONFIG }), sources: [], env: {} });
|
|
6394
|
-
function withComputerUseConfig(cwd, run) {
|
|
6395
|
-
return operationConfig.run(loadComputerUseConfig(cwd), run);
|
|
6396
|
-
}
|
|
6397
|
-
function parseBoolean(value) {
|
|
6398
|
-
if (typeof value === "boolean") return value;
|
|
6399
|
-
if (typeof value === "number") return value === 1 ? true : value === 0 ? false : void 0;
|
|
6400
|
-
if (typeof value !== "string") return void 0;
|
|
6401
|
-
const normalized = value.trim().toLowerCase();
|
|
6402
|
-
if (["1", "true", "yes", "on", "enabled"].includes(normalized)) return true;
|
|
6403
|
-
if (["0", "false", "no", "off", "disabled"].includes(normalized)) return false;
|
|
6404
|
-
return void 0;
|
|
6405
|
-
}
|
|
6406
|
-
function normalizePartial(raw) {
|
|
6407
|
-
if (!raw || typeof raw !== "object") return {};
|
|
6408
|
-
const source = raw.computer_use && typeof raw.computer_use === "object" ? raw.computer_use : raw;
|
|
6409
|
-
const out = {};
|
|
6410
|
-
const browserUse = parseBoolean(source.browser_use);
|
|
6411
|
-
const headless = parseBoolean(source.headless);
|
|
6412
|
-
const cursorOverlay = parseBoolean(source.cursor_overlay);
|
|
6413
|
-
if (browserUse !== void 0) out.browser_use = browserUse;
|
|
6414
|
-
if (headless !== void 0) out.headless = headless;
|
|
6415
|
-
if (cursorOverlay !== void 0) out.cursor_overlay = cursorOverlay;
|
|
6416
|
-
const managedBrowser = source.managed_browser;
|
|
6417
|
-
if (managedBrowser === "helium" || managedBrowser === "chrome") out.managed_browser = managedBrowser;
|
|
6418
|
-
return out;
|
|
6419
|
-
}
|
|
6420
|
-
function readConfigFile(filePath) {
|
|
6421
|
-
if (!existsSync3(filePath)) return { path: filePath, exists: false };
|
|
6422
|
-
try {
|
|
6423
|
-
const parsed = JSON.parse(readFileSync3(filePath, "utf-8"));
|
|
6424
|
-
return { path: filePath, exists: true, values: normalizePartial(parsed) };
|
|
6425
|
-
} catch (error) {
|
|
6426
|
-
return { path: filePath, exists: true, error: error instanceof Error ? error.message : String(error) };
|
|
6427
|
-
}
|
|
6428
|
-
}
|
|
6429
|
-
function readEnv() {
|
|
6430
|
-
const out = {};
|
|
6431
|
-
const browserUse = parseBoolean(process.env.PIE_COMPUTER_USE_BROWSER_USE);
|
|
6432
|
-
const headless = parseBoolean(process.env.PIE_COMPUTER_USE_HEADLESS);
|
|
6433
|
-
const cursorOverlay = parseBoolean(process.env.PIE_COMPUTER_USE_CURSOR_OVERLAY);
|
|
6434
|
-
if (browserUse !== void 0) out.browser_use = browserUse;
|
|
6435
|
-
if (headless !== void 0) out.headless = headless;
|
|
6436
|
-
if (cursorOverlay !== void 0) out.cursor_overlay = cursorOverlay;
|
|
6437
|
-
const managedBrowser = process.env.PIE_COMPUTER_USE_MANAGED_BROWSER;
|
|
6438
|
-
if (managedBrowser === "helium" || managedBrowser === "chrome") out.managed_browser = managedBrowser;
|
|
6439
|
-
return out;
|
|
6440
|
-
}
|
|
6441
|
-
function loadComputerUseConfig(cwd) {
|
|
6442
|
-
const sources = [
|
|
6443
|
-
readConfigFile(path5.join(getAgentDir(), "extensions", "computer-use.json")),
|
|
6444
|
-
readConfigFile(path5.join(cwd, ".pie", "computer-use.json"))
|
|
6445
|
-
];
|
|
6446
|
-
const env = readEnv();
|
|
6447
|
-
const config = { ...DEFAULT_CONFIG };
|
|
6448
|
-
for (const source of sources) {
|
|
6449
|
-
if (source.values) Object.assign(config, source.values);
|
|
6450
|
-
}
|
|
6451
|
-
Object.assign(config, env);
|
|
6452
|
-
return Object.freeze({ config: Object.freeze(config), sources, env });
|
|
6453
|
-
}
|
|
6454
|
-
function getComputerUseConfig() {
|
|
6455
|
-
return getLoadedComputerUseConfig().config;
|
|
6456
|
-
}
|
|
6457
|
-
function getLoadedComputerUseConfig() {
|
|
6458
|
-
return operationConfig.getStore() ?? defaultLoaded;
|
|
6459
|
-
}
|
|
6460
|
-
function isHeadlessMode() {
|
|
6461
|
-
return getComputerUseConfig().headless;
|
|
6462
|
-
}
|
|
6463
|
-
function isBrowserUseEnabled() {
|
|
6464
|
-
return getComputerUseConfig().browser_use;
|
|
6465
|
-
}
|
|
6466
|
-
|
|
6467
6607
|
// vendor/computer-use-axi/src/note.ts
|
|
6468
6608
|
function normalizedLabel(value) {
|
|
6469
6609
|
return value.toLowerCase().replace(/\s+/g, " ").trim();
|
|
@@ -6617,8 +6757,9 @@ function renderNote(note) {
|
|
|
6617
6757
|
}
|
|
6618
6758
|
|
|
6619
6759
|
// vendor/computer-use-axi/src/output.ts
|
|
6620
|
-
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";
|
|
6621
6761
|
import path6 from "node:path";
|
|
6762
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
6622
6763
|
var MODEL_TEXT_MAX_BYTES = 48 * 1024;
|
|
6623
6764
|
var MODEL_TEXT_MAX_LINES = 2e3;
|
|
6624
6765
|
var OUTPUT_PAGE_BYTES = 16 * 1024;
|
|
@@ -6630,8 +6771,13 @@ var outputs = /* @__PURE__ */ new Map();
|
|
|
6630
6771
|
var nextOutputId = 1;
|
|
6631
6772
|
var outputBytes = 0;
|
|
6632
6773
|
function outputDirectoryFor(owner) {
|
|
6633
|
-
const
|
|
6634
|
-
|
|
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);
|
|
6635
6781
|
return dir;
|
|
6636
6782
|
}
|
|
6637
6783
|
function utf8Prefix(bytes, maxBytes) {
|
|
@@ -6763,6 +6909,9 @@ function clearStoredOutputs(owner) {
|
|
|
6763
6909
|
// vendor/computer-use-axi/src/bridge.ts
|
|
6764
6910
|
init_coerce();
|
|
6765
6911
|
|
|
6912
|
+
// vendor/computer-use-axi/src/platform/index.ts
|
|
6913
|
+
init_test_backend_guard();
|
|
6914
|
+
|
|
6766
6915
|
// vendor/computer-use-axi/src/platform/macos/backend.ts
|
|
6767
6916
|
init_coerce();
|
|
6768
6917
|
init_helper();
|
|
@@ -6983,6 +7132,7 @@ init_architecture();
|
|
|
6983
7132
|
init_coerce();
|
|
6984
7133
|
|
|
6985
7134
|
// vendor/computer-use-axi/src/platform/linux/helper.ts
|
|
7135
|
+
init_test_backend_guard();
|
|
6986
7136
|
init_package_root();
|
|
6987
7137
|
import { spawn as spawn2 } from "node:child_process";
|
|
6988
7138
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
@@ -7006,6 +7156,7 @@ async function isExecutable2(filePath) {
|
|
|
7006
7156
|
async function runProcess2(command, args, timeoutMs, signal, env) {
|
|
7007
7157
|
if (signal?.aborted) throw new Error("Operation aborted.");
|
|
7008
7158
|
await new Promise((resolve2, reject) => {
|
|
7159
|
+
assertNativeBackendAllowed();
|
|
7009
7160
|
const child = spawn2(command, args, { stdio: ["ignore", "pipe", "pipe"], env });
|
|
7010
7161
|
let stdout = "";
|
|
7011
7162
|
let stderr = "";
|
|
@@ -7093,6 +7244,7 @@ var LinuxHelperClient = class {
|
|
|
7093
7244
|
this.buffer = "";
|
|
7094
7245
|
}
|
|
7095
7246
|
async ensureInstalled(signal) {
|
|
7247
|
+
assertNativeBackendAllowed();
|
|
7096
7248
|
if (await isExecutable2(this.helperPath) && this.installChecked) return;
|
|
7097
7249
|
if (!this.installPromise) {
|
|
7098
7250
|
const installPromise = (async () => {
|
|
@@ -7136,6 +7288,7 @@ var LinuxHelperClient = class {
|
|
|
7136
7288
|
return await waitForShared(this.processPromise, signal);
|
|
7137
7289
|
}
|
|
7138
7290
|
async startProcess() {
|
|
7291
|
+
assertNativeBackendAllowed();
|
|
7139
7292
|
const child = spawn2(this.helperPath, [], { stdio: ["pipe", "pipe", "pipe"] });
|
|
7140
7293
|
child.stdout.setEncoding("utf8");
|
|
7141
7294
|
child.stderr.setEncoding("utf8");
|
|
@@ -7188,6 +7341,7 @@ var LinuxHelperClient = class {
|
|
|
7188
7341
|
}
|
|
7189
7342
|
}
|
|
7190
7343
|
async command(cmd, args = {}, options) {
|
|
7344
|
+
assertNativeBackendAllowed();
|
|
7191
7345
|
const child = await this.process(options?.signal);
|
|
7192
7346
|
const id = randomUUID4();
|
|
7193
7347
|
const timeoutMs = options?.timeoutMs ?? COMMAND_TIMEOUT_MS3;
|
|
@@ -7387,6 +7541,7 @@ var linuxBackend = {
|
|
|
7387
7541
|
init_coerce();
|
|
7388
7542
|
|
|
7389
7543
|
// vendor/computer-use-axi/src/platform/windows/helper.ts
|
|
7544
|
+
init_test_backend_guard();
|
|
7390
7545
|
init_package_root();
|
|
7391
7546
|
import { spawn as spawn3 } from "node:child_process";
|
|
7392
7547
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
@@ -7410,6 +7565,7 @@ async function isExecutable3(filePath) {
|
|
|
7410
7565
|
async function runProcess3(command, args, timeoutMs, signal, env) {
|
|
7411
7566
|
if (signal?.aborted) throw new Error("Operation aborted.");
|
|
7412
7567
|
await new Promise((resolve2, reject) => {
|
|
7568
|
+
assertNativeBackendAllowed();
|
|
7413
7569
|
const child = spawn3(command, args, { stdio: ["ignore", "pipe", "pipe"], env });
|
|
7414
7570
|
let stdout = "";
|
|
7415
7571
|
let stderr = "";
|
|
@@ -7470,6 +7626,7 @@ var WindowsHelperClient = class {
|
|
|
7470
7626
|
child.unref();
|
|
7471
7627
|
}
|
|
7472
7628
|
async ensureInstalled(signal) {
|
|
7629
|
+
assertNativeBackendAllowed();
|
|
7473
7630
|
if (await isExecutable3(WINDOWS_HELPER_PATH) && this.installChecked) return;
|
|
7474
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" });
|
|
7475
7632
|
this.installChecked = true;
|
|
@@ -7478,6 +7635,7 @@ var WindowsHelperClient = class {
|
|
|
7478
7635
|
async process(signal) {
|
|
7479
7636
|
await this.ensureInstalled(signal);
|
|
7480
7637
|
if (this.child && this.child.exitCode === null && !this.child.killed) return this.child;
|
|
7638
|
+
assertNativeBackendAllowed();
|
|
7481
7639
|
const child = spawn3(WINDOWS_HELPER_PATH, [], { stdio: ["pipe", "pipe", "pipe"] });
|
|
7482
7640
|
child.stdout.setEncoding("utf8");
|
|
7483
7641
|
child.stderr.setEncoding("utf8");
|
|
@@ -7523,6 +7681,7 @@ var WindowsHelperClient = class {
|
|
|
7523
7681
|
}
|
|
7524
7682
|
}
|
|
7525
7683
|
async command(cmd, args = {}, options) {
|
|
7684
|
+
assertNativeBackendAllowed();
|
|
7526
7685
|
const child = await this.process(options?.signal);
|
|
7527
7686
|
const id = randomUUID5();
|
|
7528
7687
|
const timeoutMs = options?.timeoutMs ?? COMMAND_TIMEOUT_MS4;
|
|
@@ -7746,10 +7905,17 @@ var UnsupportedPlatformBackend = class {
|
|
|
7746
7905
|
}
|
|
7747
7906
|
};
|
|
7748
7907
|
function platformBackendForRuntime(platform = process.platform) {
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
|
|
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
|
+
});
|
|
7753
7919
|
}
|
|
7754
7920
|
var currentPlatformBackend = platformBackendForRuntime();
|
|
7755
7921
|
var backendOverrideInstalled = false;
|
|
@@ -8378,6 +8544,7 @@ function desktopResourceKey(target) {
|
|
|
8378
8544
|
}
|
|
8379
8545
|
function persistOperation(state) {
|
|
8380
8546
|
if (!state.currentTarget || !state.currentCapture || !state.currentLook || !state.currentOutline) return;
|
|
8547
|
+
if (expiredStateReasons.has(state.currentCapture.stateId) || state.helperGeneration !== helperGeneration) return;
|
|
8381
8548
|
const resourceKey = state.resourceKey ?? desktopResourceKey(state.currentTarget);
|
|
8382
8549
|
const epoch = state.epoch ?? resourceScheduler.epoch(resourceKey);
|
|
8383
8550
|
savedStates.saveDesktop(state, resourceKey, epoch);
|
|
@@ -8401,10 +8568,7 @@ async function releaseComputerUseSession() {
|
|
|
8401
8568
|
});
|
|
8402
8569
|
await attempt("drain scheduler", () => drain);
|
|
8403
8570
|
await attempt("release owned browser", () => releaseOwnedBrowserState(runtimeState));
|
|
8404
|
-
|
|
8405
|
-
if (runtimeState.previousCdpPort === void 0) delete process.env.PIE_COMPUTER_USE_CDP_PORT;
|
|
8406
|
-
else process.env.PIE_COMPUTER_USE_CDP_PORT = runtimeState.previousCdpPort;
|
|
8407
|
-
}
|
|
8571
|
+
setManagedCdpPort(void 0);
|
|
8408
8572
|
runtimeState.previousCdpPort = void 0;
|
|
8409
8573
|
if (runtimeState.managedBrowser === void 0) {
|
|
8410
8574
|
runtimeState.managedBrowserCdpPort = void 0;
|
|
@@ -8428,7 +8592,7 @@ function currentRuntimeMode() {
|
|
|
8428
8592
|
}
|
|
8429
8593
|
function currentDeliveryPolicy() {
|
|
8430
8594
|
if (isHeadlessMode()) return "background";
|
|
8431
|
-
const value = (
|
|
8595
|
+
const value = (getComputerUseEnvironmentValue("PIE_COMPUTER_USE_DELIVERY_POLICY") ?? getComputerUseEnvironmentValue("PIE_COMPUTER_USE_EVENT_DELIVERY") ?? "default").toLowerCase();
|
|
8432
8596
|
return value === "background" || value === "pid" ? "background" : value === "foreground" || value === "hid" ? "foreground" : value === "ax_only" || value === "ax-only" ? "ax_only" : "default";
|
|
8433
8597
|
}
|
|
8434
8598
|
function nativeInputDelivery(policy = currentDeliveryPolicy()) {
|
|
@@ -9359,7 +9523,7 @@ async function refreshBrowserSnapshot(contextId, tool, base) {
|
|
|
9359
9523
|
const browser = await cdpSnapshotForContext(contextId);
|
|
9360
9524
|
if (!browser) throw new Error(`Browser root '${contextId}' is no longer available. Call find_roots and observe_ui again.`);
|
|
9361
9525
|
const state = operationState();
|
|
9362
|
-
const resourceKey = state.resourceKey ?? `cdp:${browser.
|
|
9526
|
+
const resourceKey = state.resourceKey ?? `cdp:${browser.contextId.slice(BROWSER_CONTEXT_PREFIX.length)}`;
|
|
9363
9527
|
return browserObservationResult(browser, resourceKey, state.epoch ?? resourceScheduler.epoch(resourceKey), tool, base);
|
|
9364
9528
|
}
|
|
9365
9529
|
function sliceText(value, offsetValue, _limitValue) {
|
|
@@ -9998,7 +10162,7 @@ async function performAct(params, signal) {
|
|
|
9998
10162
|
}
|
|
9999
10163
|
function managedBrowserExecutableCandidates(browser) {
|
|
10000
10164
|
const overrideName = browser === "helium" ? "PIE_COMPUTER_USE_HELIUM_EXECUTABLE" : "PIE_COMPUTER_USE_CHROME_EXECUTABLE";
|
|
10001
|
-
const override = trimOrUndefined(
|
|
10165
|
+
const override = trimOrUndefined(getComputerUseEnvironmentValue(overrideName));
|
|
10002
10166
|
if (override) return [path13.resolve(override)];
|
|
10003
10167
|
const platformCandidates = process.platform === "darwin" ? browser === "helium" ? [
|
|
10004
10168
|
"/Applications/Helium.app/Contents/MacOS/Helium",
|
|
@@ -10039,7 +10203,7 @@ async function managedBrowserExecutable(browser) {
|
|
|
10039
10203
|
}
|
|
10040
10204
|
}
|
|
10041
10205
|
const overrideName = browser === "helium" ? "PIE_COMPUTER_USE_HELIUM_EXECUTABLE" : "PIE_COMPUTER_USE_CHROME_EXECUTABLE";
|
|
10042
|
-
if (trimOrUndefined(
|
|
10206
|
+
if (trimOrUndefined(getComputerUseEnvironmentValue(overrideName))) {
|
|
10043
10207
|
throw new Error(`${browser} executable from ${overrideName} was not found or is not executable: ${candidates[0]}.`);
|
|
10044
10208
|
}
|
|
10045
10209
|
throw new Error(`${browser} executable was not found. Set ${overrideName} to its absolute path.`);
|
|
@@ -10069,6 +10233,7 @@ async function waitForCdpPort(port, signal) {
|
|
|
10069
10233
|
throw new Error(`Managed browser did not expose CDP on port ${port} within ${MANAGED_BROWSER_READY_TIMEOUT_MS}ms.`);
|
|
10070
10234
|
}
|
|
10071
10235
|
async function performLaunchBrowser(params, signal) {
|
|
10236
|
+
assertNativeBackendAllowed();
|
|
10072
10237
|
const browser = getComputerUseConfig().managed_browser;
|
|
10073
10238
|
const executable = await managedBrowserExecutable(browser);
|
|
10074
10239
|
const port = await freeTcpPort();
|
|
@@ -10085,9 +10250,6 @@ async function performLaunchBrowser(params, signal) {
|
|
|
10085
10250
|
"--no-default-browser-check",
|
|
10086
10251
|
url
|
|
10087
10252
|
];
|
|
10088
|
-
if (runtimeState.previousCdpPort === void 0 && runtimeState.managedBrowserCdpPort === void 0) {
|
|
10089
|
-
runtimeState.previousCdpPort = process.env.PIE_COMPUTER_USE_CDP_PORT;
|
|
10090
|
-
}
|
|
10091
10253
|
const managedBrowser = spawn4(executable, args, { stdio: "ignore", detached: true });
|
|
10092
10254
|
managedBrowser.unref();
|
|
10093
10255
|
const stalePid = runtimeState.managedBrowserPid;
|
|
@@ -10102,22 +10264,21 @@ async function performLaunchBrowser(params, signal) {
|
|
|
10102
10264
|
runtimeState.managedBrowserPid = managedBrowser.pid;
|
|
10103
10265
|
runtimeState.managedBrowserProfileDir = profileDir;
|
|
10104
10266
|
persistRuntimeBridgeState();
|
|
10105
|
-
|
|
10267
|
+
setManagedCdpPort(String(port));
|
|
10106
10268
|
try {
|
|
10107
10269
|
await waitForCdpPort(port, signal);
|
|
10108
10270
|
} catch (error) {
|
|
10109
10271
|
if (runtimeState.managedBrowser === managedBrowser) {
|
|
10110
10272
|
await releaseOwnedBrowserState(runtimeState);
|
|
10111
|
-
|
|
10112
|
-
else process.env.PIE_COMPUTER_USE_CDP_PORT = runtimeState.previousCdpPort;
|
|
10273
|
+
setManagedCdpPort(void 0);
|
|
10113
10274
|
runtimeState.managedBrowserCdpPort = void 0;
|
|
10114
10275
|
runtimeState.previousCdpPort = void 0;
|
|
10115
10276
|
}
|
|
10116
10277
|
throw error;
|
|
10117
10278
|
}
|
|
10118
|
-
const page = (await listCdpPageContexts())[0];
|
|
10279
|
+
const page = (await listCdpPageContexts(String(port)))[0];
|
|
10119
10280
|
if (!page) throw new Error("Managed browser launched without a CDP page context.");
|
|
10120
|
-
const resourceKey = `cdp:${page.
|
|
10281
|
+
const resourceKey = `cdp:${page.contextId.slice(BROWSER_CONTEXT_PREFIX.length)}`;
|
|
10121
10282
|
const scheduled = await resourceScheduler.read(resourceKey, async () => await cdpSnapshotForContext(page.contextId));
|
|
10122
10283
|
if (!scheduled.value) throw new Error("Managed browser page could not be observed after launch.");
|
|
10123
10284
|
return browserObservationResult(scheduled.value, resourceKey, scheduled.epoch, "launch_browser");
|
|
@@ -10178,6 +10339,9 @@ async function executeTool(tool, ctx, params, signal, run, runtime) {
|
|
|
10178
10339
|
const outputRef = tool === "read_text" && trimOrUndefined(params?.ref)?.startsWith("@o") === true;
|
|
10179
10340
|
const requestedStateId = outputRef ? void 0 : trimOrUndefined(params?.stateId);
|
|
10180
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
|
+
}
|
|
10181
10345
|
if (requestedStateId && !stateRecord) {
|
|
10182
10346
|
const reason = expiredStateReasons.get(requestedStateId);
|
|
10183
10347
|
if (reason) {
|
|
@@ -10197,6 +10361,7 @@ async function executeTool(tool, ctx, params, signal, run, runtime) {
|
|
|
10197
10361
|
operation.onDispatch = runtime?.onDispatch;
|
|
10198
10362
|
if (requestedStateId && stateRecord) assertStateAccess(requestedStateId, stateRecord, operation);
|
|
10199
10363
|
return await withComputerUseConfig(ctx.cwd, () => savedStates.operations.run(operation, async () => {
|
|
10364
|
+
if (requestedStateId) operation.artifactIds = engineArtifacts?.pinForState(requestedStateId) ?? [];
|
|
10200
10365
|
try {
|
|
10201
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 ?? "");
|
|
10202
10367
|
await resourceScheduler.read("session-lifecycle", async () => {
|
|
@@ -10213,7 +10378,7 @@ async function executeTool(tool, ctx, params, signal, run, runtime) {
|
|
|
10213
10378
|
} finally {
|
|
10214
10379
|
for (const artifactId of operation.artifactIds ?? []) engineArtifacts?.unpin(artifactId);
|
|
10215
10380
|
}
|
|
10216
|
-
}));
|
|
10381
|
+
}), runtime?.environment);
|
|
10217
10382
|
}
|
|
10218
10383
|
var BROKER_PERFORMERS = {
|
|
10219
10384
|
find_roots: performListWindows,
|
|
@@ -10318,7 +10483,7 @@ async function probeBroker(endpoint, timeoutMs = 800) {
|
|
|
10318
10483
|
};
|
|
10319
10484
|
socket.setTimeout(timeoutMs, () => finish({ error: "timeout" }));
|
|
10320
10485
|
socket.on("connect", () => {
|
|
10321
|
-
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 }));
|
|
10322
10487
|
});
|
|
10323
10488
|
socket.on("data", (chunk) => {
|
|
10324
10489
|
try {
|
|
@@ -10494,6 +10659,7 @@ async function startBroker(options = {}) {
|
|
|
10494
10659
|
helperGeneration: currentHelperGenerationSafe(),
|
|
10495
10660
|
requestId: request.requestId,
|
|
10496
10661
|
cwd: request.cwd,
|
|
10662
|
+
environment: request.environment,
|
|
10497
10663
|
signal: entry.controller.signal,
|
|
10498
10664
|
onDispatch: () => {
|
|
10499
10665
|
entry.dispatched = true;
|
|
@@ -10517,7 +10683,7 @@ async function startBroker(options = {}) {
|
|
|
10517
10683
|
return;
|
|
10518
10684
|
}
|
|
10519
10685
|
const key = request.requestId;
|
|
10520
|
-
const fingerprint = requestFingerprint(request.command, request.params, request.cwd);
|
|
10686
|
+
const fingerprint = requestFingerprint(request.command, request.params, request.cwd, request.environment);
|
|
10521
10687
|
const existing = entries.get(key);
|
|
10522
10688
|
if (existing) {
|
|
10523
10689
|
if (existing.ownerId !== request.ownerId || existing.command !== request.command || existing.fingerprint !== fingerprint) {
|
|
@@ -10729,7 +10895,8 @@ async function startBroker(options = {}) {
|
|
|
10729
10895
|
pid: process.pid,
|
|
10730
10896
|
startedAt,
|
|
10731
10897
|
platform: process.platform,
|
|
10732
|
-
transport: endpoint.kind
|
|
10898
|
+
transport: endpoint.kind,
|
|
10899
|
+
backend: { fakeInstalled: options.fakeBackendInstalled === true, requireFake: requireFakeBackend() }
|
|
10733
10900
|
});
|
|
10734
10901
|
} catch (error) {
|
|
10735
10902
|
helloRejected = true;
|
|
@@ -10886,13 +11053,6 @@ async function startBroker(options = {}) {
|
|
|
10886
11053
|
clearDrainMarker();
|
|
10887
11054
|
} catch {
|
|
10888
11055
|
}
|
|
10889
|
-
if (endpoint.kind === "unix-socket") {
|
|
10890
|
-
try {
|
|
10891
|
-
const stats = lstatSync4(endpoint.path);
|
|
10892
|
-
if (stats.isSocket()) unlinkSync4(endpoint.path);
|
|
10893
|
-
} catch {
|
|
10894
|
-
}
|
|
10895
|
-
}
|
|
10896
11056
|
options.onShutdown?.();
|
|
10897
11057
|
void reason;
|
|
10898
11058
|
};
|
|
@@ -10918,7 +11078,7 @@ async function startBroker(options = {}) {
|
|
|
10918
11078
|
uncertain,
|
|
10919
11079
|
requests: entries.size,
|
|
10920
11080
|
ownerCount: owners.size,
|
|
10921
|
-
ownerFingerprints: [...owners].map((owner) =>
|
|
11081
|
+
ownerFingerprints: [...owners].map((owner) => createHash4("sha256").update(owner).digest("hex").slice(0, 12)),
|
|
10922
11082
|
artifacts: artifacts.stats(),
|
|
10923
11083
|
legacyCache,
|
|
10924
11084
|
idleExitMs
|
|
@@ -10939,19 +11099,8 @@ async function startBroker(options = {}) {
|
|
|
10939
11099
|
return statusHandle;
|
|
10940
11100
|
}
|
|
10941
11101
|
|
|
10942
|
-
// vendor/computer-use-axi/src/test-backend-guard.ts
|
|
10943
|
-
function resolveTestOnlyBackend(env = process.env) {
|
|
10944
|
-
if (env.PIE_COMPUTER_USE_FAKE_BACKEND !== "1") return { enabled: false };
|
|
10945
|
-
if (env.PIE_COMPUTER_USE_ENABLE_TEST_COMMANDS !== "1") {
|
|
10946
|
-
return {
|
|
10947
|
-
enabled: false,
|
|
10948
|
-
warning: "PIE_COMPUTER_USE_FAKE_BACKEND is test-only and was ignored: it requires PIE_COMPUTER_USE_ENABLE_TEST_COMMANDS=1 as well."
|
|
10949
|
-
};
|
|
10950
|
-
}
|
|
10951
|
-
return { enabled: true };
|
|
10952
|
-
}
|
|
10953
|
-
|
|
10954
11102
|
// vendor/computer-use-axi/src/broker-main.ts
|
|
11103
|
+
init_test_backend_guard();
|
|
10955
11104
|
async function loadTestOnlyBackend() {
|
|
10956
11105
|
const decision = resolveTestOnlyBackend();
|
|
10957
11106
|
if (decision.warning) process.stderr.write(`computer-use-axi broker: ${decision.warning}
|
|
@@ -10964,6 +11113,7 @@ async function loadTestOnlyBackend() {
|
|
|
10964
11113
|
setPlatformBackend(fake);
|
|
10965
11114
|
return fake;
|
|
10966
11115
|
} catch (error) {
|
|
11116
|
+
if (requireFakeBackend()) throw new Error("Required fake backend failed to load; refusing native fallback.", { cause: error });
|
|
10967
11117
|
process.stderr.write(
|
|
10968
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.
|
|
10969
11119
|
`
|
|
@@ -10976,6 +11126,7 @@ async function main() {
|
|
|
10976
11126
|
const testCommands = process.env.PIE_COMPUTER_USE_ENABLE_TEST_COMMANDS === "1";
|
|
10977
11127
|
const handle = await startBroker({
|
|
10978
11128
|
testCommands,
|
|
11129
|
+
fakeBackendInstalled: Boolean(fake),
|
|
10979
11130
|
// Fail-closed capacity contract hooks (tests only; both require the
|
|
10980
11131
|
// explicit test-command switch and are ignored in every other build).
|
|
10981
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,
|