@cydm/pie 2.6.12 → 2.7.0
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/README.md +68 -2
- package/dist/builtin/extensions/ask-user/index.js +3 -3
- package/dist/builtin/extensions/plan-mode/index.js +130 -21
- package/dist/builtin/extensions/subagent/index.js +4 -5
- package/dist/builtin/extensions/todo/index.js +3 -3
- package/dist/builtin/skills/computer-use-axi/SKILL.md +103 -0
- package/dist/builtin/skills/computer-use-axi/computer-use-axi-cli.js +37 -0
- package/dist/builtin/{extensions/computer-use/index.js → skills/computer-use-axi/computer-use-axi-runtime.js} +754 -642
- package/dist/builtin/skills/computer-use-axi/package.json +11 -0
- package/dist/chunks/{chunk-PPEWRUMQ.js → chunk-6RBSTII7.js} +657 -594
- package/dist/chunks/{chunk-AAEBH6KX.js → chunk-IPNAFMOJ.js} +172 -230
- package/dist/chunks/{chunk-7B4IIBVS.js → chunk-R5I2QLF2.js} +1269 -4
- package/dist/chunks/{chunk-HHNOENEH.js → chunk-TWILEFLD.js} +14 -1
- package/dist/chunks/{src-OWQI5M6W.js → src-E7NCXMU5.js} +2 -2
- package/dist/chunks/{test-stream-Y7WXELAJ.js → test-stream-BWBJTFNI.js} +1 -1
- package/dist/cli.js +463 -232
- package/models.schema.json +52 -0
- package/package.json +3 -3
- package/dist/builtin/extensions/computer-use/package.json +0 -14
- package/dist/builtin/extensions/computer-use/scripts/build-native.mjs +0 -278
- package/dist/builtin/extensions/computer-use/scripts/test-native-retention.mjs +0 -204
- package/dist/chunks/chunk-5353DEEC.js +0 -130
- package/dist/chunks/webapi-MBCKO7ZV.js +0 -2481
- package/dist/code-intel-worker.cjs +0 -211227
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/linux/arm64/linux-bridge +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/linux/x64/linux-bridge +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/arm64/pie-computer-use +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/universal/pie-computer-use.app/Contents/Info.plist +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/universal/pie-computer-use.app/Contents/MacOS/pie-computer-use +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/universal/pie-computer-use.app/Contents/_CodeSignature/CodeResources +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/macos/x64/pie-computer-use +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/prebuilt/windows/windows-bridge.exe +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/scripts/helper-path.mjs +0 -0
- /package/dist/builtin/{extensions/computer-use → skills/computer-use-axi}/scripts/setup-helper.mjs +0 -0
|
@@ -1,15 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
10
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
11
|
+
}) : x)(function(x) {
|
|
12
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
13
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
14
|
+
});
|
|
15
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
16
|
+
try {
|
|
17
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
18
|
+
} catch (e) {
|
|
19
|
+
throw mod = 0, e;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var __copyProps = (to, from, except, desc) => {
|
|
23
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
24
|
+
for (let key of __getOwnPropNames(from))
|
|
25
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
26
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
27
|
+
}
|
|
28
|
+
return to;
|
|
29
|
+
};
|
|
30
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
31
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
32
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
33
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
34
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
35
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
36
|
+
mod
|
|
37
|
+
));
|
|
13
38
|
|
|
14
39
|
// ../../node_modules/ws/lib/constants.js
|
|
15
40
|
var require_constants = __commonJS({
|
|
@@ -3694,16 +3719,16 @@ var require_websocket_server = __commonJS({
|
|
|
3694
3719
|
}
|
|
3695
3720
|
});
|
|
3696
3721
|
|
|
3697
|
-
//
|
|
3722
|
+
// vendor/computer-use-axi/src/bridge.ts
|
|
3698
3723
|
import { spawn as spawn4 } from "node:child_process";
|
|
3699
|
-
import { randomUUID as
|
|
3700
|
-
import { constants as fsConstants5, mkdtempSync
|
|
3724
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
3725
|
+
import { constants as fsConstants5, mkdtempSync } from "node:fs";
|
|
3701
3726
|
import { access as access4 } from "node:fs/promises";
|
|
3702
3727
|
import net2 from "node:net";
|
|
3703
|
-
import
|
|
3704
|
-
import
|
|
3728
|
+
import os4 from "node:os";
|
|
3729
|
+
import path11 from "node:path";
|
|
3705
3730
|
|
|
3706
|
-
//
|
|
3731
|
+
// vendor/computer-use-axi/src/platform/coerce.ts
|
|
3707
3732
|
function toBoolean(value) {
|
|
3708
3733
|
return value === true || value === "true" || value === 1;
|
|
3709
3734
|
}
|
|
@@ -3719,7 +3744,7 @@ function toOptionalString(value) {
|
|
|
3719
3744
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
3720
3745
|
}
|
|
3721
3746
|
|
|
3722
|
-
//
|
|
3747
|
+
// vendor/computer-use-axi/src/actions.ts
|
|
3723
3748
|
function mouseButton(value) {
|
|
3724
3749
|
return value === "right" || value === "middle" ? value : "left";
|
|
3725
3750
|
}
|
|
@@ -3735,9 +3760,9 @@ function keys(value) {
|
|
|
3735
3760
|
}
|
|
3736
3761
|
function path(value, env) {
|
|
3737
3762
|
if (!Array.isArray(value) || value.length < 2) throw new Error("drag.path must contain at least two points.");
|
|
3738
|
-
return value.map((
|
|
3739
|
-
const x = Array.isArray(
|
|
3740
|
-
const y = Array.isArray(
|
|
3763
|
+
return value.map((point, index) => {
|
|
3764
|
+
const x = Array.isArray(point) ? toFiniteNumber(point[0], NaN) : toFiniteNumber(point?.x, NaN);
|
|
3765
|
+
const y = Array.isArray(point) ? toFiniteNumber(point[1], NaN) : toFiniteNumber(point?.y, NaN);
|
|
3741
3766
|
env.validatePoint(x, y, `Drag point ${index + 1}`);
|
|
3742
3767
|
return { x, y };
|
|
3743
3768
|
});
|
|
@@ -3747,17 +3772,17 @@ function nativeTarget(action, operation, env) {
|
|
|
3747
3772
|
const node = env.node(action.ref.trim());
|
|
3748
3773
|
const semanticClick = operation === "click" || operation === "press";
|
|
3749
3774
|
if (semanticClick && node.isTextInput) {
|
|
3750
|
-
const
|
|
3751
|
-
env.validatePoint(
|
|
3752
|
-
return
|
|
3775
|
+
const point2 = env.center(node);
|
|
3776
|
+
env.validatePoint(point2.x, point2.y);
|
|
3777
|
+
return point2;
|
|
3753
3778
|
}
|
|
3754
3779
|
const onlyIncidentalActions = node.actions.every((candidate) => candidate === "AXShowMenu" || candidate === "AXScrollToVisible");
|
|
3755
3780
|
if (node.wireRef && !node.pictureOnly && (!semanticClick || node.canPress || node.canFocus || node.canSetValue || !onlyIncidentalActions)) {
|
|
3756
3781
|
return { ref: node.wireRef };
|
|
3757
3782
|
}
|
|
3758
|
-
const
|
|
3759
|
-
env.validatePoint(
|
|
3760
|
-
return
|
|
3783
|
+
const point = env.center(node);
|
|
3784
|
+
env.validatePoint(point.x, point.y);
|
|
3785
|
+
return point;
|
|
3761
3786
|
}
|
|
3762
3787
|
const x = toFiniteNumber(action.x, NaN);
|
|
3763
3788
|
const y = toFiniteNumber(action.y, NaN);
|
|
@@ -3860,7 +3885,7 @@ function outcomeAfterObservedValues(current, actions, valueForRef) {
|
|
|
3860
3885
|
return matches ? "worked" : current;
|
|
3861
3886
|
}
|
|
3862
3887
|
|
|
3863
|
-
//
|
|
3888
|
+
// vendor/computer-use-axi/src/cdp.ts
|
|
3864
3889
|
import { randomUUID } from "node:crypto";
|
|
3865
3890
|
|
|
3866
3891
|
// ../../node_modules/ws/wrapper.mjs
|
|
@@ -3874,7 +3899,7 @@ var import_websocket = __toESM(require_websocket(), 1);
|
|
|
3874
3899
|
var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
3875
3900
|
var wrapper_default = import_websocket.default;
|
|
3876
3901
|
|
|
3877
|
-
//
|
|
3902
|
+
// vendor/computer-use-axi/src/outline.ts
|
|
3878
3903
|
var DEFAULT_BUDGET = { maxDepth: 2, maxNodes: 150 };
|
|
3879
3904
|
function isRecord(value) {
|
|
3880
3905
|
return typeof value === "object" && value !== null;
|
|
@@ -4336,7 +4361,7 @@ function graftScopedOutline(outline, targetRef, scoped) {
|
|
|
4336
4361
|
return target;
|
|
4337
4362
|
}
|
|
4338
4363
|
|
|
4339
|
-
//
|
|
4364
|
+
// vendor/computer-use-axi/src/cdp.ts
|
|
4340
4365
|
var COMMAND_TIMEOUT_MS = 5e3;
|
|
4341
4366
|
var CDP_CONTEXT_PREFIX = "browser:";
|
|
4342
4367
|
var NAVIGATE_LOAD_TIMEOUT_MS = 1e4;
|
|
@@ -4367,11 +4392,11 @@ var CdpTab = class _CdpTab {
|
|
|
4367
4392
|
const ws = new wrapper_default(wsUrl);
|
|
4368
4393
|
connectingSockets.add(ws);
|
|
4369
4394
|
try {
|
|
4370
|
-
await new Promise((
|
|
4395
|
+
await new Promise((resolve2, reject) => {
|
|
4371
4396
|
const timer = setTimeout(() => reject(new Error(`Timed out connecting to CDP target at ${wsUrl}`)), COMMAND_TIMEOUT_MS);
|
|
4372
4397
|
ws.onopen = () => {
|
|
4373
4398
|
clearTimeout(timer);
|
|
4374
|
-
|
|
4399
|
+
resolve2();
|
|
4375
4400
|
};
|
|
4376
4401
|
ws.onerror = () => {
|
|
4377
4402
|
clearTimeout(timer);
|
|
@@ -4419,14 +4444,14 @@ var CdpTab = class _CdpTab {
|
|
|
4419
4444
|
this.loadFired = void 0;
|
|
4420
4445
|
this.rejectAllPending(new Error("CDP connection closed."));
|
|
4421
4446
|
if (this.ws.readyState === wrapper_default.CLOSED) return;
|
|
4422
|
-
await new Promise((
|
|
4447
|
+
await new Promise((resolve2) => {
|
|
4423
4448
|
const timer = setTimeout(() => {
|
|
4424
4449
|
this.ws.terminate();
|
|
4425
|
-
|
|
4450
|
+
resolve2();
|
|
4426
4451
|
}, 500);
|
|
4427
4452
|
this.ws.once("close", () => {
|
|
4428
4453
|
clearTimeout(timer);
|
|
4429
|
-
|
|
4454
|
+
resolve2();
|
|
4430
4455
|
});
|
|
4431
4456
|
if (this.ws.readyState === wrapper_default.CONNECTING) this.ws.terminate();
|
|
4432
4457
|
else this.ws.close();
|
|
@@ -4446,13 +4471,13 @@ var CdpTab = class _CdpTab {
|
|
|
4446
4471
|
}
|
|
4447
4472
|
async navigate(url) {
|
|
4448
4473
|
let timer;
|
|
4449
|
-
const loaded = new Promise((
|
|
4450
|
-
this.loadFired =
|
|
4474
|
+
const loaded = new Promise((resolve2) => {
|
|
4475
|
+
this.loadFired = resolve2;
|
|
4451
4476
|
});
|
|
4452
4477
|
try {
|
|
4453
4478
|
await this.send("Page.navigate", { url });
|
|
4454
|
-
await Promise.race([loaded, new Promise((
|
|
4455
|
-
timer = setTimeout(
|
|
4479
|
+
await Promise.race([loaded, new Promise((resolve2) => {
|
|
4480
|
+
timer = setTimeout(resolve2, NAVIGATE_LOAD_TIMEOUT_MS);
|
|
4456
4481
|
})]);
|
|
4457
4482
|
} finally {
|
|
4458
4483
|
clearTimeout(timer);
|
|
@@ -4489,11 +4514,11 @@ var CdpTab = class _CdpTab {
|
|
|
4489
4514
|
async mouseAt(x, y, type, button = "left", clickCount2 = 1) {
|
|
4490
4515
|
await this.send("Input.dispatchMouseEvent", { type, x, y, button: type === "mouseMoved" ? "none" : button, clickCount: clickCount2 });
|
|
4491
4516
|
}
|
|
4492
|
-
async dragPath(
|
|
4493
|
-
if (
|
|
4494
|
-
await this.mouseAt(
|
|
4495
|
-
for (const
|
|
4496
|
-
const end =
|
|
4517
|
+
async dragPath(path12) {
|
|
4518
|
+
if (path12.length < 2) throw new Error("CDP drag requires at least two points.");
|
|
4519
|
+
await this.mouseAt(path12[0].x, path12[0].y, "mousePressed");
|
|
4520
|
+
for (const point of path12.slice(1)) await this.send("Input.dispatchMouseEvent", { type: "mouseMoved", x: point.x, y: point.y, button: "left", buttons: 1 });
|
|
4521
|
+
const end = path12[path12.length - 1];
|
|
4497
4522
|
await this.mouseAt(end.x, end.y, "mouseReleased");
|
|
4498
4523
|
}
|
|
4499
4524
|
async withBackendNode(backendNodeId, functionDeclaration, args = []) {
|
|
@@ -4524,7 +4549,7 @@ var CdpTab = class _CdpTab {
|
|
|
4524
4549
|
}
|
|
4525
4550
|
send(method, params = {}) {
|
|
4526
4551
|
const id = this.nextId++;
|
|
4527
|
-
return new Promise((
|
|
4552
|
+
return new Promise((resolve2, reject) => {
|
|
4528
4553
|
const timer = setTimeout(() => {
|
|
4529
4554
|
this.pending.delete(id);
|
|
4530
4555
|
reject(new Error(`CDP command '${method}' timed out after ${COMMAND_TIMEOUT_MS}ms.`));
|
|
@@ -4532,7 +4557,7 @@ var CdpTab = class _CdpTab {
|
|
|
4532
4557
|
this.pending.set(id, {
|
|
4533
4558
|
resolve: (result) => {
|
|
4534
4559
|
clearTimeout(timer);
|
|
4535
|
-
|
|
4560
|
+
resolve2(result);
|
|
4536
4561
|
},
|
|
4537
4562
|
reject: (error) => {
|
|
4538
4563
|
clearTimeout(timer);
|
|
@@ -4712,9 +4737,9 @@ async function cdpMouseForContext(contextId, x, y, type, button = "left", clickC
|
|
|
4712
4737
|
return true;
|
|
4713
4738
|
}) === true;
|
|
4714
4739
|
}
|
|
4715
|
-
async function cdpDragForContext(contextId,
|
|
4740
|
+
async function cdpDragForContext(contextId, path12) {
|
|
4716
4741
|
return await withCdpContextTab(contextId, async (tab) => {
|
|
4717
|
-
await tab.dragPath(
|
|
4742
|
+
await tab.dragPath(path12);
|
|
4718
4743
|
return true;
|
|
4719
4744
|
}) === true;
|
|
4720
4745
|
}
|
|
@@ -4944,16 +4969,57 @@ function titlesMatch(tabTitle, windowTitle) {
|
|
|
4944
4969
|
return tab === win || win.startsWith(tab) || tab.startsWith(win);
|
|
4945
4970
|
}
|
|
4946
4971
|
|
|
4947
|
-
//
|
|
4948
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
4972
|
+
// vendor/computer-use-axi/src/config.ts
|
|
4973
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
4949
4974
|
import path2 from "node:path";
|
|
4950
4975
|
|
|
4951
|
-
//
|
|
4976
|
+
// src/config.ts
|
|
4977
|
+
import { existsSync, mkdirSync, readFileSync, renameSync } from "fs";
|
|
4978
|
+
import { homedir } from "os";
|
|
4979
|
+
import { dirname, join } from "path";
|
|
4980
|
+
import { fileURLToPath } from "url";
|
|
4981
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
4982
|
+
var __dirname = dirname(__filename);
|
|
4983
|
+
var isBunRuntime = !!process.versions.bun;
|
|
4984
|
+
function getPackageDir() {
|
|
4985
|
+
const envDir = process.env.PIE_PACKAGE_DIR;
|
|
4986
|
+
if (envDir) {
|
|
4987
|
+
if (envDir === "~") return homedir();
|
|
4988
|
+
if (envDir.startsWith("~/")) return homedir() + envDir.slice(1);
|
|
4989
|
+
return envDir;
|
|
4990
|
+
}
|
|
4991
|
+
let dir = __dirname;
|
|
4992
|
+
while (dir !== dirname(dir)) {
|
|
4993
|
+
if (existsSync(join(dir, "package.json"))) {
|
|
4994
|
+
return dir;
|
|
4995
|
+
}
|
|
4996
|
+
dir = dirname(dir);
|
|
4997
|
+
}
|
|
4998
|
+
return __dirname;
|
|
4999
|
+
}
|
|
5000
|
+
function getPackageJsonPath() {
|
|
5001
|
+
return join(getPackageDir(), "package.json");
|
|
5002
|
+
}
|
|
5003
|
+
var pkg = JSON.parse(readFileSync(getPackageJsonPath(), "utf-8"));
|
|
5004
|
+
var CONFIG_DIR_NAME = ".pie";
|
|
5005
|
+
var VERSION = pkg.version;
|
|
5006
|
+
var ENV_AGENT_DIR = "PIE_CODING_AGENT_DIR";
|
|
5007
|
+
function getConfigDir() {
|
|
5008
|
+
const envDir = process.env[ENV_AGENT_DIR];
|
|
5009
|
+
if (envDir) {
|
|
5010
|
+
if (envDir === "~") return homedir();
|
|
5011
|
+
if (envDir.startsWith("~/")) return homedir() + envDir.slice(1);
|
|
5012
|
+
return envDir;
|
|
5013
|
+
}
|
|
5014
|
+
return join(homedir(), CONFIG_DIR_NAME);
|
|
5015
|
+
}
|
|
5016
|
+
|
|
5017
|
+
// vendor/computer-use-axi/host.ts
|
|
4952
5018
|
function getAgentDir() {
|
|
4953
5019
|
return getConfigDir();
|
|
4954
5020
|
}
|
|
4955
5021
|
|
|
4956
|
-
//
|
|
5022
|
+
// vendor/computer-use-axi/src/config.ts
|
|
4957
5023
|
var DEFAULT_CONFIG = {
|
|
4958
5024
|
browser_use: true,
|
|
4959
5025
|
headless: false,
|
|
@@ -4986,9 +5052,9 @@ function normalizePartial(raw) {
|
|
|
4986
5052
|
return out;
|
|
4987
5053
|
}
|
|
4988
5054
|
function readConfigFile(filePath) {
|
|
4989
|
-
if (!
|
|
5055
|
+
if (!existsSync2(filePath)) return { path: filePath, exists: false };
|
|
4990
5056
|
try {
|
|
4991
|
-
const parsed = JSON.parse(
|
|
5057
|
+
const parsed = JSON.parse(readFileSync2(filePath, "utf-8"));
|
|
4992
5058
|
return { path: filePath, exists: true, values: normalizePartial(parsed) };
|
|
4993
5059
|
} catch (error) {
|
|
4994
5060
|
return { path: filePath, exists: true, error: error instanceof Error ? error.message : String(error) };
|
|
@@ -5024,9 +5090,6 @@ function loadComputerUseConfig(cwd) {
|
|
|
5024
5090
|
function getComputerUseConfig() {
|
|
5025
5091
|
return activeConfig;
|
|
5026
5092
|
}
|
|
5027
|
-
function getLoadedComputerUseConfig() {
|
|
5028
|
-
return activeLoadedConfig;
|
|
5029
|
-
}
|
|
5030
5093
|
function isHeadlessMode() {
|
|
5031
5094
|
return activeConfig.headless;
|
|
5032
5095
|
}
|
|
@@ -5034,7 +5097,7 @@ function isBrowserUseEnabled() {
|
|
|
5034
5097
|
return activeConfig.browser_use;
|
|
5035
5098
|
}
|
|
5036
5099
|
|
|
5037
|
-
//
|
|
5100
|
+
// vendor/computer-use-axi/src/note.ts
|
|
5038
5101
|
function normalizedLabel(value) {
|
|
5039
5102
|
return value.toLowerCase().replace(/\s+/g, " ").trim();
|
|
5040
5103
|
}
|
|
@@ -5186,10 +5249,111 @@ function renderNote(note) {
|
|
|
5186
5249
|
\u2026 note byte budget reached`;
|
|
5187
5250
|
}
|
|
5188
5251
|
|
|
5189
|
-
//
|
|
5190
|
-
import { closeSync,
|
|
5191
|
-
import
|
|
5252
|
+
// vendor/computer-use-axi/src/output.ts
|
|
5253
|
+
import { closeSync, mkdirSync as mkdirSync3, openSync, readFileSync as readFileSync4, readSync, readdirSync as readdirSync2, statSync as statSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
5254
|
+
import path4 from "node:path";
|
|
5255
|
+
|
|
5256
|
+
// vendor/computer-use-axi/src/persist.ts
|
|
5257
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
5258
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync3, renameSync as renameSync2, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
5192
5259
|
import path3 from "node:path";
|
|
5260
|
+
function stateRootDir(env = process.env) {
|
|
5261
|
+
const override = env.PIE_COMPUTER_USE_STATE_DIR?.trim();
|
|
5262
|
+
if (override) return override;
|
|
5263
|
+
return path3.join(getConfigDir(), "computer-use");
|
|
5264
|
+
}
|
|
5265
|
+
function statesDir(env = process.env) {
|
|
5266
|
+
return path3.join(stateRootDir(env), "states");
|
|
5267
|
+
}
|
|
5268
|
+
function outputsDir(env = process.env) {
|
|
5269
|
+
return path3.join(stateRootDir(env), "outputs");
|
|
5270
|
+
}
|
|
5271
|
+
function runtimeStatePath(env = process.env) {
|
|
5272
|
+
return path3.join(stateRootDir(env), "runtime.json");
|
|
5273
|
+
}
|
|
5274
|
+
function writeJsonAtomic(filePath, value) {
|
|
5275
|
+
mkdirSync2(path3.dirname(filePath), { recursive: true });
|
|
5276
|
+
const temp = `${filePath}.${process.pid}.tmp`;
|
|
5277
|
+
writeFileSync(temp, JSON.stringify(value), "utf8");
|
|
5278
|
+
renameSync2(temp, filePath);
|
|
5279
|
+
}
|
|
5280
|
+
function readJsonFile(filePath) {
|
|
5281
|
+
try {
|
|
5282
|
+
return JSON.parse(readFileSync3(filePath, "utf8"));
|
|
5283
|
+
} catch {
|
|
5284
|
+
return void 0;
|
|
5285
|
+
}
|
|
5286
|
+
}
|
|
5287
|
+
function fileMtime(filePath) {
|
|
5288
|
+
try {
|
|
5289
|
+
return statSync(filePath).mtimeMs;
|
|
5290
|
+
} catch {
|
|
5291
|
+
return 0;
|
|
5292
|
+
}
|
|
5293
|
+
}
|
|
5294
|
+
var DiskStateStore = class {
|
|
5295
|
+
constructor(limit = 128, env = process.env, transform) {
|
|
5296
|
+
this.limit = limit;
|
|
5297
|
+
this.transform = transform;
|
|
5298
|
+
this.dir = statesDir(env);
|
|
5299
|
+
}
|
|
5300
|
+
limit;
|
|
5301
|
+
transform;
|
|
5302
|
+
dir;
|
|
5303
|
+
recordPath(stateId) {
|
|
5304
|
+
if (!/^[A-Za-z0-9-]+$/.test(stateId)) throw new Error(`Invalid stateId: ${stateId}`);
|
|
5305
|
+
return path3.join(this.dir, `${stateId}.json`);
|
|
5306
|
+
}
|
|
5307
|
+
create(resourceKey, epoch, value) {
|
|
5308
|
+
const record = { stateId: randomUUID2(), resourceKey, epoch, value };
|
|
5309
|
+
this.set(record);
|
|
5310
|
+
return record;
|
|
5311
|
+
}
|
|
5312
|
+
set(record) {
|
|
5313
|
+
const persisted = this.transform ? { ...record, value: this.transform(record.value) } : record;
|
|
5314
|
+
writeJsonAtomic(this.recordPath(record.stateId), persisted);
|
|
5315
|
+
this.enforceLimit();
|
|
5316
|
+
}
|
|
5317
|
+
get(stateId) {
|
|
5318
|
+
const filePath = this.recordPath(stateId);
|
|
5319
|
+
if (!existsSync3(filePath)) return void 0;
|
|
5320
|
+
const record = readJsonFile(filePath);
|
|
5321
|
+
if (!record || record.stateId !== stateId) return void 0;
|
|
5322
|
+
return record;
|
|
5323
|
+
}
|
|
5324
|
+
clear() {
|
|
5325
|
+
try {
|
|
5326
|
+
for (const name of readdirSync(this.dir)) {
|
|
5327
|
+
if (name.endsWith(".json")) unlinkSync(path3.join(this.dir, name));
|
|
5328
|
+
}
|
|
5329
|
+
} catch {
|
|
5330
|
+
}
|
|
5331
|
+
}
|
|
5332
|
+
get size() {
|
|
5333
|
+
try {
|
|
5334
|
+
return readdirSync(this.dir).filter((name) => name.endsWith(".json") && !name.endsWith(".tmp")).length;
|
|
5335
|
+
} catch {
|
|
5336
|
+
return 0;
|
|
5337
|
+
}
|
|
5338
|
+
}
|
|
5339
|
+
enforceLimit() {
|
|
5340
|
+
try {
|
|
5341
|
+
const entries = readdirSync(this.dir).filter((name) => name.endsWith(".json")).map((name) => ({ name, mtime: fileMtime(path3.join(this.dir, name)) })).sort((a, b) => b.mtime - a.mtime);
|
|
5342
|
+
for (const entry of entries.slice(this.limit)) {
|
|
5343
|
+
unlinkSync(path3.join(this.dir, entry.name));
|
|
5344
|
+
}
|
|
5345
|
+
} catch {
|
|
5346
|
+
}
|
|
5347
|
+
}
|
|
5348
|
+
};
|
|
5349
|
+
function loadRuntimeStateSnapshot(env = process.env) {
|
|
5350
|
+
return readJsonFile(runtimeStatePath(env));
|
|
5351
|
+
}
|
|
5352
|
+
function persistRuntimeStateSnapshot(snapshot, env = process.env) {
|
|
5353
|
+
writeJsonAtomic(runtimeStatePath(env), snapshot);
|
|
5354
|
+
}
|
|
5355
|
+
|
|
5356
|
+
// vendor/computer-use-axi/src/output.ts
|
|
5193
5357
|
var MODEL_TEXT_MAX_BYTES = 48 * 1024;
|
|
5194
5358
|
var MODEL_TEXT_MAX_LINES = 2e3;
|
|
5195
5359
|
var OUTPUT_PAGE_BYTES = 16 * 1024;
|
|
@@ -5201,6 +5365,53 @@ var outputs = /* @__PURE__ */ new Map();
|
|
|
5201
5365
|
var outputDirectory;
|
|
5202
5366
|
var outputBytes = 0;
|
|
5203
5367
|
var nextOutputId = 1;
|
|
5368
|
+
var outputsScanned = false;
|
|
5369
|
+
function ensureOutputDirectory() {
|
|
5370
|
+
if (!outputDirectory) {
|
|
5371
|
+
outputDirectory = outputsDir();
|
|
5372
|
+
mkdirSync3(outputDirectory, { recursive: true });
|
|
5373
|
+
}
|
|
5374
|
+
if (!outputsScanned) {
|
|
5375
|
+
outputsScanned = true;
|
|
5376
|
+
try {
|
|
5377
|
+
for (const name of readdirSync2(outputDirectory)) {
|
|
5378
|
+
const match = /^o(\d+)\.meta\.json$/.exec(name);
|
|
5379
|
+
if (!match) continue;
|
|
5380
|
+
const id = Number(match[1]);
|
|
5381
|
+
if (Number.isFinite(id) && id >= nextOutputId) nextOutputId = id + 1;
|
|
5382
|
+
const metaPath = path4.join(outputDirectory, name);
|
|
5383
|
+
try {
|
|
5384
|
+
const meta = JSON.parse(readFileSyncText(metaPath));
|
|
5385
|
+
if (!meta.ref || typeof meta.ref !== "string") continue;
|
|
5386
|
+
const filePath = path4.join(outputDirectory, `${meta.ref.slice(2)}.txt`);
|
|
5387
|
+
if (!statSyncSafe(filePath)) continue;
|
|
5388
|
+
outputs.set(meta.ref, {
|
|
5389
|
+
ref: meta.ref,
|
|
5390
|
+
filePath,
|
|
5391
|
+
storedBytes: Math.max(0, Math.trunc(meta.storedBytes ?? 0)),
|
|
5392
|
+
totalBytes: Math.max(0, Math.trunc(meta.totalBytes ?? meta.storedBytes ?? 0)),
|
|
5393
|
+
complete: meta.complete === true
|
|
5394
|
+
});
|
|
5395
|
+
outputBytes += Math.max(0, Math.trunc(meta.storedBytes ?? 0));
|
|
5396
|
+
} catch {
|
|
5397
|
+
}
|
|
5398
|
+
}
|
|
5399
|
+
} catch {
|
|
5400
|
+
}
|
|
5401
|
+
}
|
|
5402
|
+
return outputDirectory;
|
|
5403
|
+
}
|
|
5404
|
+
function readFileSyncText(filePath) {
|
|
5405
|
+
return readFileSync4(filePath, "utf8");
|
|
5406
|
+
}
|
|
5407
|
+
function statSyncSafe(filePath) {
|
|
5408
|
+
try {
|
|
5409
|
+
statSync2(filePath);
|
|
5410
|
+
return true;
|
|
5411
|
+
} catch {
|
|
5412
|
+
return false;
|
|
5413
|
+
}
|
|
5414
|
+
}
|
|
5204
5415
|
function utf8Prefix(bytes, maxBytes) {
|
|
5205
5416
|
if (bytes.byteLength <= maxBytes) return bytes;
|
|
5206
5417
|
let end = Math.max(0, maxBytes);
|
|
@@ -5215,10 +5426,11 @@ function boundedPrefix(value, maxBytes, maxLines) {
|
|
|
5215
5426
|
function storeOutput(value) {
|
|
5216
5427
|
const encoded = new TextEncoder().encode(value);
|
|
5217
5428
|
const stored = encoded.byteLength > OUTPUT_ENTRY_MAX_BYTES ? utf8Prefix(encoded, OUTPUT_ENTRY_MAX_BYTES) : encoded;
|
|
5218
|
-
|
|
5429
|
+
const directory = ensureOutputDirectory();
|
|
5219
5430
|
const ref = `@o${nextOutputId++}`;
|
|
5220
|
-
const filePath =
|
|
5221
|
-
|
|
5431
|
+
const filePath = path4.join(directory, `${ref.slice(2)}.txt`);
|
|
5432
|
+
writeFileSync2(filePath, stored, { mode: 384 });
|
|
5433
|
+
writeFileSync2(path4.join(directory, `${ref.slice(2)}.meta.json`), JSON.stringify({ ref, storedBytes: stored.byteLength, totalBytes: encoded.byteLength, complete: stored.byteLength === encoded.byteLength }), { mode: 384 });
|
|
5222
5434
|
const entry = { ref, filePath, storedBytes: stored.byteLength, totalBytes: encoded.byteLength, complete: stored.byteLength === encoded.byteLength };
|
|
5223
5435
|
outputs.set(entry.ref, entry);
|
|
5224
5436
|
outputBytes += entry.storedBytes;
|
|
@@ -5229,7 +5441,11 @@ function storeOutput(value) {
|
|
|
5229
5441
|
outputs.delete(oldestRef);
|
|
5230
5442
|
outputBytes -= oldest.storedBytes;
|
|
5231
5443
|
try {
|
|
5232
|
-
|
|
5444
|
+
unlinkSync2(oldest.filePath);
|
|
5445
|
+
} catch {
|
|
5446
|
+
}
|
|
5447
|
+
try {
|
|
5448
|
+
unlinkSync2(path4.join(directory, `${oldestRef.slice(2)}.meta.json`));
|
|
5233
5449
|
} catch {
|
|
5234
5450
|
}
|
|
5235
5451
|
}
|
|
@@ -5278,7 +5494,11 @@ refine: ${refinementFor(tool)}
|
|
|
5278
5494
|
continue: read_text({ ref: "${entry.ref}", offset: ${returnedBytes} })${storageNote}`);
|
|
5279
5495
|
}
|
|
5280
5496
|
function readStoredOutput(ref, offsetValue) {
|
|
5281
|
-
|
|
5497
|
+
let entry = outputs.get(ref);
|
|
5498
|
+
if (!entry) {
|
|
5499
|
+
ensureOutputDirectory();
|
|
5500
|
+
entry = outputs.get(ref);
|
|
5501
|
+
}
|
|
5282
5502
|
if (!entry) return void 0;
|
|
5283
5503
|
let offset = Math.min(entry.storedBytes, Math.max(0, Math.trunc(typeof offsetValue === "number" && Number.isFinite(offsetValue) ? offsetValue : 0)));
|
|
5284
5504
|
const requestedBytes = Math.min(entry.storedBytes - offset, OUTPUT_PAGE_BYTES + 4);
|
|
@@ -5303,56 +5523,29 @@ function readStoredOutput(ref, offsetValue) {
|
|
|
5303
5523
|
complete: entry.complete
|
|
5304
5524
|
};
|
|
5305
5525
|
}
|
|
5306
|
-
function clearStoredOutputs() {
|
|
5307
|
-
outputs.clear();
|
|
5308
|
-
if (outputDirectory) {
|
|
5309
|
-
try {
|
|
5310
|
-
rmSync(outputDirectory, { recursive: true, force: true });
|
|
5311
|
-
} catch {
|
|
5312
|
-
}
|
|
5313
|
-
}
|
|
5314
|
-
outputDirectory = void 0;
|
|
5315
|
-
outputBytes = 0;
|
|
5316
|
-
nextOutputId = 1;
|
|
5317
|
-
}
|
|
5318
|
-
|
|
5319
|
-
// builtin/extensions/computer-use/src/contract.ts
|
|
5320
|
-
var AGENT_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
5321
|
-
"find_roots",
|
|
5322
|
-
"read_text",
|
|
5323
|
-
"wait_for",
|
|
5324
|
-
"observe_ui",
|
|
5325
|
-
"search_ui",
|
|
5326
|
-
"expand_ui",
|
|
5327
|
-
"inspect_ui",
|
|
5328
|
-
"act_ui",
|
|
5329
|
-
"navigate_browser",
|
|
5330
|
-
"evaluate_browser",
|
|
5331
|
-
"launch_browser"
|
|
5332
|
-
]);
|
|
5333
5526
|
|
|
5334
|
-
//
|
|
5527
|
+
// vendor/computer-use-axi/src/platform/macos/helper.ts
|
|
5335
5528
|
import { spawn } from "node:child_process";
|
|
5336
5529
|
import { constants as fsConstants2 } from "node:fs";
|
|
5337
5530
|
import { access, mkdir, realpath } from "node:fs/promises";
|
|
5338
5531
|
import net from "node:net";
|
|
5339
|
-
import os3 from "node:os";
|
|
5340
|
-
import path6 from "node:path";
|
|
5341
|
-
|
|
5342
|
-
// builtin/extensions/computer-use/src/platform/macos/helper-path.mjs
|
|
5343
|
-
import { accessSync, constants as fsConstants, existsSync as existsSync2 } from "node:fs";
|
|
5344
5532
|
import os2 from "node:os";
|
|
5345
|
-
import
|
|
5533
|
+
import path7 from "node:path";
|
|
5534
|
+
|
|
5535
|
+
// vendor/computer-use-axi/src/platform/macos/helper-path.mjs
|
|
5536
|
+
import { accessSync, constants as fsConstants, existsSync as existsSync4 } from "node:fs";
|
|
5537
|
+
import os from "node:os";
|
|
5538
|
+
import path5 from "node:path";
|
|
5346
5539
|
var HELPER_APP_NAME = "pie-computer-use.app";
|
|
5347
|
-
var SYSTEM_HELPER_APP_PATH =
|
|
5540
|
+
var SYSTEM_HELPER_APP_PATH = path5.join("/Applications", HELPER_APP_NAME);
|
|
5348
5541
|
function resolveMacosHelperAppPath(options = {}) {
|
|
5349
5542
|
const env = options.env ?? process.env;
|
|
5350
5543
|
const explicitPath = env.PIE_COMPUTER_USE_HELPER_APP_PATH?.trim();
|
|
5351
|
-
if (explicitPath) return
|
|
5352
|
-
const homeDir = options.homeDir ??
|
|
5544
|
+
if (explicitPath) return path5.resolve(explicitPath);
|
|
5545
|
+
const homeDir = options.homeDir ?? os.homedir();
|
|
5353
5546
|
const configDir = options.configDir ?? resolvePieConfigDir(env, homeDir);
|
|
5354
5547
|
const systemHelperAppPath = options.systemHelperAppPath ?? SYSTEM_HELPER_APP_PATH;
|
|
5355
|
-
const fileExists = options.fileExists ??
|
|
5548
|
+
const fileExists = options.fileExists ?? existsSync4;
|
|
5356
5549
|
const directoryIsWritable = options.directoryIsWritable ?? ((directoryPath) => {
|
|
5357
5550
|
try {
|
|
5358
5551
|
accessSync(directoryPath, fsConstants.W_OK);
|
|
@@ -5361,10 +5554,10 @@ function resolveMacosHelperAppPath(options = {}) {
|
|
|
5361
5554
|
return false;
|
|
5362
5555
|
}
|
|
5363
5556
|
});
|
|
5364
|
-
if (fileExists(systemHelperAppPath) && directoryIsWritable(
|
|
5557
|
+
if (fileExists(systemHelperAppPath) && directoryIsWritable(path5.dirname(systemHelperAppPath))) {
|
|
5365
5558
|
return systemHelperAppPath;
|
|
5366
5559
|
}
|
|
5367
|
-
return
|
|
5560
|
+
return path5.join(configDir, "computer-use", HELPER_APP_NAME);
|
|
5368
5561
|
}
|
|
5369
5562
|
function resolvePieConfigDir(env, homeDir) {
|
|
5370
5563
|
const envDir = env.PIE_CODING_AGENT_DIR;
|
|
@@ -5373,37 +5566,37 @@ function resolvePieConfigDir(env, homeDir) {
|
|
|
5373
5566
|
if (envDir.startsWith("~/")) return homeDir + envDir.slice(1);
|
|
5374
5567
|
return envDir;
|
|
5375
5568
|
}
|
|
5376
|
-
return
|
|
5569
|
+
return path5.join(homeDir, ".pie");
|
|
5377
5570
|
}
|
|
5378
5571
|
|
|
5379
|
-
//
|
|
5380
|
-
import { existsSync as
|
|
5381
|
-
import
|
|
5382
|
-
import { fileURLToPath } from "node:url";
|
|
5572
|
+
// vendor/computer-use-axi/src/platform/package-root.ts
|
|
5573
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
5574
|
+
import path6 from "node:path";
|
|
5575
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
5383
5576
|
function resolveExtensionRoot(moduleUrl) {
|
|
5384
5577
|
const override = process.env.PIE_COMPUTER_USE_PACKAGE_ROOT?.trim();
|
|
5385
|
-
if (override) return
|
|
5386
|
-
let dir =
|
|
5578
|
+
if (override) return path6.resolve(override);
|
|
5579
|
+
let dir = path6.dirname(fileURLToPath2(moduleUrl));
|
|
5387
5580
|
for (let depth = 0; depth < 12; depth += 1) {
|
|
5388
|
-
if (
|
|
5389
|
-
const parent =
|
|
5581
|
+
if (existsSync5(path6.join(dir, "scripts", "setup-helper.mjs"))) return dir;
|
|
5582
|
+
const parent = path6.dirname(dir);
|
|
5390
5583
|
if (parent === dir) break;
|
|
5391
5584
|
dir = parent;
|
|
5392
5585
|
}
|
|
5393
|
-
throw new Error(`computer-use: could not locate extension root (scripts/setup-helper.mjs) above ${
|
|
5586
|
+
throw new Error(`computer-use: could not locate extension root (scripts/setup-helper.mjs) above ${path6.dirname(fileURLToPath2(moduleUrl))}. Set PIE_COMPUTER_USE_PACKAGE_ROOT.`);
|
|
5394
5587
|
}
|
|
5395
5588
|
|
|
5396
|
-
//
|
|
5589
|
+
// vendor/computer-use-axi/src/platform/macos/helper.ts
|
|
5397
5590
|
var COMMAND_TIMEOUT_MS2 = 15e3;
|
|
5398
5591
|
var HELPER_PROTOCOL_VERSION = 6;
|
|
5399
5592
|
var HELPER_SETUP_TIMEOUT_MS = 6e4;
|
|
5400
5593
|
var HELPER_APP_PATH = resolveMacosHelperAppPath();
|
|
5401
|
-
var HELPER_APP_EXECUTABLE_PATH =
|
|
5402
|
-
var DEFAULT_HELPER_SOCKET_PATH =
|
|
5594
|
+
var HELPER_APP_EXECUTABLE_PATH = path7.join(HELPER_APP_PATH, "Contents", "MacOS", "pie-computer-use");
|
|
5595
|
+
var DEFAULT_HELPER_SOCKET_PATH = path7.join(os2.homedir(), "Library", "Caches", "pie-computer-use", "bridge.sock");
|
|
5403
5596
|
var HELPER_SOCKET_PATH = process.env.PIE_COMPUTER_USE_SOCKET_PATH ?? DEFAULT_HELPER_SOCKET_PATH;
|
|
5404
5597
|
var usingExternalHelperSocket = HELPER_SOCKET_PATH !== DEFAULT_HELPER_SOCKET_PATH;
|
|
5405
5598
|
var PACKAGE_ROOT = resolveExtensionRoot(import.meta.url);
|
|
5406
|
-
var SETUP_HELPER_SCRIPT =
|
|
5599
|
+
var SETUP_HELPER_SCRIPT = path7.join(PACKAGE_ROOT, "scripts", "setup-helper.mjs");
|
|
5407
5600
|
var HelperTransportError = class extends Error {
|
|
5408
5601
|
constructor(message) {
|
|
5409
5602
|
super(message);
|
|
@@ -5423,8 +5616,8 @@ function throwIfAborted(signal) {
|
|
|
5423
5616
|
}
|
|
5424
5617
|
async function sleep(ms, signal) {
|
|
5425
5618
|
throwIfAborted(signal);
|
|
5426
|
-
await new Promise((
|
|
5427
|
-
const timer = setTimeout(
|
|
5619
|
+
await new Promise((resolve2, reject) => {
|
|
5620
|
+
const timer = setTimeout(resolve2, ms);
|
|
5428
5621
|
const onAbort = () => {
|
|
5429
5622
|
clearTimeout(timer);
|
|
5430
5623
|
reject(new Error("Operation aborted."));
|
|
@@ -5443,14 +5636,14 @@ async function isExecutable(filePath) {
|
|
|
5443
5636
|
async function isResolvedHelperExecutable(filePath) {
|
|
5444
5637
|
if (!filePath) return true;
|
|
5445
5638
|
const [actualPath, expectedPath] = await Promise.all([
|
|
5446
|
-
realpath(filePath).catch(() =>
|
|
5447
|
-
realpath(HELPER_APP_EXECUTABLE_PATH).catch(() =>
|
|
5639
|
+
realpath(filePath).catch(() => path7.resolve(filePath)),
|
|
5640
|
+
realpath(HELPER_APP_EXECUTABLE_PATH).catch(() => path7.resolve(HELPER_APP_EXECUTABLE_PATH))
|
|
5448
5641
|
]);
|
|
5449
5642
|
return actualPath === expectedPath;
|
|
5450
5643
|
}
|
|
5451
5644
|
async function runProcess(command, args, timeoutMs, signal, env) {
|
|
5452
5645
|
throwIfAborted(signal);
|
|
5453
|
-
await new Promise((
|
|
5646
|
+
await new Promise((resolve2, reject) => {
|
|
5454
5647
|
const child = spawn(command, args, {
|
|
5455
5648
|
stdio: ["ignore", "pipe", "pipe"],
|
|
5456
5649
|
env
|
|
@@ -5484,7 +5677,7 @@ async function runProcess(command, args, timeoutMs, signal, env) {
|
|
|
5484
5677
|
child.on("close", (code) => {
|
|
5485
5678
|
cleanup();
|
|
5486
5679
|
if (code === 0) {
|
|
5487
|
-
|
|
5680
|
+
resolve2();
|
|
5488
5681
|
return;
|
|
5489
5682
|
}
|
|
5490
5683
|
const output = [stderr.trim(), stdout.trim()].filter(Boolean).join("\n");
|
|
@@ -5517,11 +5710,11 @@ var MacosHelperClient = class {
|
|
|
5517
5710
|
}
|
|
5518
5711
|
async launchDaemon(signal) {
|
|
5519
5712
|
if (usingExternalHelperSocket) throw new HelperTransportError(`External helper socket is unavailable at ${HELPER_SOCKET_PATH}.`);
|
|
5520
|
-
await mkdir(
|
|
5713
|
+
await mkdir(path7.dirname(HELPER_SOCKET_PATH), { recursive: true });
|
|
5521
5714
|
await runProcess("open", ["-n", "-g", HELPER_APP_PATH, "--args", "serve", "--socket", HELPER_SOCKET_PATH], COMMAND_TIMEOUT_MS2, signal);
|
|
5522
5715
|
}
|
|
5523
5716
|
async daemonCommand(cmd, args, timeoutMs, signal) {
|
|
5524
|
-
return await new Promise((
|
|
5717
|
+
return await new Promise((resolve2, reject) => {
|
|
5525
5718
|
const id = `req_${++this.requestSequence}`;
|
|
5526
5719
|
const socket = net.createConnection(HELPER_SOCKET_PATH);
|
|
5527
5720
|
let buffer = "";
|
|
@@ -5550,7 +5743,7 @@ var MacosHelperClient = class {
|
|
|
5550
5743
|
socket.end();
|
|
5551
5744
|
try {
|
|
5552
5745
|
const parsed = JSON.parse(buffer.slice(0, newline));
|
|
5553
|
-
if (parsed.ok === true)
|
|
5746
|
+
if (parsed.ok === true) resolve2(parsed.result);
|
|
5554
5747
|
else reject(new HelperCommandError(parsed?.error?.message ?? `Daemon command '${cmd}' failed.`, parsed?.error?.code));
|
|
5555
5748
|
} catch (error) {
|
|
5556
5749
|
reject(error);
|
|
@@ -5640,7 +5833,7 @@ var MacosHelperClient = class {
|
|
|
5640
5833
|
};
|
|
5641
5834
|
var macosHelper = new MacosHelperClient();
|
|
5642
5835
|
|
|
5643
|
-
//
|
|
5836
|
+
// vendor/computer-use-axi/src/platform/macos/backend.ts
|
|
5644
5837
|
function parseApps(result) {
|
|
5645
5838
|
const array = Array.isArray(result) ? result : result?.apps;
|
|
5646
5839
|
if (!Array.isArray(array)) return [];
|
|
@@ -5751,7 +5944,7 @@ var macosBackend = {
|
|
|
5751
5944
|
}
|
|
5752
5945
|
};
|
|
5753
5946
|
|
|
5754
|
-
//
|
|
5947
|
+
// vendor/computer-use-axi/src/platform/macos/browser.ts
|
|
5755
5948
|
var BROWSER_WINDOW_OPEN_TIMEOUT_MS = 1e4;
|
|
5756
5949
|
var BROWSER_BUNDLE_IDS = /* @__PURE__ */ new Set([
|
|
5757
5950
|
"com.apple.Safari",
|
|
@@ -5849,7 +6042,7 @@ async function openBrowserLocationWithAppleScript(target, url, signal) {
|
|
|
5849
6042
|
}
|
|
5850
6043
|
}
|
|
5851
6044
|
|
|
5852
|
-
//
|
|
6045
|
+
// vendor/computer-use-axi/src/permissions.ts
|
|
5853
6046
|
function throwIfAborted2(signal) {
|
|
5854
6047
|
if (signal?.aborted) throw new Error("Operation aborted.");
|
|
5855
6048
|
}
|
|
@@ -5892,7 +6085,7 @@ async function ensurePermissions(ctx, bridge, helperPath, signal) {
|
|
|
5892
6085
|
return status;
|
|
5893
6086
|
}
|
|
5894
6087
|
|
|
5895
|
-
//
|
|
6088
|
+
// vendor/computer-use-axi/src/platform/architecture.ts
|
|
5896
6089
|
var PLATFORM_ARCHITECTURE_VERSION = 1;
|
|
5897
6090
|
var REQUIRED_PLATFORM_INVARIANTS = [
|
|
5898
6091
|
"state-scoped-observations",
|
|
@@ -5914,7 +6107,7 @@ function assertPlatformArchitecture(platform, diagnostics) {
|
|
|
5914
6107
|
}
|
|
5915
6108
|
}
|
|
5916
6109
|
|
|
5917
|
-
//
|
|
6110
|
+
// vendor/computer-use-axi/src/platform/macos/permissions.ts
|
|
5918
6111
|
var GRANT_INSTRUCTIONS = "Grant Accessibility and Screen Recording to pie-computer-use.app in System Settings \u2192 Privacy & Security. Screen Recording lets the agent see the window; Accessibility lets it interact with the window.";
|
|
5919
6112
|
var SIGNING_MIGRATION_WARNING = "If these permissions were enabled before this install/update, macOS invalidated the old grants because pie-computer-use.app was re-signed. Re-enable both toggles for the newly signed helper. If a toggle is already on, switch it off and on again.";
|
|
5920
6113
|
var macosPermissionKinds = [
|
|
@@ -6033,18 +6226,18 @@ Helper path: ${helperPath}`,
|
|
|
6033
6226
|
return { permissionStatus, lastPermissionCheckAt, helperDiagnostics };
|
|
6034
6227
|
}
|
|
6035
6228
|
|
|
6036
|
-
//
|
|
6229
|
+
// vendor/computer-use-axi/src/platform/linux/helper.ts
|
|
6037
6230
|
import { spawn as spawn2 } from "node:child_process";
|
|
6038
|
-
import { randomUUID as
|
|
6231
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
6039
6232
|
import { constants as fsConstants3 } from "node:fs";
|
|
6040
6233
|
import { access as access2 } from "node:fs/promises";
|
|
6041
|
-
import
|
|
6234
|
+
import path8 from "node:path";
|
|
6042
6235
|
var PACKAGE_ROOT2 = resolveExtensionRoot(import.meta.url);
|
|
6043
|
-
var SETUP_HELPER_SCRIPT2 =
|
|
6236
|
+
var SETUP_HELPER_SCRIPT2 = path8.join(PACKAGE_ROOT2, "scripts", "setup-helper.mjs");
|
|
6044
6237
|
var HELPER_SETUP_TIMEOUT_MS2 = 6e4;
|
|
6045
6238
|
var COMMAND_TIMEOUT_MS3 = 15e3;
|
|
6046
6239
|
var LINUX_HELPER_PROTOCOL_VERSION = 4;
|
|
6047
|
-
var LINUX_HELPER_PATH = process.env.PIE_COMPUTER_USE_LINUX_HELPER_PATH ||
|
|
6240
|
+
var LINUX_HELPER_PATH = process.env.PIE_COMPUTER_USE_LINUX_HELPER_PATH || path8.join(getAgentDir(), "helpers", "computer-use", "linux-bridge");
|
|
6048
6241
|
async function isExecutable2(filePath) {
|
|
6049
6242
|
try {
|
|
6050
6243
|
await access2(filePath, fsConstants3.X_OK);
|
|
@@ -6055,7 +6248,7 @@ async function isExecutable2(filePath) {
|
|
|
6055
6248
|
}
|
|
6056
6249
|
async function runProcess2(command, args, timeoutMs, signal, env) {
|
|
6057
6250
|
if (signal?.aborted) throw new Error("Operation aborted.");
|
|
6058
|
-
await new Promise((
|
|
6251
|
+
await new Promise((resolve2, reject) => {
|
|
6059
6252
|
const child = spawn2(command, args, { stdio: ["ignore", "pipe", "pipe"], env });
|
|
6060
6253
|
let stdout = "";
|
|
6061
6254
|
let stderr = "";
|
|
@@ -6066,7 +6259,7 @@ async function runProcess2(command, args, timeoutMs, signal, env) {
|
|
|
6066
6259
|
clearTimeout(timer);
|
|
6067
6260
|
signal?.removeEventListener("abort", onAbort);
|
|
6068
6261
|
if (error) reject(error);
|
|
6069
|
-
else
|
|
6262
|
+
else resolve2();
|
|
6070
6263
|
};
|
|
6071
6264
|
const timer = setTimeout(() => {
|
|
6072
6265
|
child.kill("SIGTERM");
|
|
@@ -6095,13 +6288,13 @@ ${output}`.trim()));
|
|
|
6095
6288
|
async function waitForShared(promise, signal) {
|
|
6096
6289
|
if (!signal) return await promise;
|
|
6097
6290
|
if (signal.aborted) throw new Error("Operation aborted.");
|
|
6098
|
-
return await new Promise((
|
|
6291
|
+
return await new Promise((resolve2, reject) => {
|
|
6099
6292
|
const onAbort = () => reject(new Error("Operation aborted."));
|
|
6100
6293
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
6101
6294
|
promise.then(
|
|
6102
6295
|
(value) => {
|
|
6103
6296
|
signal.removeEventListener("abort", onAbort);
|
|
6104
|
-
|
|
6297
|
+
resolve2(value);
|
|
6105
6298
|
},
|
|
6106
6299
|
(error) => {
|
|
6107
6300
|
signal.removeEventListener("abort", onAbort);
|
|
@@ -6203,8 +6396,8 @@ var LinuxHelperClient = class {
|
|
|
6203
6396
|
});
|
|
6204
6397
|
this.child = child;
|
|
6205
6398
|
this.buffer = "";
|
|
6206
|
-
return await new Promise((
|
|
6207
|
-
child.once("spawn", () =>
|
|
6399
|
+
return await new Promise((resolve2, reject) => {
|
|
6400
|
+
child.once("spawn", () => resolve2(child));
|
|
6208
6401
|
child.once("error", reject);
|
|
6209
6402
|
});
|
|
6210
6403
|
}
|
|
@@ -6239,9 +6432,9 @@ var LinuxHelperClient = class {
|
|
|
6239
6432
|
}
|
|
6240
6433
|
async command(cmd, args = {}, options) {
|
|
6241
6434
|
const child = await this.process(options?.signal);
|
|
6242
|
-
const id =
|
|
6435
|
+
const id = randomUUID3();
|
|
6243
6436
|
const timeoutMs = options?.timeoutMs ?? COMMAND_TIMEOUT_MS3;
|
|
6244
|
-
return await new Promise((
|
|
6437
|
+
return await new Promise((resolve2, reject) => {
|
|
6245
6438
|
const onAbort = () => {
|
|
6246
6439
|
this.pending.delete(id);
|
|
6247
6440
|
clearTimeout(timer);
|
|
@@ -6255,7 +6448,7 @@ var LinuxHelperClient = class {
|
|
|
6255
6448
|
this.pending.set(id, {
|
|
6256
6449
|
resolve: (value) => {
|
|
6257
6450
|
options?.signal?.removeEventListener("abort", onAbort);
|
|
6258
|
-
|
|
6451
|
+
resolve2(value);
|
|
6259
6452
|
},
|
|
6260
6453
|
reject: (error) => {
|
|
6261
6454
|
options?.signal?.removeEventListener("abort", onAbort);
|
|
@@ -6277,7 +6470,7 @@ var LinuxHelperClient = class {
|
|
|
6277
6470
|
};
|
|
6278
6471
|
var linuxHelper = new LinuxHelperClient();
|
|
6279
6472
|
|
|
6280
|
-
//
|
|
6473
|
+
// vendor/computer-use-axi/src/platform/linux/backend.ts
|
|
6281
6474
|
function normalizedProcessName(appName) {
|
|
6282
6475
|
return appName.toLowerCase().split("/").pop().replace(/\.desktop$/i, "");
|
|
6283
6476
|
}
|
|
@@ -6433,18 +6626,18 @@ var linuxBackend = {
|
|
|
6433
6626
|
}
|
|
6434
6627
|
};
|
|
6435
6628
|
|
|
6436
|
-
//
|
|
6629
|
+
// vendor/computer-use-axi/src/platform/windows/helper.ts
|
|
6437
6630
|
import { spawn as spawn3 } from "node:child_process";
|
|
6438
|
-
import { randomUUID as
|
|
6631
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
6439
6632
|
import { constants as fsConstants4 } from "node:fs";
|
|
6440
6633
|
import { access as access3 } from "node:fs/promises";
|
|
6441
|
-
import
|
|
6634
|
+
import path9 from "node:path";
|
|
6442
6635
|
var PACKAGE_ROOT3 = resolveExtensionRoot(import.meta.url);
|
|
6443
|
-
var SETUP_HELPER_SCRIPT3 =
|
|
6636
|
+
var SETUP_HELPER_SCRIPT3 = path9.join(PACKAGE_ROOT3, "scripts", "setup-helper.mjs");
|
|
6444
6637
|
var HELPER_SETUP_TIMEOUT_MS3 = 6e4;
|
|
6445
6638
|
var COMMAND_TIMEOUT_MS4 = 15e3;
|
|
6446
6639
|
var WINDOWS_HELPER_PROTOCOL_VERSION = 4;
|
|
6447
|
-
var WINDOWS_HELPER_PATH = process.env.PIE_COMPUTER_USE_WINDOWS_HELPER_PATH ||
|
|
6640
|
+
var WINDOWS_HELPER_PATH = process.env.PIE_COMPUTER_USE_WINDOWS_HELPER_PATH || path9.join(getAgentDir(), "helpers", "computer-use", "windows-bridge.exe");
|
|
6448
6641
|
async function isExecutable3(filePath) {
|
|
6449
6642
|
try {
|
|
6450
6643
|
await access3(filePath, fsConstants4.X_OK);
|
|
@@ -6455,7 +6648,7 @@ async function isExecutable3(filePath) {
|
|
|
6455
6648
|
}
|
|
6456
6649
|
async function runProcess3(command, args, timeoutMs, signal, env) {
|
|
6457
6650
|
if (signal?.aborted) throw new Error("Operation aborted.");
|
|
6458
|
-
await new Promise((
|
|
6651
|
+
await new Promise((resolve2, reject) => {
|
|
6459
6652
|
const child = spawn3(command, args, { stdio: ["ignore", "pipe", "pipe"], env });
|
|
6460
6653
|
let stdout = "";
|
|
6461
6654
|
let stderr = "";
|
|
@@ -6485,7 +6678,7 @@ async function runProcess3(command, args, timeoutMs, signal, env) {
|
|
|
6485
6678
|
});
|
|
6486
6679
|
child.on("close", (code) => {
|
|
6487
6680
|
cleanup();
|
|
6488
|
-
if (code === 0) return
|
|
6681
|
+
if (code === 0) return resolve2();
|
|
6489
6682
|
const output = [stderr.trim(), stdout.trim()].filter(Boolean).join("\n");
|
|
6490
6683
|
reject(new Error(`Command failed (${code}): ${command} ${args.join(" ")}
|
|
6491
6684
|
${output}`.trim()));
|
|
@@ -6570,14 +6763,14 @@ var WindowsHelperClient = class {
|
|
|
6570
6763
|
}
|
|
6571
6764
|
async command(cmd, args = {}, options) {
|
|
6572
6765
|
const child = await this.process(options?.signal);
|
|
6573
|
-
const id =
|
|
6766
|
+
const id = randomUUID4();
|
|
6574
6767
|
const timeoutMs = options?.timeoutMs ?? COMMAND_TIMEOUT_MS4;
|
|
6575
|
-
return await new Promise((
|
|
6768
|
+
return await new Promise((resolve2, reject) => {
|
|
6576
6769
|
const timer = setTimeout(() => {
|
|
6577
6770
|
this.pending.delete(id);
|
|
6578
6771
|
reject(new Error(`Helper command '${cmd}' timed out after ${timeoutMs}ms.`));
|
|
6579
6772
|
}, timeoutMs);
|
|
6580
|
-
this.pending.set(id, { resolve, reject, timer });
|
|
6773
|
+
this.pending.set(id, { resolve: resolve2, reject, timer });
|
|
6581
6774
|
child.stdin.write(`${JSON.stringify({ protocolVersion: WINDOWS_HELPER_PROTOCOL_VERSION, id, cmd, args })}
|
|
6582
6775
|
`, (error) => {
|
|
6583
6776
|
if (!error) return;
|
|
@@ -6590,7 +6783,7 @@ var WindowsHelperClient = class {
|
|
|
6590
6783
|
};
|
|
6591
6784
|
var windowsHelper = new WindowsHelperClient();
|
|
6592
6785
|
|
|
6593
|
-
//
|
|
6786
|
+
// vendor/computer-use-axi/src/platform/windows/backend.ts
|
|
6594
6787
|
function normalizedProcessName2(appName) {
|
|
6595
6788
|
return appName.toLowerCase().replace(/\.exe$/i, "");
|
|
6596
6789
|
}
|
|
@@ -6726,7 +6919,7 @@ var windowsBackend = {
|
|
|
6726
6919
|
}
|
|
6727
6920
|
};
|
|
6728
6921
|
|
|
6729
|
-
//
|
|
6922
|
+
// vendor/computer-use-axi/src/platform/index.ts
|
|
6730
6923
|
var macosPlatformBackend = {
|
|
6731
6924
|
name: "macos",
|
|
6732
6925
|
ensureReady: ensureMacosReady,
|
|
@@ -6798,8 +6991,8 @@ function platformBackendForRuntime(platform = process.platform) {
|
|
|
6798
6991
|
}
|
|
6799
6992
|
var currentPlatformBackend = platformBackendForRuntime();
|
|
6800
6993
|
|
|
6801
|
-
//
|
|
6802
|
-
import { randomUUID as
|
|
6994
|
+
// vendor/computer-use-axi/src/runtime.ts
|
|
6995
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
6803
6996
|
var StaleResourceStateError = class extends Error {
|
|
6804
6997
|
constructor(resourceKey, expectedEpoch, actualEpoch) {
|
|
6805
6998
|
super(`State is stale for ${resourceKey}: expected epoch ${expectedEpoch}, current epoch ${actualEpoch}.`);
|
|
@@ -6819,7 +7012,7 @@ var StateStore = class {
|
|
|
6819
7012
|
limit;
|
|
6820
7013
|
records = /* @__PURE__ */ new Map();
|
|
6821
7014
|
create(resourceKey, epoch, value) {
|
|
6822
|
-
const record = { stateId:
|
|
7015
|
+
const record = { stateId: randomUUID5(), resourceKey, epoch, value };
|
|
6823
7016
|
this.set(record);
|
|
6824
7017
|
return record;
|
|
6825
7018
|
}
|
|
@@ -6832,8 +7025,8 @@ var StateStore = class {
|
|
|
6832
7025
|
this.records.delete(oldest);
|
|
6833
7026
|
}
|
|
6834
7027
|
}
|
|
6835
|
-
get(
|
|
6836
|
-
return this.records.get(
|
|
7028
|
+
get(stateId) {
|
|
7029
|
+
return this.records.get(stateId);
|
|
6837
7030
|
}
|
|
6838
7031
|
clear() {
|
|
6839
7032
|
this.records.clear();
|
|
@@ -6843,8 +7036,16 @@ var StateStore = class {
|
|
|
6843
7036
|
}
|
|
6844
7037
|
};
|
|
6845
7038
|
var ResourceScheduler = class {
|
|
7039
|
+
constructor(hooks = {}) {
|
|
7040
|
+
this.hooks = hooks;
|
|
7041
|
+
}
|
|
7042
|
+
hooks;
|
|
6846
7043
|
resources = /* @__PURE__ */ new Map();
|
|
6847
7044
|
closed = false;
|
|
7045
|
+
/** Current (resourceKey, epoch) pairs for persistence. */
|
|
7046
|
+
epochs() {
|
|
7047
|
+
return [...this.resources.entries()].map(([key, record]) => [key, record.epoch]);
|
|
7048
|
+
}
|
|
6848
7049
|
epoch(resourceKey) {
|
|
6849
7050
|
return this.resource(resourceKey).epoch;
|
|
6850
7051
|
}
|
|
@@ -6866,6 +7067,7 @@ var ResourceScheduler = class {
|
|
|
6866
7067
|
if (record.epoch !== baseEpoch) throw new StaleResourceStateError(resourceKey, baseEpoch, record.epoch);
|
|
6867
7068
|
const nextEpoch = record.epoch + 1;
|
|
6868
7069
|
record.epoch = nextEpoch;
|
|
7070
|
+
this.hooks.onEpochChange?.(resourceKey, nextEpoch);
|
|
6869
7071
|
return { value: await work(nextEpoch), epoch: nextEpoch };
|
|
6870
7072
|
});
|
|
6871
7073
|
}
|
|
@@ -6890,8 +7092,8 @@ var ResourceScheduler = class {
|
|
|
6890
7092
|
const record = this.resource(resourceKey);
|
|
6891
7093
|
const previous = record.tail;
|
|
6892
7094
|
let release;
|
|
6893
|
-
const next = new Promise((
|
|
6894
|
-
release =
|
|
7095
|
+
const next = new Promise((resolve2) => {
|
|
7096
|
+
release = resolve2;
|
|
6895
7097
|
});
|
|
6896
7098
|
record.tail = previous.catch(() => void 0).then(() => next);
|
|
6897
7099
|
await previous.catch(() => void 0);
|
|
@@ -6904,11 +7106,11 @@ var ResourceScheduler = class {
|
|
|
6904
7106
|
}
|
|
6905
7107
|
};
|
|
6906
7108
|
|
|
6907
|
-
//
|
|
7109
|
+
// vendor/computer-use-axi/src/browser-owner.ts
|
|
6908
7110
|
import { execFile } from "node:child_process";
|
|
6909
7111
|
import { rm } from "node:fs/promises";
|
|
6910
|
-
import
|
|
6911
|
-
import
|
|
7112
|
+
import os3 from "node:os";
|
|
7113
|
+
import path10 from "node:path";
|
|
6912
7114
|
async function requestBrowserClose(port) {
|
|
6913
7115
|
const response = await fetch(`http://127.0.0.1:${port}/json/version`, { signal: AbortSignal.timeout(500) });
|
|
6914
7116
|
const data = await response.json();
|
|
@@ -6916,7 +7118,7 @@ async function requestBrowserClose(port) {
|
|
|
6916
7118
|
const url = new URL(data.webSocketDebuggerUrl);
|
|
6917
7119
|
if (url.hostname !== "127.0.0.1" && url.hostname !== "localhost") throw new Error("Owned browser exposed a non-local debugger.");
|
|
6918
7120
|
if (url.port !== port) throw new Error("Owned browser debugger port changed.");
|
|
6919
|
-
await new Promise((
|
|
7121
|
+
await new Promise((resolve2) => {
|
|
6920
7122
|
const ws = new wrapper_default(url);
|
|
6921
7123
|
let done = false;
|
|
6922
7124
|
const finish = () => {
|
|
@@ -6924,7 +7126,7 @@ async function requestBrowserClose(port) {
|
|
|
6924
7126
|
done = true;
|
|
6925
7127
|
clearTimeout(timer);
|
|
6926
7128
|
ws.terminate();
|
|
6927
|
-
|
|
7129
|
+
resolve2();
|
|
6928
7130
|
};
|
|
6929
7131
|
const timer = setTimeout(finish, 700);
|
|
6930
7132
|
ws.on("open", () => ws.send(JSON.stringify({ id: 1, method: "Browser.close" })));
|
|
@@ -6935,15 +7137,15 @@ async function requestBrowserClose(port) {
|
|
|
6935
7137
|
}
|
|
6936
7138
|
async function waitForExit(child, timeoutMs) {
|
|
6937
7139
|
if (child.exitCode !== null || child.signalCode !== null) return true;
|
|
6938
|
-
return new Promise((
|
|
7140
|
+
return new Promise((resolve2) => {
|
|
6939
7141
|
const finish = () => {
|
|
6940
7142
|
clearTimeout(timer);
|
|
6941
7143
|
child.off("exit", finish);
|
|
6942
|
-
|
|
7144
|
+
resolve2(true);
|
|
6943
7145
|
};
|
|
6944
7146
|
const timer = setTimeout(() => {
|
|
6945
7147
|
child.off("exit", finish);
|
|
6946
|
-
|
|
7148
|
+
resolve2(false);
|
|
6947
7149
|
}, timeoutMs);
|
|
6948
7150
|
child.once("exit", finish);
|
|
6949
7151
|
});
|
|
@@ -6954,11 +7156,11 @@ async function releaseOwnedBrowser(child, port, profile) {
|
|
|
6954
7156
|
if (!await waitForExit(child, 700)) {
|
|
6955
7157
|
if (process.platform === "win32" && child.pid) {
|
|
6956
7158
|
const pid = child.pid;
|
|
6957
|
-
await new Promise((
|
|
7159
|
+
await new Promise((resolve2) => {
|
|
6958
7160
|
execFile("taskkill.exe", ["/PID", String(pid), "/T", "/F"], {
|
|
6959
7161
|
windowsHide: true,
|
|
6960
7162
|
timeout: 2e3
|
|
6961
|
-
}, () =>
|
|
7163
|
+
}, () => resolve2());
|
|
6962
7164
|
});
|
|
6963
7165
|
if (!await waitForExit(child, 1500)) {
|
|
6964
7166
|
try {
|
|
@@ -6979,8 +7181,8 @@ async function releaseOwnedBrowser(child, port, profile) {
|
|
|
6979
7181
|
}
|
|
6980
7182
|
}
|
|
6981
7183
|
if (profile) {
|
|
6982
|
-
const resolved =
|
|
6983
|
-
if (
|
|
7184
|
+
const resolved = path10.resolve(profile);
|
|
7185
|
+
if (path10.dirname(resolved) !== path10.resolve(os3.tmpdir()) || !/^pie-(chrome|helium)-cdp-/.test(path10.basename(resolved))) {
|
|
6984
7186
|
throw new Error("Refusing to remove a profile outside the owned temporary browser directory.");
|
|
6985
7187
|
}
|
|
6986
7188
|
await rm(resolved, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
|
|
@@ -6992,7 +7194,7 @@ async function releaseOwnedBrowserState(owner) {
|
|
|
6992
7194
|
owner.managedBrowserProfileDir = void 0;
|
|
6993
7195
|
}
|
|
6994
7196
|
|
|
6995
|
-
//
|
|
7197
|
+
// vendor/computer-use-axi/src/root-selection.ts
|
|
6996
7198
|
function scoreWindow(window) {
|
|
6997
7199
|
let score = 0;
|
|
6998
7200
|
if (window.isModal) score += 180;
|
|
@@ -7011,18 +7213,21 @@ function shouldPreferForegroundModalWindow(current, candidate) {
|
|
|
7011
7213
|
return candidateIsInFront && scoreWindow(candidate) >= scoreWindow(current);
|
|
7012
7214
|
}
|
|
7013
7215
|
|
|
7014
|
-
//
|
|
7216
|
+
// vendor/computer-use-axi/src/state.ts
|
|
7015
7217
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7016
7218
|
var SavedStates = class {
|
|
7017
|
-
store
|
|
7219
|
+
store;
|
|
7018
7220
|
operations = new AsyncLocalStorage();
|
|
7221
|
+
constructor(store = new StateStore(128)) {
|
|
7222
|
+
this.store = store;
|
|
7223
|
+
}
|
|
7019
7224
|
current() {
|
|
7020
7225
|
const state = this.operations.getStore();
|
|
7021
7226
|
if (!state) throw new Error("Computer-use operation state is unavailable.");
|
|
7022
7227
|
return state;
|
|
7023
7228
|
}
|
|
7024
|
-
get(
|
|
7025
|
-
return this.store.get(
|
|
7229
|
+
get(stateId) {
|
|
7230
|
+
return this.store.get(stateId);
|
|
7026
7231
|
}
|
|
7027
7232
|
set(record) {
|
|
7028
7233
|
this.store.set(record);
|
|
@@ -7090,7 +7295,7 @@ var SavedStates = class {
|
|
|
7090
7295
|
}
|
|
7091
7296
|
};
|
|
7092
7297
|
|
|
7093
|
-
//
|
|
7298
|
+
// vendor/computer-use-axi/src/view.ts
|
|
7094
7299
|
function numericRef(ref) {
|
|
7095
7300
|
const match = /^@e(\d+)$/.exec(ref);
|
|
7096
7301
|
return match ? Number(match[1]) : 0;
|
|
@@ -7226,7 +7431,7 @@ function renderChanges(changes) {
|
|
|
7226
7431
|
}).join("\n");
|
|
7227
7432
|
}
|
|
7228
7433
|
|
|
7229
|
-
//
|
|
7434
|
+
// vendor/computer-use-axi/src/bridge.ts
|
|
7230
7435
|
var MISSING_TARGET_ERROR = "No current controlled window. Call observe_ui first to choose a target window.";
|
|
7231
7436
|
var CURRENT_TARGET_GONE_ERROR = "The current controlled window is no longer available. Call observe_ui to choose a new target window.";
|
|
7232
7437
|
var COMMAND_TIMEOUT_MS5 = 15e3;
|
|
@@ -7248,6 +7453,69 @@ var runtimeState = {
|
|
|
7248
7453
|
var savedStates = new SavedStates();
|
|
7249
7454
|
var resourceScheduler = new ResourceScheduler();
|
|
7250
7455
|
var shutdownInFlight;
|
|
7456
|
+
var diskPersistence = false;
|
|
7457
|
+
function enableDiskPersistence(env = process.env) {
|
|
7458
|
+
if (diskPersistence) return;
|
|
7459
|
+
diskPersistence = true;
|
|
7460
|
+
const store = new DiskStateStore(128, env, stripLookImageForDisk);
|
|
7461
|
+
savedStates = new SavedStates(store);
|
|
7462
|
+
resourceScheduler = new ResourceScheduler({ onEpochChange: () => persistRuntimeBridgeState() });
|
|
7463
|
+
const snapshot = loadRuntimeStateSnapshot(env);
|
|
7464
|
+
if (!snapshot) return;
|
|
7465
|
+
for (const record of snapshot.windowRefs) {
|
|
7466
|
+
const stored = record;
|
|
7467
|
+
runtimeState.windowRefs.set(stored.ref, stored);
|
|
7468
|
+
runtimeState.windowRefByIdentity.set(windowRecordIdentity(stored), stored.ref);
|
|
7469
|
+
}
|
|
7470
|
+
for (const entry of snapshot.browserContexts) {
|
|
7471
|
+
runtimeState.browserContextByRoot.set(entry.root, entry.contextId);
|
|
7472
|
+
runtimeState.browserRootByContext.set(entry.contextId, entry.root);
|
|
7473
|
+
}
|
|
7474
|
+
runtimeState.nextRootRefIndex = Math.max(runtimeState.nextRootRefIndex, Math.trunc(snapshot.nextRootRefIndex) || 1);
|
|
7475
|
+
for (const entry of snapshot.epochs) resourceScheduler.restoreEpoch(entry.resourceKey, entry.epoch);
|
|
7476
|
+
if (snapshot.managedBrowser && /^\d+$/.test(snapshot.managedBrowser.cdpPort)) {
|
|
7477
|
+
runtimeState.managedBrowserCdpPort = snapshot.managedBrowser.cdpPort;
|
|
7478
|
+
runtimeState.managedBrowserPid = snapshot.managedBrowser.pid;
|
|
7479
|
+
runtimeState.managedBrowserProfileDir = snapshot.managedBrowser.profileDir;
|
|
7480
|
+
}
|
|
7481
|
+
}
|
|
7482
|
+
async function attachPersistedBrowser() {
|
|
7483
|
+
const port = runtimeState.managedBrowserCdpPort;
|
|
7484
|
+
if (!port || !/^\d+$/.test(port)) return false;
|
|
7485
|
+
try {
|
|
7486
|
+
const response = await fetch(`http://127.0.0.1:${port}/json/version`, { signal: AbortSignal.timeout(2e3) });
|
|
7487
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
7488
|
+
} catch {
|
|
7489
|
+
runtimeState.managedBrowserCdpPort = void 0;
|
|
7490
|
+
runtimeState.managedBrowserPid = void 0;
|
|
7491
|
+
runtimeState.managedBrowserProfileDir = void 0;
|
|
7492
|
+
if (runtimeState.previousCdpPort === void 0) delete process.env.PIE_COMPUTER_USE_CDP_PORT;
|
|
7493
|
+
persistRuntimeBridgeState();
|
|
7494
|
+
return false;
|
|
7495
|
+
}
|
|
7496
|
+
process.env.PIE_COMPUTER_USE_CDP_PORT = port;
|
|
7497
|
+
return true;
|
|
7498
|
+
}
|
|
7499
|
+
function stripLookImageForDisk(value) {
|
|
7500
|
+
if (value.kind !== "desktop" || !value.look.image) return value;
|
|
7501
|
+
return { ...value, look: { ...value.look, image: void 0 } };
|
|
7502
|
+
}
|
|
7503
|
+
function snapshotRuntimeBridgeState() {
|
|
7504
|
+
return {
|
|
7505
|
+
windowRefs: [...runtimeState.windowRefs.values()],
|
|
7506
|
+
browserContexts: [...runtimeState.browserContextByRoot.entries()].map(([root, contextId]) => ({ root, contextId })),
|
|
7507
|
+
nextRootRefIndex: runtimeState.nextRootRefIndex,
|
|
7508
|
+
epochs: resourceScheduler.epochs().map(([resourceKey, epoch]) => ({ resourceKey, epoch })),
|
|
7509
|
+
...runtimeState.managedBrowserCdpPort && runtimeState.managedBrowserPid ? { managedBrowser: { cdpPort: runtimeState.managedBrowserCdpPort, pid: runtimeState.managedBrowserPid, profileDir: runtimeState.managedBrowserProfileDir } } : {}
|
|
7510
|
+
};
|
|
7511
|
+
}
|
|
7512
|
+
function persistRuntimeBridgeState() {
|
|
7513
|
+
if (!diskPersistence) return;
|
|
7514
|
+
try {
|
|
7515
|
+
persistRuntimeStateSnapshot(snapshotRuntimeBridgeState());
|
|
7516
|
+
} catch {
|
|
7517
|
+
}
|
|
7518
|
+
}
|
|
7251
7519
|
function operationState() {
|
|
7252
7520
|
return savedStates.current();
|
|
7253
7521
|
}
|
|
@@ -7260,47 +7528,6 @@ function persistOperation(state) {
|
|
|
7260
7528
|
const epoch = state.epoch ?? resourceScheduler.epoch(resourceKey);
|
|
7261
7529
|
savedStates.saveDesktop(state, resourceKey, epoch);
|
|
7262
7530
|
}
|
|
7263
|
-
function shutdownComputerUseSession() {
|
|
7264
|
-
if (shutdownInFlight) return shutdownInFlight;
|
|
7265
|
-
shutdownInFlight = releaseComputerUseSession().finally(() => {
|
|
7266
|
-
shutdownInFlight = void 0;
|
|
7267
|
-
});
|
|
7268
|
-
return shutdownInFlight;
|
|
7269
|
-
}
|
|
7270
|
-
async function releaseComputerUseSession() {
|
|
7271
|
-
const drain = resourceScheduler.close();
|
|
7272
|
-
const failures = [];
|
|
7273
|
-
const attempt = (step, work) => work().catch((error) => {
|
|
7274
|
-
failures.push(error instanceof Error ? new Error(`${step}: ${error.message}`) : error);
|
|
7275
|
-
});
|
|
7276
|
-
await attempt("disconnect CDP", () => disconnectCdp());
|
|
7277
|
-
await attempt("platform shutdown", async () => {
|
|
7278
|
-
await currentPlatformBackend.shutdown?.();
|
|
7279
|
-
});
|
|
7280
|
-
await attempt("drain scheduler", () => drain);
|
|
7281
|
-
await attempt("release owned browser", () => releaseOwnedBrowserState(runtimeState));
|
|
7282
|
-
if (runtimeState.managedBrowserCdpPort && process.env.PIE_COMPUTER_USE_CDP_PORT === runtimeState.managedBrowserCdpPort) {
|
|
7283
|
-
if (runtimeState.previousCdpPort === void 0) delete process.env.PIE_COMPUTER_USE_CDP_PORT;
|
|
7284
|
-
else process.env.PIE_COMPUTER_USE_CDP_PORT = runtimeState.previousCdpPort;
|
|
7285
|
-
}
|
|
7286
|
-
runtimeState.previousCdpPort = void 0;
|
|
7287
|
-
if (runtimeState.managedBrowser === void 0) {
|
|
7288
|
-
runtimeState.managedBrowserCdpPort = void 0;
|
|
7289
|
-
}
|
|
7290
|
-
savedStates.clear();
|
|
7291
|
-
clearStoredOutputs();
|
|
7292
|
-
runtimeState.windowRefs.clear();
|
|
7293
|
-
runtimeState.windowRefByIdentity.clear();
|
|
7294
|
-
runtimeState.browserRootByContext.clear();
|
|
7295
|
-
runtimeState.browserContextByRoot.clear();
|
|
7296
|
-
runtimeState.nextRootRefIndex = 1;
|
|
7297
|
-
runtimeState.permissionStatus = void 0;
|
|
7298
|
-
runtimeState.helperDiagnostics = void 0;
|
|
7299
|
-
runtimeState.lastPermissionCheckAt = 0;
|
|
7300
|
-
resourceScheduler = new ResourceScheduler();
|
|
7301
|
-
if (failures.length === 1) throw failures[0];
|
|
7302
|
-
if (failures.length > 1) throw new AggregateError(failures, "computer-use session release had partial failures (state was reset)");
|
|
7303
|
-
}
|
|
7304
7531
|
function currentRuntimeMode() {
|
|
7305
7532
|
return isHeadlessMode() ? "stealth" : "default";
|
|
7306
7533
|
}
|
|
@@ -7341,10 +7568,10 @@ function throwIfAborted3(signal) {
|
|
|
7341
7568
|
async function sleep2(ms, signal) {
|
|
7342
7569
|
if (ms <= 0) return;
|
|
7343
7570
|
throwIfAborted3(signal);
|
|
7344
|
-
await new Promise((
|
|
7571
|
+
await new Promise((resolve2, reject) => {
|
|
7345
7572
|
const timer = setTimeout(() => {
|
|
7346
7573
|
cleanup();
|
|
7347
|
-
|
|
7574
|
+
resolve2();
|
|
7348
7575
|
}, ms);
|
|
7349
7576
|
const onAbort = () => {
|
|
7350
7577
|
cleanup();
|
|
@@ -7376,21 +7603,18 @@ function trimOrUndefined(value) {
|
|
|
7376
7603
|
function normalizeText2(value) {
|
|
7377
7604
|
return (value ?? "").trim().toLowerCase();
|
|
7378
7605
|
}
|
|
7379
|
-
function toBoolean3(value) {
|
|
7380
|
-
return value === true;
|
|
7381
|
-
}
|
|
7382
7606
|
function outlineNodeCenter(node) {
|
|
7383
7607
|
if (!node.rect) {
|
|
7384
7608
|
throw new Error(`Outline ref '${node.ref}' has no full-look coordinates after scoped expansion. Re-observe for coordinates.`);
|
|
7385
7609
|
}
|
|
7386
7610
|
return { x: node.rect.x + node.rect.w / 2, y: node.rect.y + node.rect.h / 2 };
|
|
7387
7611
|
}
|
|
7388
|
-
function validateStateId(
|
|
7612
|
+
function validateStateId(stateId) {
|
|
7389
7613
|
const state = operationState();
|
|
7390
7614
|
if (!state.currentCapture) {
|
|
7391
7615
|
throw new Error("No observation state is available. Call observe_ui first.");
|
|
7392
7616
|
}
|
|
7393
|
-
const supplied =
|
|
7617
|
+
const supplied = stateId;
|
|
7394
7618
|
if (supplied && state.currentCapture.stateId !== supplied) {
|
|
7395
7619
|
throw new Error(
|
|
7396
7620
|
`Stale state '${supplied}'. The active operation state is '${state.currentCapture.stateId}'. Observe the root again and retry.`
|
|
@@ -7550,6 +7774,7 @@ function storeWindowRef(record) {
|
|
|
7550
7774
|
const stored = { ...record, ref };
|
|
7551
7775
|
runtimeState.windowRefByIdentity.set(identity, ref);
|
|
7552
7776
|
runtimeState.windowRefs.set(ref, stored);
|
|
7777
|
+
persistRuntimeBridgeState();
|
|
7553
7778
|
return stored;
|
|
7554
7779
|
}
|
|
7555
7780
|
function storeBrowserRootRef(contextId) {
|
|
@@ -7558,6 +7783,7 @@ function storeBrowserRootRef(contextId) {
|
|
|
7558
7783
|
const ref = `@r${runtimeState.nextRootRefIndex++}`;
|
|
7559
7784
|
runtimeState.browserRootByContext.set(contextId, ref);
|
|
7560
7785
|
runtimeState.browserContextByRoot.set(ref, contextId);
|
|
7786
|
+
persistRuntimeBridgeState();
|
|
7561
7787
|
return ref;
|
|
7562
7788
|
}
|
|
7563
7789
|
function storeWindowRefForTarget(target) {
|
|
@@ -7792,7 +8018,7 @@ async function ensureTargetWindowId(target, signal) {
|
|
|
7792
8018
|
}
|
|
7793
8019
|
function captureForLook(look) {
|
|
7794
8020
|
return {
|
|
7795
|
-
stateId:
|
|
8021
|
+
stateId: randomUUID6(),
|
|
7796
8022
|
width: look.image?.width ?? 0,
|
|
7797
8023
|
height: look.image?.height ?? 0,
|
|
7798
8024
|
scaleFactor: look.window.scaleFactor,
|
|
@@ -7965,6 +8191,7 @@ function modelRefForRootDelta(delta) {
|
|
|
7965
8191
|
};
|
|
7966
8192
|
runtimeState.windowRefs.set(ref, record);
|
|
7967
8193
|
runtimeState.windowRefByIdentity.set(windowRecordIdentity(record), ref);
|
|
8194
|
+
persistRuntimeBridgeState();
|
|
7968
8195
|
return ref;
|
|
7969
8196
|
}
|
|
7970
8197
|
function executionTraceFromAct(result, policy = currentDeliveryPolicy()) {
|
|
@@ -8403,7 +8630,7 @@ function sameRootIdentity(a, b) {
|
|
|
8403
8630
|
}
|
|
8404
8631
|
async function performObserve(params, signal) {
|
|
8405
8632
|
const requestedRoot = typeof params.root === "string" ? params.root : void 0;
|
|
8406
|
-
if (requestedRoot && !/^@r\d+$/.test(requestedRoot)) throw new Error("
|
|
8633
|
+
if (requestedRoot && !/^@r\d+$/.test(requestedRoot)) throw new Error("observe --root must be an exact @r ref issued by roots.");
|
|
8407
8634
|
const browserContextId = requestedRoot ? runtimeState.browserContextByRoot.get(requestedRoot) : void 0;
|
|
8408
8635
|
if (isBrowserContextId(browserContextId)) {
|
|
8409
8636
|
const targetId = browserContextId.slice(BROWSER_CONTEXT_PREFIX.length);
|
|
@@ -8437,8 +8664,8 @@ async function performObserve(params, signal) {
|
|
|
8437
8664
|
const summary = `Observed ${mode} ${captureResult.target.windowRef ? `${captureResult.target.windowRef} ` : ""}${captureResult.target.appName} \u2014 ${captureResult.target.windowTitle}. Returned the latest outline state.`;
|
|
8438
8665
|
return await buildToolResult("observe_ui", summary, captureResult, executionTrace("look", "stealth"), signal, imageMode);
|
|
8439
8666
|
}
|
|
8440
|
-
function currentOutlineOrThrow(
|
|
8441
|
-
validateStateId(
|
|
8667
|
+
function currentOutlineOrThrow(stateId) {
|
|
8668
|
+
validateStateId(stateId);
|
|
8442
8669
|
const outline = operationState().currentOutline;
|
|
8443
8670
|
if (!outline) throw new Error("No observation outline is available. Call observe_ui first.");
|
|
8444
8671
|
return outline;
|
|
@@ -8809,8 +9036,8 @@ async function performBrowserTransaction(params, actions, signal) {
|
|
|
8809
9036
|
return await refreshBrowserSnapshot(contextId, "act_ui", baseView);
|
|
8810
9037
|
});
|
|
8811
9038
|
}
|
|
8812
|
-
function normalizeActionPath(
|
|
8813
|
-
return (
|
|
9039
|
+
function normalizeActionPath(path12) {
|
|
9040
|
+
return (path12 ?? []).map((point) => Array.isArray(point) ? { x: toFiniteNumber(point[0], 0), y: toFiniteNumber(point[1], 0) } : { x: toFiniteNumber(point.x, 0), y: toFiniteNumber(point.y, 0) });
|
|
8814
9041
|
}
|
|
8815
9042
|
function validateActionTarget(action) {
|
|
8816
9043
|
const hasRef = Boolean(trimOrUndefined(action.ref));
|
|
@@ -8827,7 +9054,7 @@ function validateActionTarget(action) {
|
|
|
8827
9054
|
}
|
|
8828
9055
|
async function performAct(params, signal) {
|
|
8829
9056
|
const actions = Array.isArray(params.actions) ? params.actions : [];
|
|
8830
|
-
if (actions.length === 0) throw new Error("
|
|
9057
|
+
if (actions.length === 0) throw new Error("act --actions must contain at least one action.");
|
|
8831
9058
|
if (actions.length > 20) throw new Error("act_ui supports at most 20 actions per transaction.");
|
|
8832
9059
|
for (const action of actions) validateActionTarget(action);
|
|
8833
9060
|
if (operationState().contextId) return await performBrowserTransaction(params, actions, signal);
|
|
@@ -8836,25 +9063,25 @@ async function performAct(params, signal) {
|
|
|
8836
9063
|
function managedBrowserExecutableCandidates(browser) {
|
|
8837
9064
|
const overrideName = browser === "helium" ? "PIE_COMPUTER_USE_HELIUM_EXECUTABLE" : "PIE_COMPUTER_USE_CHROME_EXECUTABLE";
|
|
8838
9065
|
const override = trimOrUndefined(process.env[overrideName]);
|
|
8839
|
-
if (override) return [
|
|
9066
|
+
if (override) return [path11.resolve(override)];
|
|
8840
9067
|
const platformCandidates = process.platform === "darwin" ? browser === "helium" ? [
|
|
8841
9068
|
"/Applications/Helium.app/Contents/MacOS/Helium",
|
|
8842
|
-
|
|
9069
|
+
path11.join(os4.homedir(), "Applications", "Helium.app", "Contents", "MacOS", "Helium")
|
|
8843
9070
|
] : [
|
|
8844
9071
|
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
8845
|
-
|
|
9072
|
+
path11.join(os4.homedir(), "Applications", "Google Chrome.app", "Contents", "MacOS", "Google Chrome")
|
|
8846
9073
|
] : process.platform === "win32" ? browser === "helium" ? [
|
|
8847
|
-
process.env.LOCALAPPDATA &&
|
|
8848
|
-
process.env.PROGRAMFILES &&
|
|
9074
|
+
process.env.LOCALAPPDATA && path11.join(process.env.LOCALAPPDATA, "Helium", "Application", "helium.exe"),
|
|
9075
|
+
process.env.PROGRAMFILES && path11.join(process.env.PROGRAMFILES, "Helium", "Application", "helium.exe")
|
|
8849
9076
|
] : [
|
|
8850
|
-
process.env.LOCALAPPDATA &&
|
|
8851
|
-
process.env.PROGRAMFILES &&
|
|
8852
|
-
process.env["PROGRAMFILES(X86)"] &&
|
|
9077
|
+
process.env.LOCALAPPDATA && path11.join(process.env.LOCALAPPDATA, "Google", "Chrome", "Application", "chrome.exe"),
|
|
9078
|
+
process.env.PROGRAMFILES && path11.join(process.env.PROGRAMFILES, "Google", "Chrome", "Application", "chrome.exe"),
|
|
9079
|
+
process.env["PROGRAMFILES(X86)"] && path11.join(process.env["PROGRAMFILES(X86)"], "Google", "Chrome", "Application", "chrome.exe")
|
|
8853
9080
|
] : browser === "helium" ? [
|
|
8854
9081
|
"/usr/bin/helium",
|
|
8855
9082
|
"/usr/bin/helium-browser",
|
|
8856
9083
|
"/opt/helium/chrome",
|
|
8857
|
-
|
|
9084
|
+
path11.join(os4.homedir(), ".local", "helium", "chrome")
|
|
8858
9085
|
] : [
|
|
8859
9086
|
"/usr/bin/google-chrome",
|
|
8860
9087
|
"/usr/bin/google-chrome-stable",
|
|
@@ -8863,7 +9090,7 @@ function managedBrowserExecutableCandidates(browser) {
|
|
|
8863
9090
|
"/snap/bin/chromium"
|
|
8864
9091
|
];
|
|
8865
9092
|
const pathNames = browser === "helium" ? process.platform === "win32" ? ["helium.exe"] : ["helium", "helium-browser"] : process.platform === "win32" ? ["chrome.exe"] : ["google-chrome", "google-chrome-stable", "chromium", "chromium-browser"];
|
|
8866
|
-
const pathCandidates = (process.env.PATH ?? "").split(
|
|
9093
|
+
const pathCandidates = (process.env.PATH ?? "").split(path11.delimiter).filter(Boolean).flatMap((directory) => pathNames.map((name) => path11.join(directory, name)));
|
|
8867
9094
|
return [.../* @__PURE__ */ new Set([...platformCandidates.filter((candidate) => Boolean(candidate)), ...pathCandidates])];
|
|
8868
9095
|
}
|
|
8869
9096
|
async function managedBrowserExecutable(browser) {
|
|
@@ -8882,13 +9109,13 @@ async function managedBrowserExecutable(browser) {
|
|
|
8882
9109
|
throw new Error(`${browser} executable was not found. Set ${overrideName} to its absolute path.`);
|
|
8883
9110
|
}
|
|
8884
9111
|
function freeTcpPort() {
|
|
8885
|
-
return new Promise((
|
|
9112
|
+
return new Promise((resolve2, reject) => {
|
|
8886
9113
|
const server = net2.createServer();
|
|
8887
9114
|
server.on("error", reject);
|
|
8888
9115
|
server.listen(0, "127.0.0.1", () => {
|
|
8889
9116
|
const address = server.address();
|
|
8890
9117
|
const port = typeof address === "object" && address ? address.port : 0;
|
|
8891
|
-
server.close(() => port > 0 ?
|
|
9118
|
+
server.close(() => port > 0 ? resolve2(port) : reject(new Error("Could not allocate a local CDP port.")));
|
|
8892
9119
|
});
|
|
8893
9120
|
});
|
|
8894
9121
|
}
|
|
@@ -8914,7 +9141,7 @@ async function performLaunchBrowser(params, signal) {
|
|
|
8914
9141
|
const url = requestedUrl ?? "about:blank";
|
|
8915
9142
|
await disconnectCdp();
|
|
8916
9143
|
await releaseOwnedBrowserState(runtimeState);
|
|
8917
|
-
const profileDir =
|
|
9144
|
+
const profileDir = mkdtempSync(path11.join(os4.tmpdir(), `pie-${browser}-cdp-`));
|
|
8918
9145
|
const args = [
|
|
8919
9146
|
`--remote-debugging-port=${port}`,
|
|
8920
9147
|
`--user-data-dir=${profileDir}`,
|
|
@@ -8925,11 +9152,20 @@ async function performLaunchBrowser(params, signal) {
|
|
|
8925
9152
|
if (runtimeState.previousCdpPort === void 0 && runtimeState.managedBrowserCdpPort === void 0) {
|
|
8926
9153
|
runtimeState.previousCdpPort = process.env.PIE_COMPUTER_USE_CDP_PORT;
|
|
8927
9154
|
}
|
|
8928
|
-
const managedBrowser = spawn4(executable, args, { stdio: "ignore", detached:
|
|
9155
|
+
const managedBrowser = spawn4(executable, args, { stdio: "ignore", detached: true });
|
|
8929
9156
|
managedBrowser.unref();
|
|
9157
|
+
const stalePid = runtimeState.managedBrowserPid;
|
|
9158
|
+
if (stalePid !== void 0 && stalePid !== managedBrowser.pid) {
|
|
9159
|
+
try {
|
|
9160
|
+
process.kill(stalePid, "SIGTERM");
|
|
9161
|
+
} catch {
|
|
9162
|
+
}
|
|
9163
|
+
}
|
|
8930
9164
|
runtimeState.managedBrowser = managedBrowser;
|
|
8931
9165
|
runtimeState.managedBrowserCdpPort = String(port);
|
|
9166
|
+
runtimeState.managedBrowserPid = managedBrowser.pid;
|
|
8932
9167
|
runtimeState.managedBrowserProfileDir = profileDir;
|
|
9168
|
+
persistRuntimeBridgeState();
|
|
8933
9169
|
process.env.PIE_COMPUTER_USE_CDP_PORT = String(port);
|
|
8934
9170
|
try {
|
|
8935
9171
|
await waitForCdpPort(port, signal);
|
|
@@ -9031,402 +9267,278 @@ var executeAct = makeToolExecutor("act_ui", performAct);
|
|
|
9031
9267
|
var executeNavigateBrowser = makeToolExecutor("navigate_browser", performNavigateBrowser);
|
|
9032
9268
|
var executeEvaluateBrowser = makeToolExecutor("evaluate_browser", performEvaluateBrowser);
|
|
9033
9269
|
var executeLaunchBrowser = makeToolExecutor("launch_browser", performLaunchBrowser);
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
|
|
9270
|
+
|
|
9271
|
+
// vendor/computer-use-axi/src/cli.ts
|
|
9272
|
+
var USAGE = `computer-use-axi \u2014 desktop & browser UI automation
|
|
9273
|
+
|
|
9274
|
+
Lifecycle: roots -> observe (returns stateId) -> search/expand/inspect -> act.
|
|
9275
|
+
@r refs come from roots; @e refs + stateId come from observe/search;
|
|
9276
|
+
@o refs continue long truncated output via read.
|
|
9277
|
+
|
|
9278
|
+
Commands:
|
|
9279
|
+
roots [--text T] [--app A] [--bundle-id B] [--pid N] [--kind K]
|
|
9280
|
+
observe [--root @rN] [--mode semantic|visual|fused]
|
|
9281
|
+
search --state S (--text T | --role R | --capability C)
|
|
9282
|
+
expand --state S --ref @eN [--depth 1-8]
|
|
9283
|
+
inspect --state S --ref @eN
|
|
9284
|
+
read --ref @oN|--eN [--offset BYTES] [--state S]
|
|
9285
|
+
wait --state S (--text T | --role R | --ref @eN) [--until present|absent]
|
|
9286
|
+
[--scope-ref @eN] [--value V] [--timeout-ms MS]
|
|
9287
|
+
act --state S --actions '<JSON array>' [--expect '<JSON object>']
|
|
9288
|
+
browser launch [--url U]
|
|
9289
|
+
browser navigate --state S --url U
|
|
9290
|
+
browser eval --state S --expr '<JavaScript>'
|
|
9291
|
+
|
|
9292
|
+
Options:
|
|
9293
|
+
--json Print { content, details, isError } as JSON
|
|
9294
|
+
--help, -h Show this help
|
|
9295
|
+
|
|
9296
|
+
Examples:
|
|
9297
|
+
computer-use-axi roots --app Finder
|
|
9298
|
+
computer-use-axi observe --root @r1
|
|
9299
|
+
computer-use-axi search --state S1 --text Save
|
|
9300
|
+
computer-use-axi act --state S1 --actions '[{"action":"press","ref":"@e12"}]'
|
|
9301
|
+
computer-use-axi read --ref @o1 --offset 16384`;
|
|
9302
|
+
var FLAG_ALIASES = {
|
|
9303
|
+
"-h": "--help",
|
|
9304
|
+
"--state-id": "--state",
|
|
9305
|
+
"--window": "--root",
|
|
9306
|
+
"--capability-filter": "--capability",
|
|
9307
|
+
"--scope": "--scope-ref",
|
|
9308
|
+
"--timeout": "--timeout-ms",
|
|
9309
|
+
"--expression": "--expr"
|
|
9310
|
+
};
|
|
9311
|
+
function parseArgs(argv) {
|
|
9312
|
+
const rest = [];
|
|
9313
|
+
const flags = /* @__PURE__ */ new Map();
|
|
9314
|
+
let command = "";
|
|
9315
|
+
let json = false;
|
|
9316
|
+
let help = false;
|
|
9317
|
+
const booleanFlags = /* @__PURE__ */ new Set(["--json", "--help"]);
|
|
9318
|
+
for (let i = 0; i < argv.length; i++) {
|
|
9319
|
+
const token = argv[i];
|
|
9320
|
+
const alias = FLAG_ALIASES[token] ?? token;
|
|
9321
|
+
if (!alias.startsWith("-")) {
|
|
9322
|
+
if (!command) command = token;
|
|
9323
|
+
else rest.push(token);
|
|
9073
9324
|
continue;
|
|
9074
9325
|
}
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
if (!app) continue;
|
|
9079
|
-
if (!Number.isFinite(details.target.pid) || !Number.isFinite(details.target.windowId)) continue;
|
|
9080
|
-
if (typeof details.capture.stateId !== "string") continue;
|
|
9081
|
-
const target = {
|
|
9082
|
-
appName: app,
|
|
9083
|
-
bundleId: details.target.bundleId,
|
|
9084
|
-
pid: Math.trunc(details.target.pid),
|
|
9085
|
-
windowTitle: details.target.windowTitle ?? "(untitled)",
|
|
9086
|
-
windowId: Math.trunc(details.target.windowId),
|
|
9087
|
-
windowRef: typeof details.target.windowRef === "string" ? details.target.windowRef : void 0,
|
|
9088
|
-
nativeWindowRef: typeof details.target.nativeWindowRef === "string" ? details.target.nativeWindowRef : void 0
|
|
9089
|
-
};
|
|
9090
|
-
const resourceKey = desktopResourceKey(target);
|
|
9091
|
-
if (restoredResources.has(resourceKey)) continue;
|
|
9092
|
-
const capture = {
|
|
9093
|
-
stateId: details.capture.stateId,
|
|
9094
|
-
width: Math.max(1, Math.trunc(toFiniteNumber(details.capture.width, 1))),
|
|
9095
|
-
height: Math.max(1, Math.trunc(toFiniteNumber(details.capture.height, 1))),
|
|
9096
|
-
scaleFactor: Math.max(1, toFiniteNumber(details.capture.scaleFactor, 1)),
|
|
9097
|
-
timestamp: Number.isFinite(details.capture.timestamp) ? details.capture.timestamp : Date.now()
|
|
9098
|
-
};
|
|
9099
|
-
if (details.outline?.root && typeof details.outline.lookId === "string") {
|
|
9100
|
-
const epoch = 0;
|
|
9101
|
-
resourceScheduler.restoreEpoch(resourceKey, epoch);
|
|
9102
|
-
savedStates.set({
|
|
9103
|
-
stateId: capture.stateId,
|
|
9104
|
-
resourceKey,
|
|
9105
|
-
epoch,
|
|
9106
|
-
value: {
|
|
9107
|
-
kind: "desktop",
|
|
9108
|
-
target,
|
|
9109
|
-
capture,
|
|
9110
|
-
outline: details.outline,
|
|
9111
|
-
look: {
|
|
9112
|
-
lookId: details.outline.lookId,
|
|
9113
|
-
capturedAt: details.capture.timestamp / 1e3,
|
|
9114
|
-
window: {
|
|
9115
|
-
windowId: Math.trunc(details.target.windowId),
|
|
9116
|
-
framePoints: { x: 0, y: 0, w: details.capture.width, h: details.capture.height },
|
|
9117
|
-
scaleFactor: details.capture.scaleFactor,
|
|
9118
|
-
isModal: false,
|
|
9119
|
-
role: "",
|
|
9120
|
-
subrole: ""
|
|
9121
|
-
},
|
|
9122
|
-
image: { jpegBase64: "", width: details.capture.width, height: details.capture.height },
|
|
9123
|
-
timings: {}
|
|
9124
|
-
},
|
|
9125
|
-
note: details.note
|
|
9126
|
-
}
|
|
9127
|
-
});
|
|
9128
|
-
restoredResources.add(resourceKey);
|
|
9326
|
+
if (alias === "--json") {
|
|
9327
|
+
json = true;
|
|
9328
|
+
continue;
|
|
9129
9329
|
}
|
|
9330
|
+
if (alias === "--help") {
|
|
9331
|
+
help = true;
|
|
9332
|
+
continue;
|
|
9333
|
+
}
|
|
9334
|
+
let key = alias;
|
|
9335
|
+
let value;
|
|
9336
|
+
const eq = alias.indexOf("=");
|
|
9337
|
+
if (eq >= 0) {
|
|
9338
|
+
key = alias.slice(0, eq);
|
|
9339
|
+
value = alias.slice(eq + 1);
|
|
9340
|
+
}
|
|
9341
|
+
if (!booleanFlags.has(key) && value === void 0) {
|
|
9342
|
+
const next = argv[i + 1];
|
|
9343
|
+
if (next !== void 0 && !next.startsWith("-")) {
|
|
9344
|
+
value = next;
|
|
9345
|
+
i += 1;
|
|
9346
|
+
}
|
|
9347
|
+
}
|
|
9348
|
+
flags.set(key, value ?? "");
|
|
9130
9349
|
}
|
|
9350
|
+
return { command, flags, json, help, rest };
|
|
9131
9351
|
}
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
var mouseButton2 = Type.Optional(Type.Union([Type.Literal("left"), Type.Literal("right"), Type.Literal("middle")]));
|
|
9137
|
-
var clickByRef = Type.Object({ action: Type.Literal("click"), ref: Type.String(), button: mouseButton2, clickCount: Type.Optional(Type.Number({ minimum: 1, maximum: 3 })) });
|
|
9138
|
-
var clickByPoint = Type.Object({ action: Type.Literal("click"), ...point, button: mouseButton2, clickCount: Type.Optional(Type.Number({ minimum: 1, maximum: 3 })) });
|
|
9139
|
-
var uiAction = Type.Union([
|
|
9140
|
-
Type.Object({ action: Type.Literal("press"), ref: Type.String({ description: "Actionable outline ref" }) }),
|
|
9141
|
-
clickByRef,
|
|
9142
|
-
clickByPoint,
|
|
9143
|
-
Type.Object({ action: Type.Literal("setText"), ref: Type.String({ description: "Editable outline ref" }), text: Type.String() }),
|
|
9144
|
-
Type.Object({ action: Type.Literal("typeText"), ref: Type.Optional(Type.String({ description: "Omit after a click to type into the focus established by that click" })), text: Type.String() }),
|
|
9145
|
-
Type.Object({ action: Type.Literal("keypress"), ref: Type.Optional(Type.String({ description: "Omit to send keys to the focused control" })), keys: Type.Array(Type.String(), { minItems: 1 }) }),
|
|
9146
|
-
Type.Object({ action: Type.Literal("scroll"), ref: Type.Optional(Type.String()), scrollX: Type.Optional(Type.Number()), scrollY: Type.Optional(Type.Number()) }),
|
|
9147
|
-
Type.Object({ action: Type.Literal("drag"), path: Type.Array(Type.Object(point), { minItems: 2 }) }),
|
|
9148
|
-
Type.Object({ action: Type.Literal("moveMouse"), ...point })
|
|
9149
|
-
]);
|
|
9150
|
-
var conditionProperties = {
|
|
9151
|
-
ref: Type.Optional(Type.String({ description: "Specific @e ref to test", maxLength: 128 })),
|
|
9152
|
-
scopeRef: Type.Optional(Type.String({ description: "Restrict matching to this @e subtree", maxLength: 128 })),
|
|
9153
|
-
text: Type.Optional(Type.String({ description: "Text that must match", maxLength: 512 })),
|
|
9154
|
-
role: Type.Optional(Type.String({ description: "Exact normalized role", maxLength: 128 })),
|
|
9155
|
-
value: Type.Optional(Type.String({ description: "Exact normalized value; normally pair with ref" })),
|
|
9156
|
-
until: Type.Optional(Type.Union([Type.Literal("present"), Type.Literal("absent")], { description: "Desired condition, default present" })),
|
|
9157
|
-
timeoutMs: Type.Optional(Type.Number({ description: "Maximum wait, default 10000ms", minimum: 100, maximum: 6e4 }))
|
|
9158
|
-
};
|
|
9159
|
-
var OBSERVE_RISK = {
|
|
9160
|
-
riskClass: "read_only",
|
|
9161
|
-
concurrencySafe: false,
|
|
9162
|
-
permissionScope: "host",
|
|
9163
|
-
readsHostResource: true,
|
|
9164
|
-
allowedForSubagentByDefault: false
|
|
9165
|
-
};
|
|
9166
|
-
var BROWSER_RISK = {
|
|
9167
|
-
riskClass: "external_side_effect",
|
|
9168
|
-
concurrencySafe: false,
|
|
9169
|
-
requiresPermission: true,
|
|
9170
|
-
permissionScope: "host",
|
|
9171
|
-
externalSideEffect: true,
|
|
9172
|
-
allowedForSubagentByDefault: false
|
|
9173
|
-
};
|
|
9174
|
-
var ACT_RISK = {
|
|
9175
|
-
riskClass: "external_side_effect",
|
|
9176
|
-
concurrencySafe: false,
|
|
9177
|
-
requiresPermission: true,
|
|
9178
|
-
permissionScope: "host",
|
|
9179
|
-
writesHostResource: true,
|
|
9180
|
-
externalSideEffect: true,
|
|
9181
|
-
highRisk: true,
|
|
9182
|
-
allowedForSubagentByDefault: false
|
|
9183
|
-
};
|
|
9184
|
-
function describe(description, ...extra) {
|
|
9185
|
-
const lines = [description];
|
|
9186
|
-
for (const part of extra) {
|
|
9187
|
-
if (!part) continue;
|
|
9188
|
-
for (const line of Array.isArray(part) ? part : [part]) lines.push(line);
|
|
9189
|
-
}
|
|
9190
|
-
return lines.join(" ");
|
|
9191
|
-
}
|
|
9192
|
-
var findTool = {
|
|
9193
|
-
name: "find_roots",
|
|
9194
|
-
label: "Find Roots",
|
|
9195
|
-
risk: OBSERVE_RISK,
|
|
9196
|
-
description: describe(
|
|
9197
|
-
"Find a bounded, ranked set of controllable UI roots with refs, geometry, and focus state.",
|
|
9198
|
-
"Find a target root before observe_ui when needed. Desktop control is a last resort - prefer API/CLI/web tools when they suffice."
|
|
9199
|
-
),
|
|
9200
|
-
parameters: Type.Object({
|
|
9201
|
-
text: Type.Optional(Type.String({ description: "Ranked app or title text", maxLength: 256 })),
|
|
9202
|
-
app: Type.Optional(Type.String({ description: "Exact normalized app name", maxLength: 256 })),
|
|
9203
|
-
bundleId: Type.Optional(Type.String({ description: "Exact bundle id" })),
|
|
9204
|
-
pid: Type.Optional(Type.Number({ description: "Exact process id" })),
|
|
9205
|
-
kind: Type.Optional(Type.Union([Type.Literal("window"), Type.Literal("menu"), Type.Literal("sheet"), Type.Literal("popover"), Type.Literal("dialog"), Type.Literal("browser_page")], { description: "Exact root kind" }))
|
|
9206
|
-
}),
|
|
9207
|
-
executor: executeFind
|
|
9208
|
-
};
|
|
9209
|
-
var observeTool = {
|
|
9210
|
-
name: "observe_ui",
|
|
9211
|
-
label: "Observe UI",
|
|
9212
|
-
risk: OBSERVE_RISK,
|
|
9213
|
-
description: describe(
|
|
9214
|
-
"Capture the current/frontmost root or one exact @r root and return a bounded UI outline.",
|
|
9215
|
-
"Primary UI observation tool. Follow with search_ui, expand_ui, inspect_ui, or act_ui.",
|
|
9216
|
-
[
|
|
9217
|
-
"Use mode=semantic to skip OCR and images, visual to force them, and fused for automatic selection.",
|
|
9218
|
-
"Use @e outline refs from observe_ui/search_ui for act_ui; pictureOnly refs are coordinate-only and blocked by UI-tree-only policy."
|
|
9219
|
-
]
|
|
9220
|
-
),
|
|
9221
|
-
parameters: Type.Object({
|
|
9222
|
-
root: Type.Optional(Type.String({ description: "Exact @r ref issued by find_roots" })),
|
|
9223
|
-
mode: Type.Optional(Type.Union([Type.Literal("semantic"), Type.Literal("visual"), Type.Literal("fused")], { description: "Observation mode, default fused" }))
|
|
9224
|
-
}),
|
|
9225
|
-
executor: executeObserve
|
|
9226
|
-
};
|
|
9227
|
-
var searchUiTool = {
|
|
9228
|
-
name: "search_ui",
|
|
9229
|
-
label: "Search UI",
|
|
9230
|
-
risk: OBSERVE_RISK,
|
|
9231
|
-
description: describe(
|
|
9232
|
-
"Return a bounded, deterministically ranked search of the cached outline. At least one predicate is required.",
|
|
9233
|
-
"Find targets not shown in the compact observe_ui output; refine broad searches instead of paging matches."
|
|
9234
|
-
),
|
|
9235
|
-
parameters: Type.Object({
|
|
9236
|
-
text: Type.Optional(Type.String({ description: "Human-readable text or label", maxLength: 256 })),
|
|
9237
|
-
role: Type.Optional(Type.String({ description: "Exact normalized role, e.g. button", maxLength: 128 })),
|
|
9238
|
-
capability: Type.Optional(Type.String({ description: "Exact capability, e.g. press", maxLength: 128 })),
|
|
9239
|
-
stateId
|
|
9240
|
-
}),
|
|
9241
|
-
executor: executeSearchUi
|
|
9242
|
-
};
|
|
9243
|
-
var expandUiTool = {
|
|
9244
|
-
name: "expand_ui",
|
|
9245
|
-
label: "Expand UI",
|
|
9246
|
-
risk: OBSERVE_RISK,
|
|
9247
|
-
description: describe(
|
|
9248
|
-
"Unfold bounded local outline context for one @e ref.",
|
|
9249
|
-
"Expand a specific ref instead of dumping unrelated UI."
|
|
9250
|
-
),
|
|
9251
|
-
parameters: Type.Object({ ref: Type.String(), depth: Type.Optional(Type.Number({ minimum: 1, maximum: 8, description: "Subtree depth, default 3" })), stateId }),
|
|
9252
|
-
executor: executeExpandUi
|
|
9253
|
-
};
|
|
9254
|
-
var inspectUiTool = {
|
|
9255
|
-
name: "inspect_ui",
|
|
9256
|
-
label: "Inspect UI",
|
|
9257
|
-
risk: OBSERVE_RISK,
|
|
9258
|
-
description: describe(
|
|
9259
|
-
"Inspect one exact outline ref with fields, geometry, capabilities, and annotations.",
|
|
9260
|
-
"Use when a target's evidence or provenance matters."
|
|
9261
|
-
),
|
|
9262
|
-
parameters: Type.Object({ ref: Type.String(), stateId }),
|
|
9263
|
-
executor: executeInspectUi
|
|
9264
|
-
};
|
|
9265
|
-
var actTool = {
|
|
9266
|
-
name: "act_ui",
|
|
9267
|
-
label: "Act",
|
|
9268
|
-
risk: ACT_RISK,
|
|
9269
|
-
description: describe(
|
|
9270
|
-
"Perform one or more precisely targeted checked actions and return the successor state.",
|
|
9271
|
-
"Pass dependent click/type steps together and use expect for observable completion.",
|
|
9272
|
-
["After clicking an editable region, omit ref from typeText/keypress so input follows the established focus."]
|
|
9273
|
-
),
|
|
9274
|
-
parameters: Type.Object({ stateId, expect: Type.Optional(Type.Object(conditionProperties)), actions: Type.Array(uiAction, { minItems: 1, maxItems: 20 }) }),
|
|
9275
|
-
executor: executeAct
|
|
9276
|
-
};
|
|
9277
|
-
var readTextTool = {
|
|
9278
|
-
name: "read_text",
|
|
9279
|
-
label: "Read Text",
|
|
9280
|
-
risk: OBSERVE_RISK,
|
|
9281
|
-
description: describe(
|
|
9282
|
-
"Read a fixed-size page from an @e UI ref or immutable @o truncated-output ref.",
|
|
9283
|
-
"Use @e with its stateId; @o continuation refs don't need stateId."
|
|
9284
|
-
),
|
|
9285
|
-
parameters: Type.Object({ ref: Type.String(), offset: Type.Optional(Type.Number({ minimum: 0 })), stateId: Type.Optional(stateId) }),
|
|
9286
|
-
executor: executeReadText
|
|
9287
|
-
};
|
|
9288
|
-
var waitForTool = {
|
|
9289
|
-
name: "wait_for",
|
|
9290
|
-
label: "Wait For",
|
|
9291
|
-
risk: OBSERVE_RISK,
|
|
9292
|
-
description: describe(
|
|
9293
|
-
"Wait for one scoped UI condition and return the successor state.",
|
|
9294
|
-
"Use after asynchronous UI changes instead of polling observe_ui."
|
|
9295
|
-
),
|
|
9296
|
-
parameters: Type.Object({ ...conditionProperties, stateId }),
|
|
9297
|
-
executor: executeWaitFor
|
|
9298
|
-
};
|
|
9299
|
-
var launchBrowserTool = {
|
|
9300
|
-
name: "launch_browser",
|
|
9301
|
-
label: "Launch Browser Context",
|
|
9302
|
-
risk: BROWSER_RISK,
|
|
9303
|
-
description: describe(
|
|
9304
|
-
"Launch the configured Pie-managed CDP browser and return an observed browser-page state.",
|
|
9305
|
-
"Use for browser work that needs a managed CDP context.",
|
|
9306
|
-
["Prefer curl through bash when the page is directly fetchable."]
|
|
9307
|
-
),
|
|
9308
|
-
parameters: Type.Object({ url: Type.Optional(Type.String({ maxLength: 8192 })) }),
|
|
9309
|
-
executor: executeLaunchBrowser
|
|
9310
|
-
};
|
|
9311
|
-
var navigateBrowserTool = {
|
|
9312
|
-
name: "navigate_browser",
|
|
9313
|
-
label: "Navigate Browser",
|
|
9314
|
-
risk: BROWSER_RISK,
|
|
9315
|
-
description: describe(
|
|
9316
|
-
"Navigate an observed CDP browser-page state to an HTTP(S) URL.",
|
|
9317
|
-
"Native browser windows use act_ui; this tool is CDP-only."
|
|
9318
|
-
),
|
|
9319
|
-
parameters: Type.Object({ url: Type.String({ maxLength: 8192 }), stateId }),
|
|
9320
|
-
executor: executeNavigateBrowser
|
|
9321
|
-
};
|
|
9322
|
-
var evaluateBrowserTool = {
|
|
9323
|
-
name: "evaluate_browser",
|
|
9324
|
-
label: "Evaluate Browser",
|
|
9325
|
-
risk: BROWSER_RISK,
|
|
9326
|
-
description: describe(
|
|
9327
|
-
"Evaluate targeted JavaScript in a CDP browser-page state; returned output is strictly bounded.",
|
|
9328
|
-
"Prefer observe/search/read; return selected fields, aggregates, or bounded slices."
|
|
9329
|
-
),
|
|
9330
|
-
parameters: Type.Object({ stateId, expression: Type.String({ maxLength: 65536 }) }),
|
|
9331
|
-
executor: executeEvaluateBrowser
|
|
9332
|
-
};
|
|
9333
|
-
var OBSERVE_TOOLS = [findTool, observeTool, searchUiTool, expandUiTool, inspectUiTool, readTextTool, waitForTool, launchBrowserTool, navigateBrowserTool, evaluateBrowserTool];
|
|
9334
|
-
var ACT_TOOLS = [actTool];
|
|
9335
|
-
function summarizeActArgs(args) {
|
|
9336
|
-
const actions = args?.actions;
|
|
9337
|
-
if (!Array.isArray(actions) || actions.length === 0) return "(no actions)";
|
|
9338
|
-
const names = actions.map((action) => action?.action ?? "unknown");
|
|
9339
|
-
const unique = [...new Set(names)];
|
|
9340
|
-
return `${actions.length} action(s): ${unique.join(", ")}`;
|
|
9341
|
-
}
|
|
9342
|
-
async function confirmAct(ctx, args) {
|
|
9343
|
-
if (ctx.yoloMode) return true;
|
|
9344
|
-
if (!ctx.interactions.isAvailable()) return false;
|
|
9345
|
-
const response = await ctx.interactions.request({
|
|
9346
|
-
type: "confirm",
|
|
9347
|
-
id: `computer-use:${Date.now()}`,
|
|
9348
|
-
prompt: "Allow computer-use to act on your desktop (click/type/scroll/press)?",
|
|
9349
|
-
detail: [
|
|
9350
|
-
"Class: computer_use_act",
|
|
9351
|
-
`Tool: act_ui \u2014 ${summarizeActArgs(args)}`,
|
|
9352
|
-
"",
|
|
9353
|
-
"The agent will synthesize real input events on your machine."
|
|
9354
|
-
].join("\n"),
|
|
9355
|
-
timeoutMs: 12e4
|
|
9356
|
-
}).catch(() => void 0);
|
|
9357
|
-
return !!response && response.type === "confirm" && response.confirmed === true;
|
|
9358
|
-
}
|
|
9359
|
-
function blockedActResult() {
|
|
9360
|
-
return {
|
|
9361
|
-
content: [{
|
|
9362
|
-
type: "text",
|
|
9363
|
-
text: "act_ui was blocked: the user did not confirm desktop control (or no interaction handler is available). Do not retry act_ui; explain what you intended to do and ask the user how to proceed."
|
|
9364
|
-
}],
|
|
9365
|
-
isError: true
|
|
9366
|
-
};
|
|
9352
|
+
function requiredFlag(args, name) {
|
|
9353
|
+
const value = args.flags.get(name);
|
|
9354
|
+
if (value === void 0 || value === "") usageError(`missing required option ${name}`);
|
|
9355
|
+
return value;
|
|
9367
9356
|
}
|
|
9368
|
-
function
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
label: spec.label,
|
|
9372
|
-
description: spec.description,
|
|
9373
|
-
parameters: spec.parameters,
|
|
9374
|
-
risk: spec.risk,
|
|
9375
|
-
execute: async (args, toolContext) => {
|
|
9376
|
-
if (options.confirmAct) {
|
|
9377
|
-
const approved = await options.confirmAct(args);
|
|
9378
|
-
if (!approved) return blockedActResult();
|
|
9379
|
-
}
|
|
9380
|
-
const result = await spec.executor(toolContext.toolCallId, args, toolContext.signal, void 0, ctx);
|
|
9381
|
-
return result;
|
|
9382
|
-
}
|
|
9383
|
-
});
|
|
9357
|
+
function optionalFlag(args, name) {
|
|
9358
|
+
const value = args.flags.get(name);
|
|
9359
|
+
return value === void 0 || value === "" ? void 0 : value;
|
|
9384
9360
|
}
|
|
9385
|
-
function
|
|
9386
|
-
const
|
|
9387
|
-
return
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
`headless: ${loaded.config.headless ? "enabled" : "disabled"}`,
|
|
9392
|
-
`cursor_overlay: ${loaded.config.cursor_overlay ? "enabled" : "disabled"}`,
|
|
9393
|
-
"",
|
|
9394
|
-
"Sources:",
|
|
9395
|
-
...loaded.sources.map((source) => `- ${source.path}: ${source.error ? `error: ${source.error}` : source.exists ? "loaded" : "not found"}`),
|
|
9396
|
-
`- env overrides: ${Object.keys(loaded.env).join(", ") || "none"}`
|
|
9397
|
-
].join("\n");
|
|
9361
|
+
function numericFlag(args, name) {
|
|
9362
|
+
const value = optionalFlag(args, name);
|
|
9363
|
+
if (value === void 0) return void 0;
|
|
9364
|
+
const parsed = Number(value);
|
|
9365
|
+
if (!Number.isFinite(parsed)) usageError(`${name} must be a number (got '${value}')`);
|
|
9366
|
+
return parsed;
|
|
9398
9367
|
}
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
|
|
9408
|
-
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9421
|
-
|
|
9368
|
+
function jsonFlag(args, name) {
|
|
9369
|
+
const value = requiredFlag(args, name);
|
|
9370
|
+
try {
|
|
9371
|
+
return JSON.parse(value);
|
|
9372
|
+
} catch (error) {
|
|
9373
|
+
usageError(`${name} must be valid JSON (${error.message})`);
|
|
9374
|
+
}
|
|
9375
|
+
}
|
|
9376
|
+
function usageError(message) {
|
|
9377
|
+
process.stderr.write(`computer-use-axi: ${message}
|
|
9378
|
+
|
|
9379
|
+
${USAGE}
|
|
9380
|
+
`);
|
|
9381
|
+
process.exit(2);
|
|
9382
|
+
}
|
|
9383
|
+
function buildCommand(args) {
|
|
9384
|
+
if (args.command === "browser") {
|
|
9385
|
+
const sub = args.rest[0] ?? usageError("browser requires a subcommand: launch | navigate | eval");
|
|
9386
|
+
if (sub === "launch") return { command: "launch_browser", params: { url: optionalFlag(args, "--url") } };
|
|
9387
|
+
if (sub === "navigate") return { command: "navigate_browser", params: { stateId: requiredFlag(args, "--state"), url: requiredFlag(args, "--url") } };
|
|
9388
|
+
if (sub === "eval") return { command: "evaluate_browser", params: { stateId: requiredFlag(args, "--state"), expression: requiredFlag(args, "--expr") } };
|
|
9389
|
+
usageError(`unknown browser subcommand '${sub}' (expected launch | navigate | eval)`);
|
|
9390
|
+
}
|
|
9391
|
+
switch (args.command) {
|
|
9392
|
+
case "roots":
|
|
9393
|
+
return {
|
|
9394
|
+
command: "find_roots",
|
|
9395
|
+
params: {
|
|
9396
|
+
text: optionalFlag(args, "--text"),
|
|
9397
|
+
app: optionalFlag(args, "--app"),
|
|
9398
|
+
bundleId: optionalFlag(args, "--bundle-id"),
|
|
9399
|
+
pid: numericFlag(args, "--pid"),
|
|
9400
|
+
kind: optionalFlag(args, "--kind")
|
|
9401
|
+
}
|
|
9402
|
+
};
|
|
9403
|
+
case "observe":
|
|
9404
|
+
return {
|
|
9405
|
+
command: "observe_ui",
|
|
9406
|
+
params: { root: optionalFlag(args, "--root"), mode: optionalFlag(args, "--mode") }
|
|
9407
|
+
};
|
|
9408
|
+
case "search": {
|
|
9409
|
+
const params = {
|
|
9410
|
+
text: optionalFlag(args, "--text"),
|
|
9411
|
+
role: optionalFlag(args, "--role"),
|
|
9412
|
+
capability: optionalFlag(args, "--capability"),
|
|
9413
|
+
stateId: requiredFlag(args, "--state")
|
|
9414
|
+
};
|
|
9415
|
+
if (!params.text && !params.role && !params.capability) usageError("search requires at least one of --text, --role, --capability");
|
|
9416
|
+
return { command: "search_ui", params };
|
|
9417
|
+
}
|
|
9418
|
+
case "expand":
|
|
9419
|
+
return { command: "expand_ui", params: { stateId: requiredFlag(args, "--state"), ref: requiredFlag(args, "--ref"), depth: numericFlag(args, "--depth") } };
|
|
9420
|
+
case "inspect":
|
|
9421
|
+
return { command: "inspect_ui", params: { stateId: requiredFlag(args, "--state"), ref: requiredFlag(args, "--ref") } };
|
|
9422
|
+
case "read": {
|
|
9423
|
+
const ref = requiredFlag(args, "--ref");
|
|
9424
|
+
const params = { ref, offset: numericFlag(args, "--offset") };
|
|
9425
|
+
if (ref.startsWith("@e")) params.stateId = requiredFlag(args, "--state");
|
|
9426
|
+
else params.stateId = optionalFlag(args, "--state");
|
|
9427
|
+
return { command: "read_text", params };
|
|
9428
|
+
}
|
|
9429
|
+
case "wait": {
|
|
9430
|
+
const params = {
|
|
9431
|
+
stateId: requiredFlag(args, "--state"),
|
|
9432
|
+
text: optionalFlag(args, "--text"),
|
|
9433
|
+
role: optionalFlag(args, "--role"),
|
|
9434
|
+
value: optionalFlag(args, "--value"),
|
|
9435
|
+
ref: optionalFlag(args, "--ref"),
|
|
9436
|
+
scopeRef: optionalFlag(args, "--scope-ref"),
|
|
9437
|
+
until: optionalFlag(args, "--until"),
|
|
9438
|
+
timeoutMs: numericFlag(args, "--timeout-ms")
|
|
9439
|
+
};
|
|
9440
|
+
if (!params.text && !params.role && !params.ref && !params.value) usageError("wait requires at least one of --text, --role, --value, --ref");
|
|
9441
|
+
if (params.role && !params.text && !params.value && !params.ref && !params.scopeRef) usageError("wait --role requires --ref or --scope-ref (role-only conditions must be scoped)");
|
|
9442
|
+
if (params.value && !params.ref) usageError("wait --value requires --ref (exact element value checks need an exact ref)");
|
|
9443
|
+
return { command: "wait_for", params };
|
|
9444
|
+
}
|
|
9445
|
+
case "act": {
|
|
9446
|
+
const actions = jsonFlag(args, "--actions");
|
|
9447
|
+
if (!Array.isArray(actions) || actions.length === 0) usageError("--actions must be a non-empty JSON array");
|
|
9448
|
+
const params = { stateId: requiredFlag(args, "--state"), actions };
|
|
9449
|
+
const expect = optionalFlag(args, "--expect");
|
|
9450
|
+
if (expect !== void 0) {
|
|
9451
|
+
try {
|
|
9452
|
+
params.expect = JSON.parse(expect);
|
|
9453
|
+
} catch (error) {
|
|
9454
|
+
usageError(`--expect must be valid JSON (${error.message})`);
|
|
9455
|
+
}
|
|
9456
|
+
}
|
|
9457
|
+
return { command: "act_ui", params };
|
|
9422
9458
|
}
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9459
|
+
default:
|
|
9460
|
+
usageError(args.command ? `unknown command '${args.command}'` : "missing command");
|
|
9461
|
+
}
|
|
9462
|
+
}
|
|
9463
|
+
var EXECUTORS = {
|
|
9464
|
+
find_roots: executeFind,
|
|
9465
|
+
observe_ui: executeObserve,
|
|
9466
|
+
search_ui: executeSearchUi,
|
|
9467
|
+
expand_ui: executeExpandUi,
|
|
9468
|
+
inspect_ui: executeInspectUi,
|
|
9469
|
+
read_text: executeReadText,
|
|
9470
|
+
wait_for: executeWaitFor,
|
|
9471
|
+
act_ui: executeAct,
|
|
9472
|
+
launch_browser: executeLaunchBrowser,
|
|
9473
|
+
navigate_browser: executeNavigateBrowser,
|
|
9474
|
+
evaluate_browser: executeEvaluateBrowser
|
|
9475
|
+
};
|
|
9476
|
+
function adaptGuidance(text) {
|
|
9477
|
+
return text.replace(/observe_ui\(\{ root: "(@r\d+)" \}\)/g, "computer-use-axi observe --root $1").replace(/read_text\(\{ ref: "(@o\d+)", offset: (\d+) \}\)/g, "computer-use-axi read --ref $1 --offset $2").replace(/read_text\(\{ ref: "(@o\d+)" \}\)/g, "computer-use-axi read --ref $1").replace(/\bfind_roots\b/g, "computer-use-axi roots").replace(/\bobserve_ui\b/g, "computer-use-axi observe").replace(/\bsearch_ui\b/g, "computer-use-axi search").replace(/\bexpand_ui\b/g, "computer-use-axi expand").replace(/\binspect_ui\b/g, "computer-use-axi inspect").replace(/\bread_text\b/g, "computer-use-axi read").replace(/\bwait_for\b/g, "computer-use-axi wait").replace(/\bact_ui\b/g, "computer-use-axi act").replace(/\blaunch_browser\b/g, "computer-use-axi browser launch").replace(/\bnavigate_browser\b/g, "computer-use-axi browser navigate").replace(/\bevaluate_browser\b/g, "computer-use-axi browser eval").replace(/computer-use-axi observe\(\{ root: "([^"]+)" \}\)/g, 'computer-use-axi observe --root "$1"');
|
|
9478
|
+
}
|
|
9479
|
+
async function main() {
|
|
9480
|
+
const args = parseArgs(process.argv.slice(2));
|
|
9481
|
+
if (args.help || !args.command && args.flags.size === 0) {
|
|
9482
|
+
process.stdout.write(`${USAGE}
|
|
9483
|
+
`);
|
|
9484
|
+
return 0;
|
|
9485
|
+
}
|
|
9486
|
+
const { command, params } = buildCommand(args);
|
|
9487
|
+
const executor = EXECUTORS[command];
|
|
9488
|
+
if (!executor) usageError(`internal: no executor for ${command}`);
|
|
9489
|
+
enableDiskPersistence();
|
|
9490
|
+
await attachPersistedBrowser();
|
|
9491
|
+
const ctx = { cwd: process.cwd(), getMessages: () => [] };
|
|
9492
|
+
const signal = AbortSignal.timeout(Number(process.env.PIE_COMPUTER_USE_AXI_TIMEOUT_MS) > 0 ? Number(process.env.PIE_COMPUTER_USE_AXI_TIMEOUT_MS) : 12e4);
|
|
9493
|
+
try {
|
|
9494
|
+
const result = await executor("cli", params, signal, void 0, ctx);
|
|
9495
|
+
if (args.json) {
|
|
9496
|
+
const adapted = {
|
|
9497
|
+
...result,
|
|
9498
|
+
content: result.content.map((part) => part.type === "text" && typeof part.text === "string" ? { ...part, text: adaptGuidance(part.text) } : part)
|
|
9499
|
+
};
|
|
9500
|
+
process.stdout.write(`${JSON.stringify(adapted)}
|
|
9501
|
+
`);
|
|
9502
|
+
} else {
|
|
9503
|
+
const text = result.content.map((part) => part.type === "text" && typeof part.text === "string" ? part.text : void 0).filter(Boolean).join("\n");
|
|
9504
|
+
if (text) process.stdout.write(`${adaptGuidance(text)}
|
|
9505
|
+
`);
|
|
9506
|
+
else if (result.content.some((part) => part.type === "image")) process.stdout.write("(image-only observation; use --mode semantic for a text outline or --json for raw content)\n");
|
|
9507
|
+
}
|
|
9508
|
+
if (result.isError) return 1;
|
|
9509
|
+
return 0;
|
|
9510
|
+
} catch (error) {
|
|
9511
|
+
const message = adaptGuidance(error instanceof Error ? error.message : String(error));
|
|
9512
|
+
if (args.json) {
|
|
9513
|
+
process.stdout.write(`${JSON.stringify({ content: [{ type: "text", text: message }], isError: true })}
|
|
9514
|
+
`);
|
|
9515
|
+
} else {
|
|
9516
|
+
process.stderr.write(`${message}
|
|
9517
|
+
`);
|
|
9518
|
+
}
|
|
9519
|
+
return 1;
|
|
9520
|
+
}
|
|
9521
|
+
}
|
|
9522
|
+
var isDirectEntry = (() => {
|
|
9523
|
+
try {
|
|
9524
|
+
return import.meta.url === new URL(`file://${process.argv[1]}`).href;
|
|
9525
|
+
} catch {
|
|
9526
|
+
return false;
|
|
9527
|
+
}
|
|
9528
|
+
})();
|
|
9529
|
+
if (isDirectEntry) {
|
|
9530
|
+
main().then((code) => {
|
|
9531
|
+
process.exitCode = code;
|
|
9532
|
+
}).catch((error) => {
|
|
9533
|
+
process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}
|
|
9534
|
+
`);
|
|
9535
|
+
process.exitCode = 1;
|
|
9428
9536
|
});
|
|
9429
9537
|
}
|
|
9430
9538
|
export {
|
|
9431
|
-
|
|
9539
|
+
USAGE,
|
|
9540
|
+
adaptGuidance,
|
|
9541
|
+
buildCommand,
|
|
9542
|
+
parseArgs,
|
|
9543
|
+
usageError
|
|
9432
9544
|
};
|