@vm0/cli 9.157.1 → 9.158.1

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/zero.js CHANGED
@@ -16,6 +16,8 @@ import {
16
16
  completeTelegramFileUpload,
17
17
  configureGlobalProxyFromEnv,
18
18
  connectorTypeSchema,
19
+ createComputerUseReadCommand,
20
+ createComputerUseWriteCommand,
19
21
  createLocalBrowserReadCommand,
20
22
  createLocalBrowserWriteCommand,
21
23
  createSkill,
@@ -23,6 +25,7 @@ import {
23
25
  createZeroRun,
24
26
  decodeCliTokenPayload,
25
27
  decodeZeroTokenPayload,
28
+ deleteComputerUseHost,
26
29
  deleteLocalBrowserHost,
27
30
  deleteSkill,
28
31
  deleteZeroAgent,
@@ -50,7 +53,7 @@ import {
50
53
  getActiveOrg,
51
54
  getApiUrl,
52
55
  getAuthMethodsForType,
53
- getComputerUseHost,
56
+ getComputerUseCommand,
54
57
  getConnectorDerivedNames,
55
58
  getConnectorEnvironmentMapping,
56
59
  getConnectorFirewall,
@@ -83,6 +86,8 @@ import {
83
86
  isInteractive,
84
87
  isUUID,
85
88
  leaveZeroOrg,
89
+ listComputerUseAuditEvents,
90
+ listComputerUseHosts,
86
91
  listLocalBrowserAuditEvents,
87
92
  listLocalBrowserHosts,
88
93
  listSkills,
@@ -106,7 +111,6 @@ import {
106
111
  promptPassword,
107
112
  promptSelect,
108
113
  promptText,
109
- registerComputerUseHost,
110
114
  removeZeroOrgMember,
111
115
  renderRunCreated,
112
116
  requestDeveloperSupportConsent,
@@ -130,7 +134,6 @@ import {
130
134
  source_default,
131
135
  submitDeveloperSupport,
132
136
  switchZeroOrg,
133
- unregisterComputerUseHost,
134
137
  updateSkill,
135
138
  updateZeroAgent,
136
139
  updateZeroAgentInstructions,
@@ -142,7 +145,7 @@ import {
142
145
  zeroAgentCustomSkillNameSchema,
143
146
  zeroLocalAgentCommand,
144
147
  zeroTokenAllowsFeatureSwitch
145
- } from "./chunk-YWCHIHYE.js";
148
+ } from "./chunk-Y2IQIGV7.js";
146
149
  import {
147
150
  __commonJS,
148
151
  __require,
@@ -33941,1044 +33944,273 @@ Notes:
33941
33944
 
33942
33945
  // src/commands/zero/computer-use/index.ts
33943
33946
  init_esm_shims();
33944
-
33945
- // src/commands/zero/computer-use/host.ts
33946
- init_esm_shims();
33947
-
33948
- // src/lib/computer-use/desktop-server.ts
33949
- init_esm_shims();
33950
- import {
33951
- createServer
33952
- } from "http";
33953
- import { createServer as createNetServer } from "net";
33954
-
33955
- // src/lib/computer-use/screencapture.ts
33956
- init_esm_shims();
33957
- import { execFile } from "child_process";
33958
- import { readFile, unlink } from "fs/promises";
33959
- import { randomUUID } from "crypto";
33960
- import { join as join5 } from "path";
33961
- import { tmpdir as tmpdir4 } from "os";
33962
- import { promisify } from "util";
33963
- var execFileAsync = promisify(execFile);
33964
- async function captureScreenshot() {
33965
- const tmpPath = join5(tmpdir4(), `vm0-screenshot-${randomUUID()}.jpg`);
33966
- try {
33967
- await execFileAsync("screencapture", ["-x", "-t", "jpg", tmpPath]);
33968
- const info = await getScreenInfo();
33969
- if (info.scaleFactor > 1) {
33970
- await execFileAsync("sips", [
33971
- "-z",
33972
- String(info.height),
33973
- String(info.width),
33974
- "-s",
33975
- "formatOptions",
33976
- "80",
33977
- tmpPath
33978
- ]);
33979
- }
33980
- const buffer = await readFile(tmpPath);
33981
- return {
33982
- image: buffer.toString("base64"),
33983
- width: info.width,
33984
- height: info.height,
33985
- scaleFactor: info.scaleFactor,
33986
- format: "jpg"
33987
- };
33988
- } finally {
33989
- await unlink(tmpPath).catch(() => {
33990
- });
33991
- }
33992
- }
33993
- async function captureRegionScreenshot(region) {
33994
- const tmpPath = join5(tmpdir4(), `vm0-zoom-${randomUUID()}.jpg`);
33995
- try {
33996
- const regionArg = `${region.x},${region.y},${region.width},${region.height}`;
33997
- await execFileAsync("screencapture", [
33998
- "-x",
33999
- "-t",
34000
- "jpg",
34001
- "-R",
34002
- regionArg,
34003
- tmpPath
34004
- ]);
34005
- const info = await getScreenInfo();
34006
- if (info.scaleFactor > 1) {
34007
- await execFileAsync("sips", [
34008
- "-z",
34009
- String(region.height),
34010
- String(region.width),
34011
- "-s",
34012
- "formatOptions",
34013
- "80",
34014
- tmpPath
34015
- ]);
34016
- }
34017
- const buffer = await readFile(tmpPath);
34018
- return {
34019
- image: buffer.toString("base64"),
34020
- width: region.width,
34021
- height: region.height,
34022
- scaleFactor: info.scaleFactor,
34023
- format: "jpg"
34024
- };
34025
- } finally {
34026
- await unlink(tmpPath).catch(() => {
34027
- });
34028
- }
33947
+ function sleep2(ms) {
33948
+ return new Promise((resolve2) => {
33949
+ setTimeout(resolve2, ms);
33950
+ });
34029
33951
  }
34030
- async function getScreenInfo() {
34031
- const { stdout } = await execFileAsync("system_profiler", [
34032
- "SPDisplaysDataType",
34033
- "-json"
34034
- ]);
34035
- const data = JSON.parse(stdout);
34036
- const displays = data.SPDisplaysDataType ?? [];
34037
- for (const gpu of displays) {
34038
- const screens = gpu.spdisplays_ndrvs ?? [];
34039
- for (const screen of screens) {
34040
- const pixelStr = screen._spdisplays_pixels;
34041
- if (pixelStr) {
34042
- const pixelMatch = pixelStr.match(/(\d+)\s*x\s*(\d+)/);
34043
- if (pixelMatch?.[1] && pixelMatch[2]) {
34044
- const physicalWidth = parseInt(pixelMatch[1], 10);
34045
- const physicalHeight = parseInt(pixelMatch[2], 10);
34046
- const resStr = screen._spdisplays_resolution ?? screen.spdisplays_resolution ?? "";
34047
- const resMatch = resStr.match(/(\d+)\s*x\s*(\d+)/);
34048
- let scaleFactor;
34049
- let logicalWidth;
34050
- let logicalHeight;
34051
- if (resMatch?.[1] && resMatch[2]) {
34052
- logicalWidth = parseInt(resMatch[1], 10);
34053
- logicalHeight = parseInt(resMatch[2], 10);
34054
- scaleFactor = Math.round(physicalWidth / logicalWidth);
34055
- } else {
34056
- const isRetina = /retina/i.test(resStr);
34057
- scaleFactor = isRetina ? 2 : 1;
34058
- logicalWidth = Math.floor(physicalWidth / scaleFactor);
34059
- logicalHeight = Math.floor(physicalHeight / scaleFactor);
34060
- }
34061
- return {
34062
- width: logicalWidth,
34063
- height: logicalHeight,
34064
- scaleFactor
34065
- };
34066
- }
34067
- }
34068
- }
33952
+ function parseTimeoutSeconds(value) {
33953
+ if (!value) return 30;
33954
+ const seconds = Number.parseInt(value, 10);
33955
+ if (!Number.isFinite(seconds) || seconds <= 0) {
33956
+ throw new Error("Timeout must be a positive number of seconds");
34069
33957
  }
34070
- return { width: 1920, height: 1080, scaleFactor: 1 };
34071
- }
34072
-
34073
- // src/lib/computer-use/cliclick.ts
34074
- init_esm_shims();
34075
- import { execFile as execFile2 } from "child_process";
34076
- import { promisify as promisify2 } from "util";
34077
- import { setTimeout as sleep2 } from "timers/promises";
34078
- var execFileAsync2 = promisify2(execFile2);
34079
- async function leftClickDrag(startX, startY, endX, endY) {
34080
- await execFileAsync2("cliclick", [
34081
- `dd:${startX},${startY}`,
34082
- `du:${endX},${endY}`
34083
- ]);
34084
- }
34085
- async function leftMouseDown(x, y) {
34086
- await execFileAsync2("cliclick", [`dd:${x},${y}`]);
34087
- }
34088
- async function leftMouseUp(x, y) {
34089
- await execFileAsync2("cliclick", [`du:${x},${y}`]);
33958
+ return seconds;
34090
33959
  }
34091
- var ACTION_COMMANDS = {
34092
- left_click: "c",
34093
- right_click: "rc",
34094
- middle_click: "mc",
34095
- double_click: "dc",
34096
- triple_click: "tc",
34097
- move: "m"
34098
- };
34099
- var VALID_ACTIONS = new Set(Object.keys(ACTION_COMMANDS));
34100
- async function isCliclickInstalled() {
34101
- try {
34102
- await execFileAsync2("which", ["cliclick"]);
34103
- return true;
34104
- } catch {
34105
- return false;
33960
+ function parseOptionalNonNegativeInteger(value, label) {
33961
+ if (value === void 0) return void 0;
33962
+ const parsed = Number.parseInt(value, 10);
33963
+ if (!Number.isFinite(parsed) || parsed < 0) {
33964
+ throw new Error(`${label} must be a non-negative integer`);
34106
33965
  }
33966
+ return parsed;
34107
33967
  }
34108
- async function checkCliclickInstalled() {
34109
- try {
34110
- await execFileAsync2("which", ["cliclick"]);
34111
- } catch {
34112
- throw new Error("cliclick not found. Install with: brew install cliclick");
34113
- }
34114
- }
34115
- async function executeMouseAction(action, x, y) {
34116
- await checkCliclickInstalled();
34117
- const prefix = ACTION_COMMANDS[action];
34118
- await execFileAsync2("cliclick", [`${prefix}:${x},${y}`]);
34119
- }
34120
- async function getCursorPosition() {
34121
- await checkCliclickInstalled();
34122
- const { stdout } = await execFileAsync2("cliclick", ["p"]);
34123
- const parts = stdout.trim().split(",");
34124
- const xStr = parts[0];
34125
- const yStr = parts[1];
34126
- if (parts.length !== 2 || xStr === void 0 || yStr === void 0) {
34127
- throw new Error(`Unexpected cliclick output: ${stdout.trim()}`);
34128
- }
34129
- const x = parseInt(xStr, 10);
34130
- const y = parseInt(yStr, 10);
34131
- if (Number.isNaN(x) || Number.isNaN(y)) {
34132
- throw new Error(`Failed to parse cursor position: ${stdout.trim()}`);
34133
- }
34134
- return { x, y };
34135
- }
34136
- var VALID_SPECIAL_KEYS = /* @__PURE__ */ new Set([
34137
- "cmd",
34138
- "ctrl",
34139
- "alt",
34140
- "shift",
34141
- "fn",
34142
- "arrow-up",
34143
- "arrow-down",
34144
- "arrow-left",
34145
- "arrow-right",
34146
- "tab",
34147
- "esc",
34148
- "space",
34149
- "delete",
34150
- "return",
34151
- "enter",
34152
- "home",
34153
- "end",
34154
- "page-up",
34155
- "page-down",
34156
- ...Array.from({ length: 19 }, (_, i) => {
34157
- return `f${i + 1}`;
34158
- })
34159
- ]);
34160
- function isValidKeyName(key) {
34161
- return VALID_SPECIAL_KEYS.has(key) || key.length === 1;
34162
- }
34163
- function parseKeyCombo(keys) {
34164
- const parts = keys.split("+");
34165
- if (parts.length === 0 || parts.some((p) => {
34166
- return p === "";
34167
- })) {
34168
- throw new Error(`Invalid key combo: "${keys}"`);
33968
+ function parsePositiveInteger2(value, label) {
33969
+ if (value === void 0) {
33970
+ throw new Error(`${label} is required`);
34169
33971
  }
34170
- const mainKey = parts[parts.length - 1];
34171
- const modifiers = parts.slice(0, -1);
34172
- for (const key of parts) {
34173
- if (!isValidKeyName(key)) {
34174
- throw new Error(
34175
- `Unknown key: "${key}". Valid keys: single characters, or special keys like cmd, ctrl, alt, shift, tab, esc, return, arrow-up, f1-f19, etc.`
34176
- );
34177
- }
33972
+ const parsed = Number.parseInt(value, 10);
33973
+ if (!Number.isFinite(parsed) || parsed <= 0) {
33974
+ throw new Error(`${label} must be a positive integer`);
34178
33975
  }
34179
- return { modifiers, mainKey };
34180
- }
34181
- function keyAction(key) {
34182
- return VALID_SPECIAL_KEYS.has(key) ? `kp:${key}` : `t:${key}`;
33976
+ return parsed;
34183
33977
  }
34184
- async function pressKey(keys) {
34185
- const { modifiers, mainKey } = parseKeyCombo(keys);
34186
- if (modifiers.length === 0) {
34187
- await execFileAsync2("cliclick", [keyAction(mainKey)]);
34188
- return;
34189
- }
34190
- const args = [];
34191
- for (const mod of modifiers) {
34192
- args.push(`kd:${mod}`);
34193
- }
34194
- args.push(keyAction(mainKey));
34195
- for (let i = modifiers.length - 1; i >= 0; i--) {
34196
- args.push(`ku:${modifiers[i]}`);
33978
+ function parsePositiveNumber(value, label) {
33979
+ if (value === void 0) return void 0;
33980
+ const parsed = Number.parseFloat(value);
33981
+ if (!Number.isFinite(parsed) || parsed <= 0) {
33982
+ throw new Error(`${label} must be a positive number`);
34197
33983
  }
34198
- await execFileAsync2("cliclick", args);
34199
- }
34200
- async function holdKey(keys, durationMs) {
34201
- const { modifiers, mainKey } = parseKeyCombo(keys);
34202
- const allKeys = [...modifiers, mainKey];
34203
- const downArgs = allKeys.map((k) => {
34204
- return `kd:${k}`;
34205
- });
34206
- const upArgs = [...allKeys].reverse().map((k) => {
34207
- return `ku:${k}`;
34208
- });
34209
- await execFileAsync2("cliclick", downArgs);
34210
- await sleep2(durationMs);
34211
- await execFileAsync2("cliclick", upArgs);
34212
- }
34213
- async function typeText(text) {
34214
- await execFileAsync2("cliclick", [`t:${text}`]);
33984
+ return parsed;
34215
33985
  }
34216
-
34217
- // src/lib/computer-use/scroll.ts
34218
- init_esm_shims();
34219
- import { execFile as execFile3 } from "child_process";
34220
- import { promisify as promisify3 } from "util";
34221
- var execFileAsync3 = promisify3(execFile3);
34222
- var DEFAULT_SCROLL_AMOUNT = 3;
34223
- async function scroll(x, y, direction, amount = DEFAULT_SCROLL_AMOUNT) {
34224
- await execFileAsync3("cliclick", [`m:${x},${y}`]);
34225
- let dy = 0;
34226
- let dx = 0;
34227
- switch (direction) {
34228
- case "up":
34229
- dy = amount;
34230
- break;
34231
- case "down":
34232
- dy = -amount;
34233
- break;
34234
- case "left":
34235
- dx = amount;
34236
- break;
34237
- case "right":
34238
- dx = -amount;
34239
- break;
33986
+ function parseMouseButton(value) {
33987
+ if (value === "left" || value === "right" || value === "middle") {
33988
+ return value;
34240
33989
  }
34241
- const script = [
34242
- "ObjC.import('CoreGraphics');",
34243
- `var e = $.CGEventCreateScrollWheelEvent(null, 0, 2, ${dy}, ${dx});`,
34244
- "$.CGEventPost($.kCGHIDEventTap, e);"
34245
- ].join(" ");
34246
- await execFileAsync3("osascript", ["-l", "JavaScript", "-e", script]);
34247
- }
34248
-
34249
- // src/lib/computer-use/clipboard.ts
34250
- init_esm_shims();
34251
- import { execFile as execFile4, spawn } from "child_process";
34252
- import { promisify as promisify4 } from "util";
34253
- var execFileAsync4 = promisify4(execFile4);
34254
- async function readClipboard() {
34255
- const { stdout } = await execFileAsync4("pbpaste");
34256
- return stdout;
34257
- }
34258
- async function writeClipboard(text) {
34259
- return new Promise((resolve2, reject) => {
34260
- const proc = spawn("pbcopy", { stdio: ["pipe", "ignore", "ignore"] });
34261
- proc.on("error", reject);
34262
- proc.on("close", (code) => {
34263
- if (code === 0) {
34264
- resolve2();
34265
- } else {
34266
- reject(new Error(`pbcopy exited with code ${code}`));
34267
- }
34268
- });
34269
- proc.stdin.end(text);
34270
- });
33990
+ throw new Error("button must be left, right, or middle");
34271
33991
  }
34272
-
34273
- // src/lib/computer-use/application.ts
34274
- init_esm_shims();
34275
- import { execFile as execFile5 } from "child_process";
34276
- import { promisify as promisify5 } from "util";
34277
- var execFileAsync5 = promisify5(execFile5);
34278
- async function openApplication(nameOrBundleId) {
34279
- const isBundleId = nameOrBundleId.includes(".");
34280
- const flag = isBundleId ? "-b" : "-a";
34281
- await execFileAsync5("open", [flag, nameOrBundleId]);
34282
- }
34283
-
34284
- // src/lib/computer-use/desktop-server.ts
34285
- function readBody(req) {
34286
- return new Promise((resolve2, reject) => {
34287
- const chunks = [];
34288
- req.on("data", (chunk) => {
34289
- chunks.push(chunk);
34290
- });
34291
- req.on("end", () => {
34292
- resolve2(Buffer.concat(chunks).toString());
34293
- });
34294
- req.on("error", reject);
34295
- });
34296
- }
34297
- async function handleZoom(searchParams, res) {
34298
- const x = Number(searchParams.get("x"));
34299
- const y = Number(searchParams.get("y"));
34300
- const width = Number(searchParams.get("width"));
34301
- const height = Number(searchParams.get("height"));
34302
- if ([x, y, width, height].some((v) => {
34303
- return !Number.isFinite(v);
34304
- })) {
34305
- res.writeHead(400, { "Content-Type": "text/plain" });
34306
- res.end(
34307
- "Missing or invalid query parameters: x, y, width, height are required numbers"
34308
- );
34309
- return;
34310
- }
34311
- if (width <= 0 || height <= 0) {
34312
- res.writeHead(400, { "Content-Type": "text/plain" });
34313
- res.end("width and height must be positive");
34314
- return;
34315
- }
34316
- if (x < 0 || y < 0) {
34317
- res.writeHead(400, { "Content-Type": "text/plain" });
34318
- res.end("x and y must be non-negative");
34319
- return;
33992
+ function parseLimit4(value) {
33993
+ if (value === void 0) {
33994
+ return 50;
34320
33995
  }
34321
- const info = await getScreenInfo();
34322
- if (x + width > info.width || y + height > info.height) {
34323
- res.writeHead(400, { "Content-Type": "text/plain" });
34324
- res.end(`Region exceeds screen bounds (${info.width}x${info.height})`);
34325
- return;
33996
+ const parsed = parsePositiveInteger2(value, "limit");
33997
+ if (parsed > 200) {
33998
+ throw new Error("limit must be 200 or less");
34326
33999
  }
34327
- const result = await captureRegionScreenshot({ x, y, width, height });
34328
- res.writeHead(200, { "Content-Type": "application/json" });
34329
- res.end(JSON.stringify(result));
34330
- }
34331
- function parseJsonBody(req) {
34332
- return new Promise((resolve2, reject) => {
34333
- const chunks = [];
34334
- let size = 0;
34335
- req.on("data", (chunk) => {
34336
- size += chunk.length;
34337
- if (size > 1024) {
34338
- reject(new Error("Request body too large"));
34339
- req.destroy();
34340
- return;
34341
- }
34342
- chunks.push(chunk);
34343
- });
34344
- req.on("end", () => {
34345
- try {
34346
- resolve2(JSON.parse(Buffer.concat(chunks).toString()));
34347
- } catch {
34348
- reject(new Error("Invalid JSON body"));
34349
- }
34350
- });
34351
- req.on("error", reject);
34352
- });
34000
+ return parsed;
34353
34001
  }
34354
- async function handleMouseRequest(req, res) {
34355
- const body = await parseJsonBody(req);
34356
- if (typeof body !== "object" || body === null || !("action" in body)) {
34357
- res.writeHead(400, { "Content-Type": "text/plain" });
34358
- res.end("Missing required fields: action, x, y");
34359
- return;
34360
- }
34361
- const { action } = body;
34362
- if (typeof action !== "string") {
34363
- res.writeHead(400, { "Content-Type": "text/plain" });
34364
- res.end("Invalid action");
34365
- return;
34002
+ function resultText(command) {
34003
+ if (!command.result) {
34004
+ return "";
34366
34005
  }
34367
- if (VALID_ACTIONS.has(action)) {
34368
- if (!("x" in body) || !("y" in body)) {
34369
- res.writeHead(400, { "Content-Type": "text/plain" });
34370
- res.end("Missing required fields: action, x, y");
34371
- return;
34006
+ return JSON.stringify(command.result, null, 2);
34007
+ }
34008
+ async function waitForCommand(commandId, timeoutSeconds) {
34009
+ const deadline = Date.now() + timeoutSeconds * 1e3;
34010
+ while (Date.now() <= deadline) {
34011
+ const command = await getComputerUseCommand(commandId);
34012
+ if (command.status === "pending_approval" || command.status === "queued" || command.status === "running") {
34013
+ if (process.stdout.isTTY) {
34014
+ process.stdout.write(".");
34015
+ }
34016
+ await sleep2(1e3);
34017
+ continue;
34372
34018
  }
34373
- const { x, y } = body;
34374
- if (typeof x !== "number" || typeof y !== "number" || !Number.isFinite(x) || !Number.isFinite(y)) {
34375
- res.writeHead(400, { "Content-Type": "text/plain" });
34376
- res.end("Coordinates x and y must be finite numbers");
34377
- return;
34019
+ if (process.stdout.isTTY) {
34020
+ process.stdout.write("\n");
34378
34021
  }
34379
- const info = await getScreenInfo();
34380
- if (x < 0 || x >= info.width || y < 0 || y >= info.height) {
34381
- res.writeHead(400, { "Content-Type": "text/plain" });
34382
- res.end(
34383
- `Coordinates out of bounds. Screen size: ${info.width}x${info.height} (points)`
34022
+ if (command.status === "failed") {
34023
+ throw new Error(
34024
+ command.error ? `${command.error.code}: ${command.error.message}` : "Computer-use command failed"
34384
34025
  );
34385
- return;
34386
34026
  }
34387
- await executeMouseAction(action, x, y);
34388
- res.writeHead(200, { "Content-Type": "application/json" });
34389
- res.end(JSON.stringify({ ok: true }));
34390
- return;
34391
- }
34392
- const typedBody = body;
34393
- switch (typedBody.action) {
34394
- case "left_click_drag":
34395
- await leftClickDrag(
34396
- typedBody.startX,
34397
- typedBody.startY,
34398
- typedBody.endX,
34399
- typedBody.endY
34400
- );
34401
- break;
34402
- case "left_mouse_down":
34403
- await leftMouseDown(typedBody.x, typedBody.y);
34404
- break;
34405
- case "left_mouse_up":
34406
- await leftMouseUp(typedBody.x, typedBody.y);
34407
- break;
34408
- case "scroll":
34409
- await scroll(
34410
- typedBody.x,
34411
- typedBody.y,
34412
- typedBody.direction,
34413
- typedBody.amount
34414
- );
34415
- break;
34416
- default:
34417
- res.writeHead(400, { "Content-Type": "text/plain" });
34418
- res.end(
34419
- `Unknown mouse action: ${body.action}`
34420
- );
34421
- return;
34422
- }
34423
- res.writeHead(200, { "Content-Type": "application/json" });
34424
- res.end(JSON.stringify({ ok: true }));
34425
- }
34426
- async function handleKeyboard(req, res) {
34427
- const raw = await readBody(req);
34428
- const body = JSON.parse(raw);
34429
- switch (body.action) {
34430
- case "key":
34431
- await pressKey(body.keys);
34432
- break;
34433
- case "hold_key":
34434
- if (typeof body.durationMs !== "number" || !Number.isFinite(body.durationMs) || body.durationMs <= 0) {
34435
- res.writeHead(400, { "Content-Type": "text/plain" });
34436
- res.end("durationMs must be a positive number");
34437
- return;
34438
- }
34439
- await holdKey(body.keys, body.durationMs);
34440
- break;
34441
- case "type":
34442
- if (typeof body.text !== "string" || body.text.length === 0) {
34443
- res.writeHead(400, { "Content-Type": "text/plain" });
34444
- res.end("text must be a non-empty string");
34445
- return;
34446
- }
34447
- await typeText(body.text);
34448
- break;
34449
- default:
34450
- res.writeHead(400, { "Content-Type": "text/plain" });
34451
- res.end(
34452
- `Unknown keyboard action: ${body.action}`
34453
- );
34454
- return;
34455
- }
34456
- res.writeHead(200, { "Content-Type": "application/json" });
34457
- res.end(JSON.stringify({ ok: true }));
34458
- }
34459
- async function handleClipboard(req, res) {
34460
- if (req.method === "GET") {
34461
- const text = await readClipboard();
34462
- res.writeHead(200, { "Content-Type": "application/json" });
34463
- res.end(JSON.stringify({ text }));
34464
- } else if (req.method === "POST") {
34465
- const raw = await readBody(req);
34466
- const body = JSON.parse(raw);
34467
- await writeClipboard(body.text);
34468
- res.writeHead(200, { "Content-Type": "application/json" });
34469
- res.end(JSON.stringify({ ok: true }));
34470
- } else {
34471
- res.writeHead(404, { "Content-Type": "text/plain" });
34472
- res.end("Not found");
34473
- }
34474
- }
34475
- async function handleOpenApplication(req, res) {
34476
- const raw = await readBody(req);
34477
- const body = JSON.parse(raw);
34478
- if (typeof body.nameOrBundleId !== "string" || body.nameOrBundleId.length === 0) {
34479
- res.writeHead(400, { "Content-Type": "text/plain" });
34480
- res.end("nameOrBundleId must be a non-empty string");
34481
- return;
34482
- }
34483
- await openApplication(body.nameOrBundleId);
34484
- res.writeHead(200, { "Content-Type": "application/json" });
34485
- res.end(JSON.stringify({ ok: true }));
34486
- }
34487
- async function getRandomPort() {
34488
- return new Promise((resolve2, reject) => {
34489
- const server = createNetServer();
34490
- server.listen(0, "127.0.0.1", () => {
34491
- const { port } = server.address();
34492
- server.close(() => {
34493
- resolve2(port);
34494
- });
34495
- });
34496
- server.on("error", reject);
34497
- });
34498
- }
34499
- async function handleCursorPosition(res) {
34500
- const position = await getCursorPosition();
34501
- res.writeHead(200, { "Content-Type": "application/json" });
34502
- res.end(JSON.stringify(position));
34503
- }
34504
- function routeKey(method, pathname) {
34505
- return `${method} ${pathname}`;
34506
- }
34507
- async function handleRequest(token, req, res) {
34508
- if (req.headers["x-vm0-token"] !== token) {
34509
- res.writeHead(403, { "Content-Type": "text/plain" });
34510
- res.end("Forbidden");
34511
- return;
34512
- }
34513
- const url = new URL(req.url ?? "/", "http://localhost");
34514
- const { pathname, searchParams } = url;
34515
- const key = routeKey(req.method ?? "GET", pathname);
34516
- try {
34517
- switch (key) {
34518
- case "GET /screenshot": {
34519
- const result = await captureScreenshot();
34520
- res.writeHead(200, { "Content-Type": "application/json" });
34521
- res.end(JSON.stringify(result));
34522
- break;
34523
- }
34524
- case "GET /info": {
34525
- const info = await getScreenInfo();
34526
- res.writeHead(200, { "Content-Type": "application/json" });
34527
- res.end(JSON.stringify(info));
34528
- break;
34529
- }
34530
- case "GET /zoom":
34531
- await handleZoom(searchParams, res);
34532
- break;
34533
- case "POST /mouse":
34534
- await handleMouseRequest(req, res);
34535
- break;
34536
- case "GET /clipboard":
34537
- case "POST /clipboard":
34538
- await handleClipboard(req, res);
34539
- break;
34540
- case "POST /keyboard":
34541
- await handleKeyboard(req, res);
34542
- break;
34543
- case "POST /open-application":
34544
- await handleOpenApplication(req, res);
34545
- break;
34546
- case "GET /cursor-position":
34547
- await handleCursorPosition(res);
34548
- break;
34549
- default:
34550
- res.writeHead(404, { "Content-Type": "text/plain" });
34551
- res.end("Not found");
34027
+ const text = resultText(command);
34028
+ if (text) {
34029
+ console.log(text);
34552
34030
  }
34553
- } catch (error) {
34554
- const message = error instanceof Error ? error.message : "Internal server error";
34555
- res.writeHead(500, { "Content-Type": "text/plain" });
34556
- res.end(message);
34031
+ return;
34557
34032
  }
34033
+ throw new Error(`Computer-use command timed out: ${commandId}`);
34558
34034
  }
34559
- function startDesktopServer(token, port) {
34560
- return new Promise((resolve2, reject) => {
34561
- const server = createServer((req, res) => {
34562
- handleRequest(token, req, res).catch(() => {
34563
- if (!res.headersSent) {
34564
- res.writeHead(500, { "Content-Type": "text/plain" });
34565
- res.end("Internal server error");
34566
- }
34567
- });
34568
- });
34569
- server.on("error", reject);
34570
- server.listen(port, "127.0.0.1", () => {
34571
- resolve2(server);
34572
- });
34035
+ async function runReadCommand(kind, options, payload = {}) {
34036
+ const timeoutSeconds = parseTimeoutSeconds(options.timeout);
34037
+ const created = await createComputerUseReadCommand({
34038
+ kind,
34039
+ timeoutMs: timeoutSeconds * 1e3,
34040
+ ...options.host ? { hostName: options.host } : {},
34041
+ ...options.hostId ? { hostId: options.hostId } : {},
34042
+ ...payload
34573
34043
  });
34044
+ await waitForCommand(created.commandId, timeoutSeconds);
34574
34045
  }
34575
-
34576
- // src/lib/computer-use/ngrok.ts
34577
- init_esm_shims();
34578
- async function loadNgrok() {
34579
- try {
34580
- const mod = await import("@ngrok/ngrok");
34581
- return mod.default;
34582
- } catch (cause) {
34583
- throw new Error(
34584
- "Failed to load ngrok tunnel module. This may be caused by a system library (GLIBC) incompatibility. See: https://github.com/vm0-ai/vm0/issues/6825",
34585
- { cause }
34586
- );
34587
- }
34588
- }
34589
- async function startDesktopTunnel(ngrokToken, endpointPrefix, port) {
34590
- const ngrok = await loadNgrok();
34591
- await ngrok.forward({
34592
- addr: `localhost:${port}`,
34593
- authtoken: ngrokToken,
34594
- domain: `desktop.${endpointPrefix}.internal`
34046
+ async function runWriteCommand(kind, options, payload) {
34047
+ const timeoutSeconds = parseTimeoutSeconds(options.timeout);
34048
+ const created = await createComputerUseWriteCommand({
34049
+ kind,
34050
+ timeoutMs: timeoutSeconds * 1e3,
34051
+ ...options.host ? { hostName: options.host } : {},
34052
+ ...options.hostId ? { hostId: options.hostId } : {},
34053
+ ...payload
34595
34054
  });
34055
+ await waitForCommand(created.commandId, timeoutSeconds);
34596
34056
  }
34597
- async function stopDesktopTunnel() {
34598
- const ngrok = await loadNgrok();
34599
- await ngrok.kill();
34600
- }
34601
-
34602
- // src/commands/zero/computer-use/host.ts
34603
- var hostStartCommand = new Command().name("start").description("Start the computer-use host daemon (macOS only)").action(
34604
- withErrorHandler(async () => {
34605
- if (process.platform !== "darwin") {
34606
- throw new Error(
34607
- "Computer-use host requires macOS\n\nThe host daemon uses macOS-specific commands (screencapture, system_profiler)."
34608
- );
34609
- }
34610
- if (!await isCliclickInstalled()) {
34611
- console.log(
34612
- source_default.yellow(
34613
- "\u26A0 cliclick not found. Mouse and keyboard operations will not be available.\n Install with: brew install cliclick"
34614
- )
34615
- );
34616
- console.log();
34617
- }
34618
- console.log(source_default.cyan("Registering computer-use host..."));
34619
- const credentials = await registerComputerUseHost();
34620
- const port = await getRandomPort();
34621
- const server = await startDesktopServer(credentials.token, port);
34622
- try {
34623
- await startDesktopTunnel(
34624
- credentials.ngrokToken,
34625
- credentials.endpointPrefix,
34626
- port
34627
- );
34628
- console.log();
34629
- console.log(source_default.green("\u2713 Computer-use host active"));
34630
- console.log(` Desktop: desktop.${credentials.domain}`);
34631
- console.log();
34632
- console.log(source_default.dim("Press ^C twice to disconnect"));
34633
- console.log();
34634
- let sigintCount = 0;
34635
- await new Promise((resolve2) => {
34636
- const keepAlive = setInterval(() => {
34637
- }, 6e4);
34638
- const done = () => {
34639
- clearInterval(keepAlive);
34640
- process.removeListener("SIGINT", onSigint);
34641
- resolve2();
34642
- };
34643
- const onSigint = () => {
34644
- sigintCount++;
34645
- if (sigintCount === 1) {
34646
- console.log(
34647
- source_default.dim("\nPress ^C again to disconnect and exit...")
34648
- );
34649
- } else {
34650
- done();
34651
- }
34652
- };
34653
- process.on("SIGINT", onSigint);
34654
- process.once("SIGTERM", done);
34655
- });
34656
- } finally {
34657
- console.log();
34658
- console.log(source_default.cyan("Stopping computer-use host..."));
34659
- server.close();
34660
- await stopDesktopTunnel();
34661
- await unregisterComputerUseHost().catch(() => {
34662
- });
34663
- console.log(source_default.green("\u2713 Host stopped"));
34664
- }
34665
- })
34666
- );
34667
- var hostStopCommand = new Command().name("stop").description("Stop and unregister the computer-use host").action(
34668
- withErrorHandler(async () => {
34669
- console.log(source_default.cyan("Unregistering computer-use host..."));
34670
- try {
34671
- await unregisterComputerUseHost();
34672
- console.log(source_default.green("\u2713 Host unregistered"));
34673
- } catch (error) {
34674
- if (error instanceof ApiRequestError && error.status === 404) {
34675
- console.log(source_default.yellow("No active host registration found"));
34676
- return;
34677
- }
34678
- throw error;
34679
- }
34680
- })
34681
- );
34682
-
34683
- // src/commands/zero/computer-use/client.ts
34684
- init_esm_shims();
34685
- import { writeFile, mkdir } from "fs/promises";
34686
- import { basename as basename7, join as join6 } from "path";
34687
-
34688
- // src/lib/computer-use/client.ts
34689
- init_esm_shims();
34690
- var cachedHost = null;
34691
- var CACHE_TTL_MS = 3e4;
34692
- async function discoverHost() {
34693
- if (cachedHost && Date.now() - cachedHost.cachedAt < CACHE_TTL_MS) {
34694
- return { domain: cachedHost.domain, token: cachedHost.token };
34695
- }
34696
- const host = await getComputerUseHost();
34697
- if (!host) {
34698
- throw new Error(
34699
- "No active computer-use host found\n\nStart a host with: zero computer-use host start"
34700
- );
34701
- }
34702
- cachedHost = { ...host, cachedAt: Date.now() };
34703
- return host;
34704
- }
34705
- async function callHost(path, options) {
34706
- const { domain, token } = await discoverHost();
34707
- const url = `https://desktop.${domain}${path}`;
34708
- const headers = { "x-vm0-token": token };
34709
- const init = { headers };
34710
- if (options?.method) {
34711
- init.method = options.method;
34712
- }
34713
- if (options?.body !== void 0) {
34714
- headers["content-type"] = "application/json";
34715
- init.body = JSON.stringify(options.body);
34716
- }
34717
- const response = await fetch(url, init);
34718
- if (!response.ok) {
34719
- const body = await response.text().catch(() => {
34720
- return "";
34721
- });
34722
- throw new Error(
34723
- `Host returned ${response.status}: ${body || response.statusText}`
34724
- );
34725
- }
34726
- return response;
34057
+ function addTargetOptions(command) {
34058
+ return command.option("--host <name>", "Run on a named computer-use host").option("--host-id <id>", "Run on a specific computer-use host id").option("--timeout <seconds>", "Maximum time to wait", "30");
34727
34059
  }
34728
-
34729
- // src/commands/zero/computer-use/client.ts
34730
- function safeFormat(format) {
34731
- return basename7(format);
34060
+ function appOption(command) {
34061
+ return command.requiredOption("--app <name>", "Target app name or bundle id");
34732
34062
  }
34733
- function mouseClickCommand(name, action, description) {
34734
- return new Command().name(name).description(description).argument("<x>", "X coordinate (points)").argument("<y>", "Y coordinate (points)").action(
34735
- withErrorHandler(async (xStr, yStr) => {
34736
- const x = parseInt(xStr, 10);
34737
- const y = parseInt(yStr, 10);
34738
- if (Number.isNaN(x) || Number.isNaN(y)) {
34739
- throw new Error("Coordinates must be integers");
34740
- }
34741
- const response = await callHost("/mouse", {
34742
- method: "POST",
34743
- body: { action, x, y }
34744
- });
34745
- const data = await response.json();
34746
- process.stdout.write(JSON.stringify(data) + "\n");
34063
+ function formatAuditEvent(event) {
34064
+ return [
34065
+ `${event.createdAt} ${event.event} ${event.kind}`,
34066
+ `command=${event.commandId}`,
34067
+ event.hostId ? `host=${event.hostId}` : null,
34068
+ event.app ? `app=${event.app}` : null,
34069
+ event.approvalOutcome ? `approval=${event.approvalOutcome}` : null
34070
+ ].filter((part) => {
34071
+ return part !== null;
34072
+ }).join(" ");
34073
+ }
34074
+ var listAppsCommand = addTargetOptions(
34075
+ new Command().name("list-apps").description("List apps available to the Desktop Computer Use host").action(
34076
+ withErrorHandler(async (options) => {
34077
+ await runReadCommand("apps.list", options);
34747
34078
  })
34748
- );
34749
- }
34750
- var clientScreenshotCommand = new Command().name("screenshot").description("Capture a screenshot from the remote host").action(
34751
- withErrorHandler(async () => {
34752
- const response = await callHost("/screenshot");
34753
- const data = await response.json();
34754
- const dir = "/tmp/computer-use";
34755
- await mkdir(dir, { recursive: true });
34756
- const timestamp = Date.now();
34757
- const filePath = join6(
34758
- dir,
34759
- `screenshot-${timestamp}.${safeFormat(data.format)}`
34760
- );
34761
- const buffer = Buffer.from(data.image, "base64");
34762
- await writeFile(filePath, buffer);
34763
- process.stdout.write(`${filePath}
34764
- `);
34765
- process.stderr.write(
34766
- JSON.stringify({
34767
- width: data.width,
34768
- height: data.height,
34769
- scaleFactor: data.scaleFactor
34770
- }) + "\n"
34771
- );
34772
- })
34773
- );
34774
- var clientZoomCommand = new Command().name("zoom").description("Capture a region screenshot from the remote host").requiredOption("--x <number>", "X coordinate of the region").requiredOption("--y <number>", "Y coordinate of the region").requiredOption("--width <number>", "Width of the region").requiredOption("--height <number>", "Height of the region").action(
34775
- withErrorHandler(
34776
- async (opts) => {
34777
- const params = new URLSearchParams({
34778
- x: opts.x,
34779
- y: opts.y,
34780
- width: opts.width,
34781
- height: opts.height
34782
- });
34783
- const response = await callHost(`/zoom?${params.toString()}`);
34784
- const data = await response.json();
34785
- const dir = "/tmp/computer-use";
34786
- await mkdir(dir, { recursive: true });
34787
- const timestamp = Date.now();
34788
- const filePath = join6(
34789
- dir,
34790
- `zoom-${timestamp}.${safeFormat(data.format)}`
34791
- );
34792
- const buffer = Buffer.from(data.image, "base64");
34793
- await writeFile(filePath, buffer);
34794
- process.stdout.write(`${filePath}
34795
- `);
34796
- process.stderr.write(
34797
- JSON.stringify({
34798
- width: data.width,
34799
- height: data.height,
34800
- scaleFactor: data.scaleFactor
34801
- }) + "\n"
34802
- );
34803
- }
34804
34079
  )
34805
34080
  );
34806
- var clientInfoCommand = new Command().name("info").description("Get screen info from the remote host").action(
34807
- withErrorHandler(async () => {
34808
- const response = await callHost("/info");
34809
- const data = await response.json();
34810
- process.stdout.write(JSON.stringify(data) + "\n");
34811
- })
34812
- );
34813
- var clientLeftClickCommand = mouseClickCommand(
34814
- "left-click",
34815
- "left_click",
34816
- "Perform a left click at coordinates"
34817
- );
34818
- var clientRightClickCommand = mouseClickCommand(
34819
- "right-click",
34820
- "right_click",
34821
- "Perform a right click at coordinates"
34081
+ var getAppStateCommand = appOption(
34082
+ addTargetOptions(
34083
+ new Command().name("get-app-state").description("Get screenshot and accessibility state for an app").action(
34084
+ withErrorHandler(async (options) => {
34085
+ await runReadCommand("app.state", options, { app: options.app });
34086
+ })
34087
+ )
34088
+ )
34822
34089
  );
34823
- var clientMiddleClickCommand = mouseClickCommand(
34824
- "middle-click",
34825
- "middle_click",
34826
- "Perform a middle click at coordinates"
34090
+ var clickCommand = appOption(
34091
+ addTargetOptions(
34092
+ new Command().name("click").description("Click an accessibility element or screenshot coordinate").option("--snapshot-id <id>", "Snapshot id returned by get-app-state").option("--element <id>", "Element id from get-app-state").option("--x <points>", "Screenshot x coordinate fallback").option("--y <points>", "Screenshot y coordinate fallback").option("--button <button>", "Mouse button", "left").option("--click-count <count>", "Number of clicks", "1").action(
34093
+ withErrorHandler(async (options) => {
34094
+ const x = parseOptionalNonNegativeInteger(options.x, "x");
34095
+ const y = parseOptionalNonNegativeInteger(options.y, "y");
34096
+ await runWriteCommand("element.click", options, {
34097
+ app: options.app,
34098
+ ...options.snapshotId ? { snapshotId: options.snapshotId } : {},
34099
+ ...options.element ? { elementId: options.element } : {},
34100
+ ...x !== void 0 ? { x } : {},
34101
+ ...y !== void 0 ? { y } : {},
34102
+ button: parseMouseButton(options.button),
34103
+ clickCount: parsePositiveInteger2(options.clickCount, "click-count")
34104
+ });
34105
+ })
34106
+ )
34107
+ )
34827
34108
  );
34828
- var clientDoubleClickCommand = mouseClickCommand(
34829
- "double-click",
34830
- "double_click",
34831
- "Perform a double click at coordinates"
34109
+ var scrollCommand = appOption(
34110
+ addTargetOptions(
34111
+ new Command().name("scroll").description("Scroll an accessibility element").option("--snapshot-id <id>", "Snapshot id returned by get-app-state").requiredOption("--element <id>", "Element id from get-app-state").requiredOption(
34112
+ "--direction <direction>",
34113
+ "Scroll direction: up, down, left, or right"
34114
+ ).option("--pages <count>", "Number of pages to scroll", "1").action(
34115
+ withErrorHandler(async (options) => {
34116
+ await runWriteCommand("element.scroll", options, {
34117
+ app: options.app,
34118
+ ...options.snapshotId ? { snapshotId: options.snapshotId } : {},
34119
+ elementId: options.element,
34120
+ direction: options.direction,
34121
+ pages: parsePositiveNumber(options.pages, "pages")
34122
+ });
34123
+ })
34124
+ )
34125
+ )
34832
34126
  );
34833
- var clientTripleClickCommand = mouseClickCommand(
34834
- "triple-click",
34835
- "triple_click",
34836
- "Perform a triple click at coordinates"
34127
+ var setValueCommand = appOption(
34128
+ addTargetOptions(
34129
+ new Command().name("set-value").description("Set the value of a settable accessibility element").option("--snapshot-id <id>", "Snapshot id returned by get-app-state").requiredOption("--element <id>", "Element id from get-app-state").requiredOption("--value <text>", "Value to assign").action(
34130
+ withErrorHandler(async (options) => {
34131
+ await runWriteCommand("element.set_value", options, {
34132
+ app: options.app,
34133
+ ...options.snapshotId ? { snapshotId: options.snapshotId } : {},
34134
+ elementId: options.element,
34135
+ value: options.value
34136
+ });
34137
+ })
34138
+ )
34139
+ )
34837
34140
  );
34838
- var clientLeftClickDragCommand = new Command().name("left-click-drag").description("Drag from (startX, startY) to (endX, endY)").argument("<startX>", "Start X coordinate").argument("<startY>", "Start Y coordinate").argument("<endX>", "End X coordinate").argument("<endY>", "End Y coordinate").action(
34839
- withErrorHandler(
34840
- async (startX, startY, endX, endY) => {
34841
- await callHost("/mouse", {
34842
- method: "POST",
34843
- body: {
34844
- action: "left_click_drag",
34845
- startX: Number(startX),
34846
- startY: Number(startY),
34847
- endX: Number(endX),
34848
- endY: Number(endY)
34849
- }
34850
- });
34851
- process.stdout.write("ok\n");
34852
- }
34141
+ var typeTextCommand = appOption(
34142
+ addTargetOptions(
34143
+ new Command().name("type-text").description("Type literal text into the target app").requiredOption("--text <text>", "Text to type").action(
34144
+ withErrorHandler(async (options) => {
34145
+ await runWriteCommand("keyboard.type_text", options, {
34146
+ app: options.app,
34147
+ text: options.text
34148
+ });
34149
+ })
34150
+ )
34853
34151
  )
34854
34152
  );
34855
- var clientLeftMouseDownCommand = new Command().name("left-mouse-down").description("Press and hold the left mouse button at (x, y)").argument("<x>", "X coordinate").argument("<y>", "Y coordinate").action(
34856
- withErrorHandler(async (x, y) => {
34857
- await callHost("/mouse", {
34858
- method: "POST",
34859
- body: { action: "left_mouse_down", x: Number(x), y: Number(y) }
34860
- });
34861
- process.stdout.write("ok\n");
34862
- })
34153
+ var pressKeyCommand = appOption(
34154
+ addTargetOptions(
34155
+ new Command().name("press-key").description("Press a key or key combination in the target app").requiredOption("--key <key>", "Key or key combination to press").action(
34156
+ withErrorHandler(async (options) => {
34157
+ await runWriteCommand("keyboard.press_key", options, {
34158
+ app: options.app,
34159
+ key: options.key
34160
+ });
34161
+ })
34162
+ )
34163
+ )
34863
34164
  );
34864
- var clientLeftMouseUpCommand = new Command().name("left-mouse-up").description("Release the left mouse button at (x, y)").argument("<x>", "X coordinate").argument("<y>", "Y coordinate").action(
34865
- withErrorHandler(async (x, y) => {
34866
- await callHost("/mouse", {
34867
- method: "POST",
34868
- body: { action: "left_mouse_up", x: Number(x), y: Number(y) }
34869
- });
34870
- process.stdout.write("ok\n");
34871
- })
34165
+ var performActionCommand = appOption(
34166
+ addTargetOptions(
34167
+ new Command().name("perform-action").description("Invoke a secondary accessibility action").option("--snapshot-id <id>", "Snapshot id returned by get-app-state").requiredOption("--element <id>", "Element id from get-app-state").requiredOption("--action <name>", "Accessibility action name").action(
34168
+ withErrorHandler(async (options) => {
34169
+ await runWriteCommand("element.perform_action", options, {
34170
+ app: options.app,
34171
+ ...options.snapshotId ? { snapshotId: options.snapshotId } : {},
34172
+ elementId: options.element,
34173
+ action: options.action
34174
+ });
34175
+ })
34176
+ )
34177
+ )
34872
34178
  );
34873
- var clientScrollCommand = new Command().name("scroll").description("Scroll at the given screen position").argument("<x>", "X coordinate").argument("<y>", "Y coordinate").argument("<direction>", "Scroll direction: up, down, left, right").argument("[amount]", "Scroll amount in lines (default 3)").action(
34874
- withErrorHandler(
34875
- async (x, y, direction, amount) => {
34876
- await callHost("/mouse", {
34877
- method: "POST",
34878
- body: {
34879
- action: "scroll",
34880
- x: Number(x),
34881
- y: Number(y),
34882
- direction,
34883
- ...amount !== void 0 && { amount: Number(amount) }
34884
- }
34885
- });
34886
- process.stdout.write("ok\n");
34887
- }
34179
+ var openAppCommand = appOption(
34180
+ addTargetOptions(
34181
+ new Command().name("open-app").description("Open or activate an app on the Desktop host").action(
34182
+ withErrorHandler(async (options) => {
34183
+ await runWriteCommand("app.open", options, { app: options.app });
34184
+ })
34185
+ )
34888
34186
  )
34889
34187
  );
34890
- var clientReadClipboardCommand = new Command().name("read-clipboard").description("Read text content from the remote clipboard").action(
34188
+ var hostsCommand = new Command().name("hosts").description("List linked Desktop Computer Use hosts").action(
34891
34189
  withErrorHandler(async () => {
34892
- const response = await callHost("/clipboard");
34893
- const data = await response.json();
34894
- process.stdout.write(data.text);
34190
+ const { hosts } = await listComputerUseHosts();
34191
+ console.log(JSON.stringify({ hosts }, null, 2));
34895
34192
  })
34896
34193
  );
34897
- var clientWriteClipboardCommand = new Command().name("write-clipboard").description("Write text content to the remote clipboard").argument("<text>", "Text to write to clipboard").action(
34898
- withErrorHandler(async (text) => {
34899
- await callHost("/clipboard", {
34900
- method: "POST",
34901
- body: { text }
34902
- });
34903
- process.stdout.write("ok\n");
34904
- })
34905
- );
34906
- var clientKeyCommand = new Command().name("key").description("Press a key or key combination (e.g., cmd+c, return)").argument("<combo>", "Key combo string (e.g., cmd+c, ctrl+shift+s, return)").action(
34907
- withErrorHandler(async (combo) => {
34908
- await callHost("/keyboard", {
34909
- method: "POST",
34910
- body: { action: "key", keys: combo }
34911
- });
34912
- process.stdout.write("ok\n");
34194
+ var revokeHostCommand = new Command().name("revoke-host").description("Revoke a linked Desktop Computer Use host").argument("<host-id>").action(
34195
+ withErrorHandler(async (hostId) => {
34196
+ await deleteComputerUseHost(hostId);
34197
+ console.log(`Revoked computer-use host ${hostId}`);
34913
34198
  })
34914
34199
  );
34915
- var clientHoldKeyCommand = new Command().name("hold-key").description("Hold a key or key combination for a duration").argument("<combo>", "Key combo string (e.g., shift, cmd+shift)").argument("<durationMs>", "Duration to hold in milliseconds").action(
34916
- withErrorHandler(async (combo, durationStr) => {
34917
- const durationMs = parseInt(durationStr, 10);
34918
- if (Number.isNaN(durationMs) || durationMs <= 0) {
34919
- throw new Error("durationMs must be a positive integer");
34920
- }
34921
- await callHost("/keyboard", {
34922
- method: "POST",
34923
- body: { action: "hold_key", keys: combo, durationMs }
34924
- });
34925
- process.stdout.write("ok\n");
34926
- })
34927
- );
34928
- var clientTypeCommand = new Command().name("type").description("Type text at the current cursor position").argument("<text>", "Text to type").action(
34929
- withErrorHandler(async (text) => {
34930
- await callHost("/keyboard", {
34931
- method: "POST",
34932
- body: { action: "type", text }
34933
- });
34934
- process.stdout.write("ok\n");
34935
- })
34936
- );
34937
- var clientOpenAppCommand = new Command().name("open-app").description("Open or activate a macOS application by name or bundle ID").argument(
34938
- "<nameOrBundleId>",
34939
- "App name (e.g., Safari) or bundle ID (e.g., com.apple.Safari)"
34940
- ).action(
34941
- withErrorHandler(async (nameOrBundleId) => {
34942
- await callHost("/open-application", {
34943
- method: "POST",
34944
- body: { nameOrBundleId }
34200
+ var auditCommand = new Command().name("audit").description("List Desktop Computer Use write-command audit events").option("--limit <count>", "Maximum events to return", "50").option("--command-id <id>", "Filter by command id").option("--host-id <id>", "Filter by host id").option("--run-id <id>", "Filter by run id").action(
34201
+ withErrorHandler(async (options) => {
34202
+ const { auditEvents } = await listComputerUseAuditEvents({
34203
+ limit: parseLimit4(options.limit),
34204
+ ...options.commandId ? { commandId: options.commandId } : {},
34205
+ ...options.hostId ? { hostId: options.hostId } : {},
34206
+ ...options.runId ? { runId: options.runId } : {}
34945
34207
  });
34946
- process.stdout.write("ok\n");
34947
- })
34948
- );
34949
- var clientMouseMoveCommand = mouseClickCommand(
34950
- "mouse-move",
34951
- "move",
34952
- "Move mouse pointer to coordinates"
34953
- );
34954
- var clientCursorPositionCommand = new Command().name("cursor-position").description("Get current cursor position from the remote host").action(
34955
- withErrorHandler(async () => {
34956
- const response = await callHost("/cursor-position");
34957
- const data = await response.json();
34958
- process.stdout.write(JSON.stringify(data) + "\n");
34208
+ for (const event of auditEvents) {
34209
+ console.log(formatAuditEvent(event));
34210
+ }
34959
34211
  })
34960
34212
  );
34961
-
34962
- // src/commands/zero/computer-use/index.ts
34963
- var hostCommand = new Command().name("host").description("Manage computer-use host daemon").addCommand(hostStartCommand).addCommand(hostStopCommand);
34964
- var clientCommand = new Command().name("client").description("Interact with remote computer-use host").addCommand(clientScreenshotCommand).addCommand(clientZoomCommand).addCommand(clientInfoCommand).addCommand(clientLeftClickCommand).addCommand(clientRightClickCommand).addCommand(clientMiddleClickCommand).addCommand(clientDoubleClickCommand).addCommand(clientTripleClickCommand).addCommand(clientLeftClickDragCommand).addCommand(clientLeftMouseDownCommand).addCommand(clientLeftMouseUpCommand).addCommand(clientScrollCommand).addCommand(clientReadClipboardCommand).addCommand(clientWriteClipboardCommand).addCommand(clientKeyCommand).addCommand(clientHoldKeyCommand).addCommand(clientTypeCommand).addCommand(clientOpenAppCommand).addCommand(clientMouseMoveCommand).addCommand(clientCursorPositionCommand);
34965
- clientCommand.addHelpText(
34966
- "after",
34967
- `
34968
- Coordinate System:
34969
- All coordinates use macOS logical points, not physical pixels.
34970
- On Retina displays, logical size = physical size / scaleFactor.
34971
- Run "info" to check your screen's logical dimensions.
34972
-
34973
- Examples:
34974
- zero computer-use client screenshot
34975
- zero computer-use client zoom --x 0 --y 0 --width 500 --height 500
34976
- zero computer-use client info
34977
- zero computer-use client left-click 500 300
34978
- zero computer-use client scroll 500 300 down 5
34979
- zero computer-use client key "cmd+c"`
34980
- );
34981
- var zeroComputerUseCommand = new Command().name("computer-use").description("Remote desktop control for cloud agents").addCommand(hostCommand).addCommand(clientCommand);
34213
+ var zeroComputerUseCommand = new Command().name("computer-use").description("Desktop app computer use through Zero CLI").addCommand(listAppsCommand).addCommand(getAppStateCommand).addCommand(clickCommand).addCommand(scrollCommand).addCommand(setValueCommand).addCommand(typeTextCommand).addCommand(pressKeyCommand).addCommand(performActionCommand).addCommand(openAppCommand).addCommand(hostsCommand).addCommand(revokeHostCommand).addCommand(auditCommand);
34982
34214
 
34983
34215
  // src/commands/zero/built-in/index.ts
34984
34216
  init_esm_shims();
@@ -35418,17 +34650,17 @@ var videoCommand = createVideoGenerateCommand({
35418
34650
  init_esm_shims();
35419
34651
  import { mkdtemp, rm } from "fs/promises";
35420
34652
  import { readFileSync as readFileSync15 } from "fs";
35421
- import { join as join8 } from "path";
35422
- import { tmpdir as tmpdir5 } from "os";
34653
+ import { join as join6 } from "path";
34654
+ import { tmpdir as tmpdir4 } from "os";
35423
34655
 
35424
34656
  // src/lib/host/publish-static-site.ts
35425
34657
  init_esm_shims();
35426
- import { readFile as readFile3 } from "fs/promises";
34658
+ import { readFile as readFile2 } from "fs/promises";
35427
34659
 
35428
34660
  // src/lib/host/static-site.ts
35429
34661
  init_esm_shims();
35430
34662
  import { createHash } from "crypto";
35431
- import { readdir, readFile as readFile2, stat } from "fs/promises";
34663
+ import { readdir, readFile, stat } from "fs/promises";
35432
34664
  import { extname as extname3, relative, resolve, sep, dirname, posix } from "path";
35433
34665
  var MIME_BY_EXTENSION3 = {
35434
34666
  ".html": "text/html; charset=utf-8",
@@ -35552,7 +34784,7 @@ function collectReferences(ext, text) {
35552
34784
  return isHtmlExtension(ext) ? collectHtmlReferences(text) : collectCssReferences(text);
35553
34785
  }
35554
34786
  async function hashFile(path) {
35555
- const bytes = await readFile2(path);
34787
+ const bytes = await readFile(path);
35556
34788
  return createHash("sha256").update(bytes).digest("hex");
35557
34789
  }
35558
34790
  async function walk(root, dir, files) {
@@ -35592,7 +34824,7 @@ async function assertReferencesExist(files) {
35592
34824
  if (!shouldValidateReferences(ext)) {
35593
34825
  continue;
35594
34826
  }
35595
- const text = await readFile2(file.absolutePath, "utf8");
34827
+ const text = await readFile(file.absolutePath, "utf8");
35596
34828
  const references = collectReferences(ext, text);
35597
34829
  for (const reference of references) {
35598
34830
  const normalized = normalizeReference(file.path, reference);
@@ -35666,7 +34898,7 @@ async function publishStaticSite(options) {
35666
34898
  throw new Error(`Missing upload URL for ${file.path}`);
35667
34899
  }
35668
34900
  options.onProgress?.({ phase: "uploading", path: file.path });
35669
- const bytes = await readFile3(file.absolutePath);
34901
+ const bytes = await readFile2(file.absolutePath);
35670
34902
  const response = await fetch(uploadUrl, {
35671
34903
  method: "PUT",
35672
34904
  headers: { "Content-Type": file.contentType },
@@ -35693,8 +34925,8 @@ async function publishStaticSite(options) {
35693
34925
  init_esm_shims();
35694
34926
  var import_react = __toESM(require_react(), 1);
35695
34927
  var import_server = __toESM(require_server_node(), 1);
35696
- import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
35697
- import { join as join7 } from "path";
34928
+ import { mkdir, writeFile } from "fs/promises";
34929
+ import { join as join5 } from "path";
35698
34930
  function h(type, props, ...children) {
35699
34931
  return import_react.default.createElement(type, props, ...children);
35700
34932
  }
@@ -36344,19 +35576,19 @@ h1 {
36344
35576
  }
36345
35577
  `;
36346
35578
  async function buildGeneratedWebsite(options) {
36347
- const assetsDir = join7(options.outDir, "assets");
36348
- await mkdir2(assetsDir, { recursive: true });
35579
+ const assetsDir = join5(options.outDir, "assets");
35580
+ await mkdir(assetsDir, { recursive: true });
36349
35581
  const markup = (0, import_server.renderToStaticMarkup)(
36350
35582
  import_react.default.createElement(WebsiteDocument, {
36351
35583
  data: options.siteData,
36352
35584
  templateId: options.templateId
36353
35585
  })
36354
35586
  );
36355
- await writeFile2(
36356
- join7(options.outDir, "index.html"),
35587
+ await writeFile(
35588
+ join5(options.outDir, "index.html"),
36357
35589
  `<!doctype html>${markup}`
36358
35590
  );
36359
- await writeFile2(join7(assetsDir, "styles.css"), WEBSITE_CSS.trimStart());
35591
+ await writeFile(join5(assetsDir, "styles.css"), WEBSITE_CSS.trimStart());
36360
35592
  }
36361
35593
 
36362
35594
  // src/commands/zero/built-in/generate/website.ts
@@ -36423,8 +35655,8 @@ Notes:
36423
35655
  title: options.title,
36424
35656
  audience: options.audience
36425
35657
  });
36426
- const buildRoot = await mkdtemp(join8(tmpdir5(), "zero-website-"));
36427
- const outDir = join8(buildRoot, "dist");
35658
+ const buildRoot = await mkdtemp(join6(tmpdir4(), "zero-website-"));
35659
+ const outDir = join6(buildRoot, "dist");
36428
35660
  try {
36429
35661
  if (!options.json) {
36430
35662
  console.log(source_default.dim("Building React template..."));
@@ -36597,10 +35829,10 @@ init_esm_shims();
36597
35829
 
36598
35830
  // src/commands/zero/web/download-file.ts
36599
35831
  init_esm_shims();
36600
- import { basename as basename8, join as join9 } from "path";
36601
- import { tmpdir as tmpdir6 } from "os";
35832
+ import { basename as basename7, join as join7 } from "path";
35833
+ import { tmpdir as tmpdir5 } from "os";
36602
35834
  function defaultOutPath4(fileId) {
36603
- return join9(tmpdir6(), `web-${basename8(fileId)}`);
35835
+ return join7(tmpdir5(), `web-${basename7(fileId)}`);
36604
35836
  }
36605
35837
  var downloadFileCommand4 = new Command().name("download-file").description("Download a web-uploaded file by id").argument("<file-id>", "File id (UUID returned by the upload API)").option(
36606
35838
  "-o, --out <path>",
@@ -36685,7 +35917,7 @@ function sleep3(ms) {
36685
35917
  setTimeout(resolve2, ms);
36686
35918
  });
36687
35919
  }
36688
- function parseTimeoutSeconds(value) {
35920
+ function parseTimeoutSeconds2(value) {
36689
35921
  if (!value) return 30;
36690
35922
  const seconds = Number.parseInt(value, 10);
36691
35923
  if (!Number.isFinite(seconds) || seconds <= 0) {
@@ -36693,7 +35925,7 @@ function parseTimeoutSeconds(value) {
36693
35925
  }
36694
35926
  return seconds;
36695
35927
  }
36696
- function parseOptionalNonNegativeInteger(value, label) {
35928
+ function parseOptionalNonNegativeInteger2(value, label) {
36697
35929
  if (value === void 0) return void 0;
36698
35930
  const parsed = Number.parseInt(value, 10);
36699
35931
  if (!Number.isFinite(parsed) || parsed < 0) {
@@ -36701,7 +35933,7 @@ function parseOptionalNonNegativeInteger(value, label) {
36701
35933
  }
36702
35934
  return parsed;
36703
35935
  }
36704
- function parsePositiveInteger2(value, label) {
35936
+ function parsePositiveInteger3(value, label) {
36705
35937
  if (value === void 0) {
36706
35938
  throw new Error(`${label} is required`);
36707
35939
  }
@@ -36711,24 +35943,24 @@ function parsePositiveInteger2(value, label) {
36711
35943
  }
36712
35944
  return parsed;
36713
35945
  }
36714
- function parseLimit4(value) {
35946
+ function parseLimit5(value) {
36715
35947
  if (value === void 0) {
36716
35948
  return 50;
36717
35949
  }
36718
- const parsed = parsePositiveInteger2(value, "limit");
35950
+ const parsed = parsePositiveInteger3(value, "limit");
36719
35951
  if (parsed > 200) {
36720
35952
  throw new Error("limit must be 200 or less");
36721
35953
  }
36722
35954
  return parsed;
36723
35955
  }
36724
- function resultText(command) {
35956
+ function resultText2(command) {
36725
35957
  if (!command.result) {
36726
35958
  return "";
36727
35959
  }
36728
35960
  return JSON.stringify(command.result, null, 2);
36729
35961
  }
36730
- async function runReadCommand(kind, options) {
36731
- const timeoutSeconds = parseTimeoutSeconds(options.timeout);
35962
+ async function runReadCommand2(kind, options) {
35963
+ const timeoutSeconds = parseTimeoutSeconds2(options.timeout);
36732
35964
  const created = await createLocalBrowserReadCommand({
36733
35965
  kind,
36734
35966
  timeoutMs: timeoutSeconds * 1e3,
@@ -36754,7 +35986,7 @@ async function runReadCommand(kind, options) {
36754
35986
  command.error ? `${command.error.code}: ${command.error.message}` : "Local-browser command failed"
36755
35987
  );
36756
35988
  }
36757
- const text = resultText(command);
35989
+ const text = resultText2(command);
36758
35990
  if (text) {
36759
35991
  console.log(text);
36760
35992
  }
@@ -36762,7 +35994,7 @@ async function runReadCommand(kind, options) {
36762
35994
  }
36763
35995
  throw new Error(`Local-browser command timed out: ${created.commandId}`);
36764
35996
  }
36765
- async function waitForCommand(commandId, timeoutSeconds) {
35997
+ async function waitForCommand2(commandId, timeoutSeconds) {
36766
35998
  const deadline = Date.now() + timeoutSeconds * 1e3;
36767
35999
  while (Date.now() <= deadline) {
36768
36000
  const command = await getLocalBrowserReadCommand(commandId);
@@ -36781,7 +36013,7 @@ async function waitForCommand(commandId, timeoutSeconds) {
36781
36013
  command.error ? `${command.error.code}: ${command.error.message}` : "Local-browser command failed"
36782
36014
  );
36783
36015
  }
36784
- const text = resultText(command);
36016
+ const text = resultText2(command);
36785
36017
  if (text) {
36786
36018
  console.log(text);
36787
36019
  }
@@ -36789,8 +36021,8 @@ async function waitForCommand(commandId, timeoutSeconds) {
36789
36021
  }
36790
36022
  throw new Error(`Local-browser command timed out: ${commandId}`);
36791
36023
  }
36792
- async function runWriteCommand(kind, options, payload) {
36793
- const timeoutSeconds = parseTimeoutSeconds(options.timeout);
36024
+ async function runWriteCommand2(kind, options, payload) {
36025
+ const timeoutSeconds = parseTimeoutSeconds2(options.timeout);
36794
36026
  const created = await createLocalBrowserWriteCommand({
36795
36027
  kind,
36796
36028
  timeoutMs: timeoutSeconds * 1e3,
@@ -36799,7 +36031,7 @@ async function runWriteCommand(kind, options, payload) {
36799
36031
  ...options.hostId ? { hostId: options.hostId } : {},
36800
36032
  ...payload
36801
36033
  });
36802
- await waitForCommand(created.commandId, timeoutSeconds);
36034
+ await waitForCommand2(created.commandId, timeoutSeconds);
36803
36035
  }
36804
36036
  function addReadOptions(command) {
36805
36037
  return command.option("--host <name>", "Run on a named local-browser host").option("--host-id <id>", "Run on a specific local-browser host id").option("--tab-id <id>", "Target a specific browser tab").option("--timeout <seconds>", "Maximum time to wait", "30");
@@ -36812,7 +36044,7 @@ function readCommand(name, kind) {
36812
36044
  return addReadOptions(
36813
36045
  new Command().name(name).description(`Run ${kind}`).action(
36814
36046
  withErrorHandler(async (options) => {
36815
- await runReadCommand(kind, options);
36047
+ await runReadCommand2(kind, options);
36816
36048
  })
36817
36049
  )
36818
36050
  );
@@ -36831,7 +36063,7 @@ function formatHost(host) {
36831
36063
  ` capabilities: ${formatCapabilities(host.supportedCapabilities)}`
36832
36064
  ].join("\n");
36833
36065
  }
36834
- function formatAuditEvent(event) {
36066
+ function formatAuditEvent2(event) {
36835
36067
  const parts = [
36836
36068
  event.createdAt,
36837
36069
  event.event,
@@ -36858,7 +36090,7 @@ function formatAuditEvent(event) {
36858
36090
  }
36859
36091
  return parts.join(" ");
36860
36092
  }
36861
- var hostsCommand = new Command().name("hosts").description("List and revoke linked local-browser hosts").addCommand(
36093
+ var hostsCommand2 = new Command().name("hosts").description("List and revoke linked local-browser hosts").addCommand(
36862
36094
  new Command().name("list").description("List linked local-browser hosts").option("--json", "Output hosts as JSON").action(
36863
36095
  withErrorHandler(async (options) => {
36864
36096
  const result = await listLocalBrowserHosts();
@@ -36886,11 +36118,11 @@ var hostsCommand = new Command().name("hosts").description("List and revoke link
36886
36118
  })
36887
36119
  )
36888
36120
  );
36889
- var auditCommand = new Command().name("audit").description("Inspect local-browser write command audit events").addCommand(
36121
+ var auditCommand2 = new Command().name("audit").description("Inspect local-browser write command audit events").addCommand(
36890
36122
  new Command().name("list").description("List local-browser write command audit events").option("--limit <count>", "Maximum events to show", "50").option("--command-id <id>", "Filter by command id").option("--host-id <id>", "Filter by host id").option("--run-id <id>", "Filter by run id").option("--json", "Output audit events as JSON").action(
36891
36123
  withErrorHandler(async (options) => {
36892
36124
  const result = await listLocalBrowserAuditEvents({
36893
- limit: parseLimit4(options.limit),
36125
+ limit: parseLimit5(options.limit),
36894
36126
  ...options.commandId ? { commandId: options.commandId } : {},
36895
36127
  ...options.hostId ? { hostId: options.hostId } : {},
36896
36128
  ...options.runId ? { runId: options.runId } : {}
@@ -36903,7 +36135,7 @@ var auditCommand = new Command().name("audit").description("Inspect local-browse
36903
36135
  console.log(source_default.dim("No local-browser audit events found."));
36904
36136
  return;
36905
36137
  }
36906
- console.log(result.auditEvents.map(formatAuditEvent).join("\n"));
36138
+ console.log(result.auditEvents.map(formatAuditEvent2).join("\n"));
36907
36139
  })
36908
36140
  )
36909
36141
  );
@@ -36911,7 +36143,7 @@ var tabsCommand = new Command().name("tabs").description("Read and control brows
36911
36143
  addWriteOptions(
36912
36144
  new Command().name("activate").description("Run tabs.activate").requiredOption("--tab-id <id>", "Tab to activate").action(
36913
36145
  withErrorHandler(async (options) => {
36914
- await runWriteCommand("tabs.activate", options, {});
36146
+ await runWriteCommand2("tabs.activate", options, {});
36915
36147
  })
36916
36148
  ),
36917
36149
  { tabId: false }
@@ -36920,7 +36152,7 @@ var tabsCommand = new Command().name("tabs").description("Read and control brows
36920
36152
  addWriteOptions(
36921
36153
  new Command().name("open").description("Run tabs.open").requiredOption("--url <url>", "URL to open").action(
36922
36154
  withErrorHandler(async (options) => {
36923
- await runWriteCommand("tabs.open", options, { url: options.url });
36155
+ await runWriteCommand2("tabs.open", options, { url: options.url });
36924
36156
  })
36925
36157
  )
36926
36158
  )
@@ -36928,7 +36160,7 @@ var tabsCommand = new Command().name("tabs").description("Read and control brows
36928
36160
  addWriteOptions(
36929
36161
  new Command().name("close").description("Run tabs.close").requiredOption("--tab-id <id>", "Tab to close").action(
36930
36162
  withErrorHandler(async (options) => {
36931
- await runWriteCommand("tabs.close", options, {});
36163
+ await runWriteCommand2("tabs.close", options, {});
36932
36164
  })
36933
36165
  ),
36934
36166
  { tabId: false }
@@ -36938,10 +36170,10 @@ var pageCommand = new Command().name("page").description("Read and control the a
36938
36170
  addWriteOptions(
36939
36171
  new Command().name("click").description("Run page.click").option("--selector <selector>", "CSS selector to click").option("--x <pixels>", "X coordinate to click").option("--y <pixels>", "Y coordinate to click").action(
36940
36172
  withErrorHandler(async (options) => {
36941
- await runWriteCommand("page.click", options, {
36173
+ await runWriteCommand2("page.click", options, {
36942
36174
  ...options.selector ? { selector: options.selector } : {},
36943
- ...options.x !== void 0 ? { x: parseOptionalNonNegativeInteger(options.x, "x") } : {},
36944
- ...options.y !== void 0 ? { y: parseOptionalNonNegativeInteger(options.y, "y") } : {}
36175
+ ...options.x !== void 0 ? { x: parseOptionalNonNegativeInteger2(options.x, "x") } : {},
36176
+ ...options.y !== void 0 ? { y: parseOptionalNonNegativeInteger2(options.y, "y") } : {}
36945
36177
  });
36946
36178
  })
36947
36179
  )
@@ -36950,7 +36182,7 @@ var pageCommand = new Command().name("page").description("Read and control the a
36950
36182
  addWriteOptions(
36951
36183
  new Command().name("type").description("Run page.type").requiredOption("--selector <selector>", "CSS selector to type into").requiredOption("--text <text>", "Text to type").action(
36952
36184
  withErrorHandler(async (options) => {
36953
- await runWriteCommand("page.type", options, {
36185
+ await runWriteCommand2("page.type", options, {
36954
36186
  selector: options.selector,
36955
36187
  text: options.text
36956
36188
  });
@@ -36968,9 +36200,9 @@ var pageCommand = new Command().name("page").description("Read and control the a
36968
36200
  if (options.direction !== "up" && options.direction !== "down") {
36969
36201
  throw new Error("direction must be up or down");
36970
36202
  }
36971
- await runWriteCommand("page.scroll", options, {
36203
+ await runWriteCommand2("page.scroll", options, {
36972
36204
  direction: options.direction,
36973
- amount: parsePositiveInteger2(options.amount, "amount")
36205
+ amount: parsePositiveInteger3(options.amount, "amount")
36974
36206
  });
36975
36207
  })
36976
36208
  )
@@ -36979,7 +36211,7 @@ var pageCommand = new Command().name("page").description("Read and control the a
36979
36211
  addWriteOptions(
36980
36212
  new Command().name("navigate").description("Run page.navigate").requiredOption("--url <url>", "URL to navigate to").action(
36981
36213
  withErrorHandler(async (options) => {
36982
- await runWriteCommand("page.navigate", options, {
36214
+ await runWriteCommand2("page.navigate", options, {
36983
36215
  url: options.url
36984
36216
  });
36985
36217
  })
@@ -36997,7 +36229,7 @@ Examples:
36997
36229
  Click page? zero local-browser page click --selector button
36998
36230
  Open tab? zero local-browser tabs open --url https://example.com
36999
36231
  Audit actions? zero local-browser audit list`
37000
- ).addCommand(hostsCommand).addCommand(auditCommand).addCommand(tabsCommand).addCommand(pageCommand);
36232
+ ).addCommand(hostsCommand2).addCommand(auditCommand2).addCommand(tabsCommand).addCommand(pageCommand);
37001
36233
 
37002
36234
  // src/commands/zero/host/index.ts
37003
36235
  init_esm_shims();
@@ -37287,7 +36519,7 @@ function registerZeroCommands(prog, commands) {
37287
36519
  var program = new Command();
37288
36520
  program.name("zero").description(
37289
36521
  "Zero CLI \u2014 interact with the zero platform from inside the sandbox"
37290
- ).version("9.157.1").addHelpText("after", () => {
36522
+ ).version("9.158.1").addHelpText("after", () => {
37291
36523
  return buildZeroHelpText();
37292
36524
  });
37293
36525
  if (process.argv[1]?.endsWith("zero.js") || process.argv[1]?.endsWith("zero.ts") || process.argv[1]?.endsWith("zero")) {