@agentorg/computer 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2151,51 +2151,51 @@ var require_extension = __commonJS({
2151
2151
  let paramName;
2152
2152
  let start = -1;
2153
2153
  let code = -1;
2154
- let end = -1;
2154
+ let end2 = -1;
2155
2155
  let i = 0;
2156
2156
  for (; i < header.length; i++) {
2157
2157
  code = header.charCodeAt(i);
2158
2158
  if (extensionName === void 0) {
2159
- if (end === -1 && tokenChars[code] === 1) {
2159
+ if (end2 === -1 && tokenChars[code] === 1) {
2160
2160
  if (start === -1) start = i;
2161
2161
  } else if (i !== 0 && (code === 32 || code === 9)) {
2162
- if (end === -1 && start !== -1) end = i;
2162
+ if (end2 === -1 && start !== -1) end2 = i;
2163
2163
  } else if (code === 59 || code === 44) {
2164
2164
  if (start === -1) {
2165
2165
  throw new SyntaxError(`Unexpected character at index ${i}`);
2166
2166
  }
2167
- if (end === -1) end = i;
2168
- const name = header.slice(start, end);
2167
+ if (end2 === -1) end2 = i;
2168
+ const name = header.slice(start, end2);
2169
2169
  if (code === 44) {
2170
2170
  push(offers, name, params);
2171
2171
  params = /* @__PURE__ */ Object.create(null);
2172
2172
  } else {
2173
2173
  extensionName = name;
2174
2174
  }
2175
- start = end = -1;
2175
+ start = end2 = -1;
2176
2176
  } else {
2177
2177
  throw new SyntaxError(`Unexpected character at index ${i}`);
2178
2178
  }
2179
2179
  } else if (paramName === void 0) {
2180
- if (end === -1 && tokenChars[code] === 1) {
2180
+ if (end2 === -1 && tokenChars[code] === 1) {
2181
2181
  if (start === -1) start = i;
2182
2182
  } else if (code === 32 || code === 9) {
2183
- if (end === -1 && start !== -1) end = i;
2183
+ if (end2 === -1 && start !== -1) end2 = i;
2184
2184
  } else if (code === 59 || code === 44) {
2185
2185
  if (start === -1) {
2186
2186
  throw new SyntaxError(`Unexpected character at index ${i}`);
2187
2187
  }
2188
- if (end === -1) end = i;
2189
- push(params, header.slice(start, end), true);
2188
+ if (end2 === -1) end2 = i;
2189
+ push(params, header.slice(start, end2), true);
2190
2190
  if (code === 44) {
2191
2191
  push(offers, extensionName, params);
2192
2192
  params = /* @__PURE__ */ Object.create(null);
2193
2193
  extensionName = void 0;
2194
2194
  }
2195
- start = end = -1;
2196
- } else if (code === 61 && start !== -1 && end === -1) {
2195
+ start = end2 = -1;
2196
+ } else if (code === 61 && start !== -1 && end2 === -1) {
2197
2197
  paramName = header.slice(start, i);
2198
- start = end = -1;
2198
+ start = end2 = -1;
2199
2199
  } else {
2200
2200
  throw new SyntaxError(`Unexpected character at index ${i}`);
2201
2201
  }
@@ -2212,7 +2212,7 @@ var require_extension = __commonJS({
2212
2212
  if (start === -1) start = i;
2213
2213
  } else if (code === 34 && start !== -1) {
2214
2214
  inQuotes = false;
2215
- end = i;
2215
+ end2 = i;
2216
2216
  } else if (code === 92) {
2217
2217
  isEscaping = true;
2218
2218
  } else {
@@ -2220,16 +2220,16 @@ var require_extension = __commonJS({
2220
2220
  }
2221
2221
  } else if (code === 34 && header.charCodeAt(i - 1) === 61) {
2222
2222
  inQuotes = true;
2223
- } else if (end === -1 && tokenChars[code] === 1) {
2223
+ } else if (end2 === -1 && tokenChars[code] === 1) {
2224
2224
  if (start === -1) start = i;
2225
2225
  } else if (start !== -1 && (code === 32 || code === 9)) {
2226
- if (end === -1) end = i;
2226
+ if (end2 === -1) end2 = i;
2227
2227
  } else if (code === 59 || code === 44) {
2228
2228
  if (start === -1) {
2229
2229
  throw new SyntaxError(`Unexpected character at index ${i}`);
2230
2230
  }
2231
- if (end === -1) end = i;
2232
- let value = header.slice(start, end);
2231
+ if (end2 === -1) end2 = i;
2232
+ let value = header.slice(start, end2);
2233
2233
  if (mustUnescape) {
2234
2234
  value = value.replace(/\\/g, "");
2235
2235
  mustUnescape = false;
@@ -2241,7 +2241,7 @@ var require_extension = __commonJS({
2241
2241
  extensionName = void 0;
2242
2242
  }
2243
2243
  paramName = void 0;
2244
- start = end = -1;
2244
+ start = end2 = -1;
2245
2245
  } else {
2246
2246
  throw new SyntaxError(`Unexpected character at index ${i}`);
2247
2247
  }
@@ -2250,8 +2250,8 @@ var require_extension = __commonJS({
2250
2250
  if (start === -1 || inQuotes || code === 32 || code === 9) {
2251
2251
  throw new SyntaxError("Unexpected end of input");
2252
2252
  }
2253
- if (end === -1) end = i;
2254
- const token = header.slice(start, end);
2253
+ if (end2 === -1) end2 = i;
2254
+ const token = header.slice(start, end2);
2255
2255
  if (extensionName === void 0) {
2256
2256
  push(offers, token, params);
2257
2257
  } else {
@@ -3312,30 +3312,30 @@ var require_subprotocol = __commonJS({
3312
3312
  function parse3(header) {
3313
3313
  const protocols = /* @__PURE__ */ new Set();
3314
3314
  let start = -1;
3315
- let end = -1;
3315
+ let end2 = -1;
3316
3316
  let i = 0;
3317
3317
  for (i; i < header.length; i++) {
3318
3318
  const code = header.charCodeAt(i);
3319
- if (end === -1 && tokenChars[code] === 1) {
3319
+ if (end2 === -1 && tokenChars[code] === 1) {
3320
3320
  if (start === -1) start = i;
3321
3321
  } else if (i !== 0 && (code === 32 || code === 9)) {
3322
- if (end === -1 && start !== -1) end = i;
3322
+ if (end2 === -1 && start !== -1) end2 = i;
3323
3323
  } else if (code === 44) {
3324
3324
  if (start === -1) {
3325
3325
  throw new SyntaxError(`Unexpected character at index ${i}`);
3326
3326
  }
3327
- if (end === -1) end = i;
3328
- const protocol2 = header.slice(start, end);
3327
+ if (end2 === -1) end2 = i;
3328
+ const protocol2 = header.slice(start, end2);
3329
3329
  if (protocols.has(protocol2)) {
3330
3330
  throw new SyntaxError(`The "${protocol2}" subprotocol is duplicated`);
3331
3331
  }
3332
3332
  protocols.add(protocol2);
3333
- start = end = -1;
3333
+ start = end2 = -1;
3334
3334
  } else {
3335
3335
  throw new SyntaxError(`Unexpected character at index ${i}`);
3336
3336
  }
3337
3337
  }
3338
- if (start === -1 || end !== -1) {
3338
+ if (start === -1 || end2 !== -1) {
3339
3339
  throw new SyntaxError("Unexpected end of input");
3340
3340
  }
3341
3341
  const protocol = header.slice(start, i);
@@ -3753,25 +3753,73 @@ var require_websocket_server = __commonJS({
3753
3753
  // src/main.ts
3754
3754
  import { readFileSync as readFileSync6 } from "node:fs";
3755
3755
  import { homedir as homedir2 } from "node:os";
3756
- import { isAbsolute as isAbsolute2, join as join10, resolve as resolve5 } from "node:path";
3756
+ import { isAbsolute as isAbsolute2, join as join11, resolve as resolve5 } from "node:path";
3757
3757
  import { parseArgs } from "node:util";
3758
3758
  import { isMainThread as isMainThread2 } from "node:worker_threads";
3759
3759
 
3760
+ // src/browser-host.ts
3761
+ import { mkdtempSync, rmSync } from "node:fs";
3762
+ import { join, sep } from "node:path";
3763
+
3764
+ // src/playwright.ts
3765
+ import { createRequire } from "node:module";
3766
+ var loaded;
3767
+ var playwright = () => {
3768
+ loaded ??= createRequire(import.meta.url)("playwright-core");
3769
+ return loaded;
3770
+ };
3771
+
3772
+ // src/browser-host.ts
3773
+ var sandboxFor = (options) => options.sandbox ?? (process.platform !== "linux" || !options.executable && !["chromium", "chrome-for-testing"].includes(options.channel ?? "chrome"));
3774
+ async function hostBrowser(options) {
3775
+ const run3 = mkdtempSync(join("/tmp", "agentcomputer-"));
3776
+ process.env.XDG_RUNTIME_DIR = run3;
3777
+ process.env.TMPDIR = run3;
3778
+ const context = await playwright().chromium.launchPersistentContext(options.profile, {
3779
+ headless: true,
3780
+ chromiumSandbox: sandboxFor(options),
3781
+ ...options.executable ? { executablePath: options.executable } : { channel: options.channel ?? "chrome" }
3782
+ });
3783
+ const browser = context.browser();
3784
+ if (!browser) throw new Error("The browser can't be shared.");
3785
+ const { endpoint } = await browser.bind("agentcomputer");
3786
+ if (!endpoint.startsWith(run3 + sep)) {
3787
+ await context.close();
3788
+ throw new Error(`The browser's socket isn't in its own folder: ${endpoint}`);
3789
+ }
3790
+ process.stdout.write(`${JSON.stringify({ endpoint })}
3791
+ `);
3792
+ let stopping = false;
3793
+ const stop = async () => {
3794
+ if (stopping) return;
3795
+ stopping = true;
3796
+ await browser.unbind().catch(() => {
3797
+ });
3798
+ await context.close().catch(() => {
3799
+ });
3800
+ rmSync(run3, { recursive: true, force: true });
3801
+ process.exit(0);
3802
+ };
3803
+ for (const signal of ["SIGINT", "SIGTERM"]) process.once(signal, () => void stop());
3804
+ context.on("close", () => void stop());
3805
+ }
3806
+
3760
3807
  // src/container.ts
3761
3808
  import { execFile, spawn as spawn3 } from "node:child_process";
3762
3809
  import { readFileSync as readFileSync3 } from "node:fs";
3763
3810
  import { connect } from "node:net";
3764
- import { join as join7 } from "node:path";
3811
+ import { join as join8 } from "node:path";
3765
3812
  import { createInterface as createInterface2 } from "node:readline";
3766
3813
  import { Readable as Readable3 } from "node:stream";
3767
3814
  import { promisify } from "node:util";
3768
3815
 
3769
3816
  // src/browser.ts
3770
3817
  import { spawn } from "node:child_process";
3771
- import { createRequire } from "node:module";
3772
- import { dirname, join } from "node:path";
3818
+ import { createRequire as createRequire2 } from "node:module";
3819
+ import { dirname, join as join2 } from "node:path";
3773
3820
  import { createInterface } from "node:readline";
3774
3821
  import { pipeline, Readable } from "node:stream";
3822
+ import { fileURLToPath } from "node:url";
3775
3823
 
3776
3824
  // node_modules/@modelcontextprotocol/client/dist/chunk-DYPzFuB5.mjs
3777
3825
  var __create2 = Object.create;
@@ -3961,8 +4009,8 @@ function nullish(input2) {
3961
4009
  }
3962
4010
  function cleanRegex(source) {
3963
4011
  const start = source.startsWith("^") ? 1 : 0;
3964
- const end = source.endsWith("$") ? source.length - 1 : source.length;
3965
- return source.slice(start, end);
4012
+ const end2 = source.endsWith("$") ? source.length - 1 : source.length;
4013
+ return source.slice(start, end2);
3966
4014
  }
3967
4015
  function floatSafeRemainder(val, step) {
3968
4016
  const ratio = val / step;
@@ -9531,15 +9579,15 @@ var initializer2 = (inst, issues) => {
9531
9579
  if (_installedErrorProtos.has(proto))
9532
9580
  return;
9533
9581
  _installedErrorProtos.add(proto);
9534
- _lazyMethod(proto, "format", (self) => (mapper) => formatError(self, mapper));
9535
- _lazyMethod(proto, "flatten", (self) => (mapper) => flattenError(self, mapper));
9536
- _lazyMethod(proto, "addIssue", (self) => (issue3) => {
9537
- self.issues.push(issue3);
9538
- self.message = JSON.stringify(self.issues, jsonStringifyReplacer, 2);
9582
+ _lazyMethod(proto, "format", (self2) => (mapper) => formatError(self2, mapper));
9583
+ _lazyMethod(proto, "flatten", (self2) => (mapper) => flattenError(self2, mapper));
9584
+ _lazyMethod(proto, "addIssue", (self2) => (issue3) => {
9585
+ self2.issues.push(issue3);
9586
+ self2.message = JSON.stringify(self2.issues, jsonStringifyReplacer, 2);
9539
9587
  });
9540
- _lazyMethod(proto, "addIssues", (self) => (issues2) => {
9541
- self.issues.push(...issues2);
9542
- self.message = JSON.stringify(self.issues, jsonStringifyReplacer, 2);
9588
+ _lazyMethod(proto, "addIssues", (self2) => (issues2) => {
9589
+ self2.issues.push(...issues2);
9590
+ self2.message = JSON.stringify(self2.issues, jsonStringifyReplacer, 2);
9543
9591
  });
9544
9592
  Object.defineProperty(proto, "isEmpty", {
9545
9593
  configurable: true,
@@ -10216,7 +10264,7 @@ var ZodObject = /* @__PURE__ */ $constructor("ZodObject", (inst, def) => {
10216
10264
  $ZodObjectJIT.init(inst, def);
10217
10265
  ZodType.init(inst, def);
10218
10266
  inst._zod.processJSONSchema = (ctx, json4, params) => objectProcessor(inst, ctx, json4, params);
10219
- util_exports.installLazyProp(inst, "shape", (self) => self._zod.def.shape, false);
10267
+ util_exports.installLazyProp(inst, "shape", (self2) => self2._zod.def.shape, false);
10220
10268
  }, {
10221
10269
  keyof() {
10222
10270
  return _enum(Object.keys(this._zod.def.shape));
@@ -17350,10 +17398,10 @@ var require_util = /* @__PURE__ */ __commonJSMin(((exports) => {
17350
17398
  }
17351
17399
  exports.alwaysValidSchema = alwaysValidSchema;
17352
17400
  function checkUnknownRules(it, schema = it.schema) {
17353
- const { opts, self } = it;
17401
+ const { opts, self: self2 } = it;
17354
17402
  if (!opts.strictSchema) return;
17355
17403
  if (typeof schema === "boolean") return;
17356
- const rules = self.RULES.keywords;
17404
+ const rules = self2.RULES.keywords;
17357
17405
  for (const key in schema) if (!rules[key]) checkStrictMode(it, `unknown keyword: "${key}"`);
17358
17406
  }
17359
17407
  exports.checkUnknownRules = checkUnknownRules;
@@ -17685,8 +17733,8 @@ var require_rules = /* @__PURE__ */ __commonJSMin(((exports) => {
17685
17733
  var require_applicability = /* @__PURE__ */ __commonJSMin(((exports) => {
17686
17734
  Object.defineProperty(exports, "__esModule", { value: true });
17687
17735
  exports.shouldUseRule = exports.shouldUseGroup = exports.schemaHasRulesForType = void 0;
17688
- function schemaHasRulesForType({ schema, self }, type) {
17689
- const group = self.RULES.types[type];
17736
+ function schemaHasRulesForType({ schema, self: self2 }, type) {
17737
+ const group = self2.RULES.types[type];
17690
17738
  return group && group !== true && shouldUseGroup(schema, group);
17691
17739
  }
17692
17740
  exports.schemaHasRulesForType = schemaHasRulesForType;
@@ -18099,14 +18147,14 @@ var require_keyword = /* @__PURE__ */ __commonJSMin(((exports) => {
18099
18147
  return !schemaType.length || schemaType.some((st) => st === "array" ? Array.isArray(schema) : st === "object" ? schema && typeof schema == "object" && !Array.isArray(schema) : typeof schema == st || allowUndefined && typeof schema == "undefined");
18100
18148
  }
18101
18149
  exports.validSchemaType = validSchemaType;
18102
- function validateKeywordUsage({ schema, opts, self, errSchemaPath }, def, keyword) {
18150
+ function validateKeywordUsage({ schema, opts, self: self2, errSchemaPath }, def, keyword) {
18103
18151
  if (Array.isArray(def.keyword) ? !def.keyword.includes(keyword) : def.keyword !== keyword) throw new Error("ajv implementation error");
18104
18152
  const deps = def.dependencies;
18105
18153
  if (deps === null || deps === void 0 ? void 0 : deps.some((kwd) => !Object.prototype.hasOwnProperty.call(schema, kwd))) throw new Error(`parent schema must have dependencies of ${keyword}: ${deps.join(",")}`);
18106
18154
  if (def.validateSchema) {
18107
18155
  if (!def.validateSchema(schema[keyword])) {
18108
- const msg = `keyword "${keyword}" value is invalid at path "${errSchemaPath}": ` + self.errorsText(def.validateSchema.errors);
18109
- if (opts.validateSchema === "log") self.logger.error(msg);
18156
+ const msg = `keyword "${keyword}" value is invalid at path "${errSchemaPath}": ` + self2.errorsText(def.validateSchema.errors);
18157
+ if (opts.validateSchema === "log") self2.logger.error(msg);
18110
18158
  else throw new Error(msg);
18111
18159
  }
18112
18160
  }
@@ -18490,9 +18538,9 @@ var require_validate = /* @__PURE__ */ __commonJSMin(((exports) => {
18490
18538
  }
18491
18539
  (0, boolSchema_1.boolOrEmptySchema)(it, valid);
18492
18540
  }
18493
- function schemaCxtHasRules({ schema, self }) {
18541
+ function schemaCxtHasRules({ schema, self: self2 }) {
18494
18542
  if (typeof schema == "boolean") return !schema;
18495
- for (const key in schema) if (self.RULES.all[key]) return true;
18543
+ for (const key in schema) if (self2.RULES.all[key]) return true;
18496
18544
  return false;
18497
18545
  }
18498
18546
  function isSchemaObj(it) {
@@ -18517,8 +18565,8 @@ var require_validate = /* @__PURE__ */ __commonJSMin(((exports) => {
18517
18565
  schemaKeywords(it, types, !(0, dataType_1.coerceAndCheckDataType)(it, types), errsCount);
18518
18566
  }
18519
18567
  function checkRefsAndKeywords(it) {
18520
- const { schema, errSchemaPath, opts, self } = it;
18521
- if (schema.$ref && opts.ignoreKeywordsWithRef && (0, util_1.schemaHasRulesButRef)(schema, self.RULES)) self.logger.warn(`$ref: keywords ignored in schema at path "${errSchemaPath}"`);
18568
+ const { schema, errSchemaPath, opts, self: self2 } = it;
18569
+ if (schema.$ref && opts.ignoreKeywordsWithRef && (0, util_1.schemaHasRulesButRef)(schema, self2.RULES)) self2.logger.warn(`$ref: keywords ignored in schema at path "${errSchemaPath}"`);
18522
18570
  }
18523
18571
  function checkNoDefault(it) {
18524
18572
  const { schema, opts } = it;
@@ -18554,8 +18602,8 @@ var require_validate = /* @__PURE__ */ __commonJSMin(((exports) => {
18554
18602
  if (items instanceof codegen_1.Name) gen.assign((0, codegen_1._)`${evaluated}.items`, items);
18555
18603
  }
18556
18604
  function schemaKeywords(it, types, typeErrors, errsCount) {
18557
- const { gen, schema, data, allErrors, opts, self } = it;
18558
- const { RULES } = self;
18605
+ const { gen, schema, data, allErrors, opts, self: self2 } = it;
18606
+ const { RULES } = self2;
18559
18607
  if (schema.$ref && (opts.ignoreKeywordsWithRef || !(0, util_1.schemaHasRulesButRef)(schema, RULES))) {
18560
18608
  gen.block(() => keywordCode(it, "$ref", RULES.all.$ref.definition));
18561
18609
  return;
@@ -20577,10 +20625,10 @@ var require_ref = /* @__PURE__ */ __commonJSMin(((exports) => {
20577
20625
  schemaType: "string",
20578
20626
  code(cxt) {
20579
20627
  const { gen, schema: $ref, it } = cxt;
20580
- const { baseId, schemaEnv: env, validateName, opts, self } = it;
20628
+ const { baseId, schemaEnv: env, validateName, opts, self: self2 } = it;
20581
20629
  const { root } = env;
20582
20630
  if (($ref === "#" || $ref === "#/") && baseId === root.baseId) return callRootRef();
20583
- const schOrEnv = compile_1.resolveRef.call(self, root, baseId, $ref);
20631
+ const schOrEnv = compile_1.resolveRef.call(self2, root, baseId, $ref);
20584
20632
  if (schOrEnv === void 0) throw new ref_error_1.default(it.opts.uriResolver, baseId, $ref);
20585
20633
  if (schOrEnv instanceof compile_1.SchemaEnv) return callValidate(schOrEnv);
20586
20634
  return inlineRefSchema(schOrEnv);
@@ -21840,13 +21888,13 @@ var require_format$2 = /* @__PURE__ */ __commonJSMin(((exports) => {
21840
21888
  },
21841
21889
  code(cxt, ruleType) {
21842
21890
  const { gen, data, $data, schema, schemaCode, it } = cxt;
21843
- const { opts, errSchemaPath, schemaEnv, self } = it;
21891
+ const { opts, errSchemaPath, schemaEnv, self: self2 } = it;
21844
21892
  if (!opts.validateFormats) return;
21845
21893
  if ($data) validate$DataFormat();
21846
21894
  else validateFormat();
21847
21895
  function validate$DataFormat() {
21848
21896
  const fmts = gen.scopeValue("formats", {
21849
- ref: self.formats,
21897
+ ref: self2.formats,
21850
21898
  code: opts.code.formats
21851
21899
  });
21852
21900
  const fDef = gen.const("fDef", (0, codegen_1._)`${fmts}[${schemaCode}]`);
@@ -21865,7 +21913,7 @@ var require_format$2 = /* @__PURE__ */ __commonJSMin(((exports) => {
21865
21913
  }
21866
21914
  }
21867
21915
  function validateFormat() {
21868
- const formatDef = self.formats[schema];
21916
+ const formatDef = self2.formats[schema];
21869
21917
  if (!formatDef) {
21870
21918
  unknownFormat();
21871
21919
  return;
@@ -21875,7 +21923,7 @@ var require_format$2 = /* @__PURE__ */ __commonJSMin(((exports) => {
21875
21923
  if (fmtType === ruleType) cxt.pass(validCondition());
21876
21924
  function unknownFormat() {
21877
21925
  if (opts.strictSchema === false) {
21878
- self.logger.warn(unknownMsg());
21926
+ self2.logger.warn(unknownMsg());
21879
21927
  return;
21880
21928
  }
21881
21929
  throw new Error(unknownMsg());
@@ -22301,9 +22349,9 @@ var require_dynamicAnchor = /* @__PURE__ */ __commonJSMin(((exports) => {
22301
22349
  }
22302
22350
  exports.dynamicAnchor = dynamicAnchor;
22303
22351
  function _getValidate(cxt) {
22304
- const { schemaEnv, schema, self } = cxt.it;
22352
+ const { schemaEnv, schema, self: self2 } = cxt.it;
22305
22353
  const { root, baseId, localRefs, meta: meta3 } = schemaEnv.root;
22306
- const { schemaId } = self.opts;
22354
+ const { schemaId } = self2.opts;
22307
22355
  const sch = new compile_1.SchemaEnv({
22308
22356
  schema,
22309
22357
  schemaId,
@@ -22312,7 +22360,7 @@ var require_dynamicAnchor = /* @__PURE__ */ __commonJSMin(((exports) => {
22312
22360
  localRefs,
22313
22361
  meta: meta3
22314
22362
  });
22315
- compile_1.compileSchema.call(self, sch);
22363
+ compile_1.compileSchema.call(self2, sch);
22316
22364
  return (0, ref_1.getValidate)(cxt, sch);
22317
22365
  }
22318
22366
  exports.default = def;
@@ -23612,14 +23660,14 @@ var require_limit = /* @__PURE__ */ __commonJSMin(((exports) => {
23612
23660
  error: error62,
23613
23661
  code(cxt) {
23614
23662
  const { gen, data, schemaCode, keyword, it } = cxt;
23615
- const { opts, self } = it;
23663
+ const { opts, self: self2 } = it;
23616
23664
  if (!opts.validateFormats) return;
23617
- const fCxt = new ajv_1.KeywordCxt(it, self.RULES.all.format.definition, "format");
23665
+ const fCxt = new ajv_1.KeywordCxt(it, self2.RULES.all.format.definition, "format");
23618
23666
  if (fCxt.$data) validate$DataFormat();
23619
23667
  else validateFormat();
23620
23668
  function validate$DataFormat() {
23621
23669
  const fmts = gen.scopeValue("formats", {
23622
- ref: self.formats,
23670
+ ref: self2.formats,
23623
23671
  code: opts.code.formats
23624
23672
  });
23625
23673
  const fmt = gen.const("fmt", (0, codegen_1._)`${fmts}[${fCxt.schemaCode}]`);
@@ -23627,7 +23675,7 @@ var require_limit = /* @__PURE__ */ __commonJSMin(((exports) => {
23627
23675
  }
23628
23676
  function validateFormat() {
23629
23677
  const format = fCxt.schema;
23630
- const fmtDef = self.formats[format];
23678
+ const fmtDef = self2.formats[format];
23631
23679
  if (!fmtDef || fmtDef === true) return;
23632
23680
  if (typeof fmtDef != "object" || fmtDef instanceof RegExp || typeof fmtDef.compare != "function") throw new Error(`"${keyword}": format "${format}" does not define "compare" function`);
23633
23681
  const fmt = gen.scopeValue("formats", {
@@ -27080,35 +27128,35 @@ ${value}`, dataLines++;
27080
27128
  }
27081
27129
  return chunk.slice(searchIndex);
27082
27130
  }
27083
- function parseLine(chunk, start, end) {
27084
- if (start === end) {
27131
+ function parseLine(chunk, start, end2) {
27132
+ if (start === end2) {
27085
27133
  dispatchEvent();
27086
27134
  return;
27087
27135
  }
27088
27136
  const firstCharCode = chunk.charCodeAt(start);
27089
27137
  if (isDataPrefix(chunk, start, firstCharCode)) {
27090
- const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5, value2 = chunk.slice(valueStart, end);
27138
+ const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5, value2 = chunk.slice(valueStart, end2);
27091
27139
  data = dataLines === 0 ? value2 : `${data}
27092
27140
  ${value2}`, dataLines++;
27093
27141
  return;
27094
27142
  }
27095
27143
  if (isEventPrefix(chunk, start, firstCharCode)) {
27096
- eventType = chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || void 0;
27144
+ eventType = chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end2) || void 0;
27097
27145
  return;
27098
27146
  }
27099
27147
  if (firstCharCode === 105 && chunk.charCodeAt(start + 1) === 100 && chunk.charCodeAt(start + 2) === 58) {
27100
- const value2 = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end);
27148
+ const value2 = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end2);
27101
27149
  value2.includes("\0") || (id = value2);
27102
27150
  return;
27103
27151
  }
27104
27152
  if (firstCharCode === 58) {
27105
27153
  if (onComment) {
27106
- const line2 = chunk.slice(start, end);
27154
+ const line2 = chunk.slice(start, end2);
27107
27155
  onComment(line2.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1));
27108
27156
  }
27109
27157
  return;
27110
27158
  }
27111
- const line = chunk.slice(start, end), fieldSeparatorIndex = line.indexOf(":");
27159
+ const line = chunk.slice(start, end2), fieldSeparatorIndex = line.indexOf(":");
27112
27160
  if (fieldSeparatorIndex === -1) {
27113
27161
  processField(line, "", line);
27114
27162
  return;
@@ -27890,7 +27938,9 @@ function sendAnswer(upstream, response) {
27890
27938
  pipeline(Readable.fromWeb(upstream.body), response, () => {
27891
27939
  });
27892
27940
  }
27893
- var defaultCli = () => join(dirname(createRequire(import.meta.url).resolve("@playwright/mcp/package.json")), "cli.js");
27941
+ var mcpCli = () => join2(dirname(createRequire2(import.meta.url).resolve("@playwright/mcp/package.json")), "cli.js");
27942
+ var self = fileURLToPath(import.meta.url);
27943
+ var ANSWERS = /* @__PURE__ */ new Set(["browser_handle_dialog", "browser_file_upload"]);
27894
27944
  function withoutHidden(text2, hidden) {
27895
27945
  const clean = (json4) => {
27896
27946
  const message = JSON.parse(json4);
@@ -27901,49 +27951,96 @@ function withoutHidden(text2, hidden) {
27901
27951
  if (text2.trimStart().startsWith("{")) return clean(text2);
27902
27952
  return text2.replace(/^data: (\{.*\})$/gm, (_, json4) => `data: ${clean(json4)}`);
27903
27953
  }
27954
+ async function end(child) {
27955
+ if (child.exitCode !== null || child.signalCode !== null) return;
27956
+ const gone = new Promise((done) => child.once("exit", () => done()));
27957
+ child.kill("SIGTERM");
27958
+ const timer = setTimeout(() => child.kill("SIGKILL"), STOP_MS);
27959
+ await gone;
27960
+ clearTimeout(timer);
27961
+ }
27904
27962
  var Browser = class {
27905
- #child;
27963
+ #host;
27964
+ #mcp;
27906
27965
  #origin;
27966
+ /** The bound browser's socket, for the live viewer. */
27967
+ endpoint;
27907
27968
  #hidden;
27908
- #exited = false;
27909
27969
  #stopping = false;
27910
27970
  /** The tools it offers, read once it is up. */
27911
27971
  tools = [];
27972
+ gate;
27912
27973
  constructor(config3, folder, cwd, terminal, log, exited) {
27913
27974
  this.#hidden = new Set(terminal ? [] : [RUNS_CODE]);
27914
- this.#child = spawn(
27975
+ const ended = (what) => (code) => {
27976
+ if (!this.#stopping) {
27977
+ log(`${what} exited with ${code}.`);
27978
+ exited();
27979
+ }
27980
+ };
27981
+ this.#host = spawn(
27915
27982
  process.execPath,
27916
27983
  [
27917
- config3.cli ?? defaultCli(),
27918
- "--headless",
27919
- "--host",
27920
- "127.0.0.1",
27921
- "--port",
27922
- "0",
27923
- ...config3.path ? ["--browser", config3.browser ?? "chromium", "--executable-path", config3.path] : ["--browser", config3.browser ?? "chrome"],
27924
- ...config3.sandbox === false ? ["--no-sandbox"] : [],
27925
- "--user-data-dir",
27926
- join(folder, "profile"),
27927
- "--output-dir",
27928
- join(folder, "output")
27984
+ self,
27985
+ "browser-host",
27986
+ "--profile",
27987
+ join2(folder, "profile"),
27988
+ ...config3.path ? ["--executable", config3.path] : ["--channel", config3.browser ?? "chrome"],
27989
+ ...config3.sandbox === false ? ["--no-sandbox"] : []
27929
27990
  ],
27930
- // Its own limit on which files it touches is the folder it starts in.
27931
- { cwd, stdio: ["ignore", "pipe", "pipe"] }
27991
+ { stdio: ["ignore", "pipe", "pipe"] }
27932
27992
  );
27933
- this.#origin = new Promise((done, failed) => {
27934
- this.#child.on("error", failed);
27935
- this.#child.once("exit", (code) => {
27936
- this.#exited = true;
27937
- failed(new Error(`The browser's server exited with ${code}.`));
27938
- if (!this.#stopping) exited();
27939
- });
27940
- for (const stream of [this.#child.stdout, this.#child.stderr])
27941
- createInterface({ input: stream }).on("line", (line) => {
27993
+ this.endpoint = new Promise((done, failed) => {
27994
+ this.#host.on("error", failed);
27995
+ this.#host.once("exit", (code) => failed(new Error(`The browser exited with ${code}.`)));
27996
+ this.#host.once("exit", ended("The browser"));
27997
+ createInterface({ input: this.#host.stdout }).on("line", (line) => {
27998
+ try {
27999
+ const { endpoint } = JSON.parse(line);
28000
+ log(`The browser is shared on ${endpoint}.`);
28001
+ done(endpoint);
28002
+ } catch {
27942
28003
  log(line);
27943
- const listening = /^Listening on (http:\/\/[^/\s]+)/.exec(line);
27944
- if (listening) done(listening[1]);
27945
- });
28004
+ }
28005
+ });
28006
+ createInterface({ input: this.#host.stderr }).on("line", log);
28007
+ });
28008
+ this.endpoint.catch(() => {
27946
28009
  });
28010
+ this.#origin = this.endpoint.then(
28011
+ (endpoint) => new Promise((done, failed) => {
28012
+ if (this.#stopping) return failed(new Error("It stopped."));
28013
+ const mcp = spawn(
28014
+ process.execPath,
28015
+ [
28016
+ mcpCli(),
28017
+ "--host",
28018
+ "127.0.0.1",
28019
+ "--port",
28020
+ "0",
28021
+ "--endpoint",
28022
+ endpoint,
28023
+ "--output-dir",
28024
+ join2(folder, "output")
28025
+ ],
28026
+ // Its own limit on which files it touches is the folder it starts in.
28027
+ { cwd, stdio: ["ignore", "pipe", "pipe"] }
28028
+ );
28029
+ this.#mcp = mcp;
28030
+ mcp.on("error", failed);
28031
+ mcp.once(
28032
+ "exit",
28033
+ (code) => failed(new Error(`The browser's server exited with ${code}.`))
28034
+ );
28035
+ mcp.once("exit", ended("The browser's server"));
28036
+ for (const stream of [mcp.stdout, mcp.stderr])
28037
+ createInterface({ input: stream }).on("line", (line) => {
28038
+ log(line);
28039
+ const listening = /^Listening on (http:\/\/[^/\s]+)/.exec(line);
28040
+ if (listening) done(listening[1]);
28041
+ });
28042
+ })
28043
+ );
27947
28044
  this.#origin.catch(() => {
27948
28045
  });
27949
28046
  }
@@ -27977,21 +28074,40 @@ var Browser = class {
27977
28074
  if (body.length > 0) message = JSON.parse(body.toString("utf8"));
27978
28075
  } catch {
27979
28076
  }
27980
- if (message.method === "tools/call" && this.#hidden.has(String(message.params?.name))) {
28077
+ const tool = message.method === "tools/call" ? String(message.params?.name) : void 0;
28078
+ const refuse = (text2, code = -32e3) => {
27981
28079
  response.writeHead(200, { "Content-Type": "application/json" });
27982
- return void response.end(
28080
+ response.end(
27983
28081
  JSON.stringify({
27984
28082
  jsonrpc: "2.0",
27985
28083
  id: message.id ?? null,
27986
- error: { code: -32602, message: `Unknown tool: ${String(message.params?.name)}` }
28084
+ ...code === -32602 ? { error: { code, message: text2 } } : { result: { content: [{ type: "text", text: text2 }], isError: true } }
27987
28085
  })
27988
28086
  );
28087
+ };
28088
+ if (tool && this.#hidden.has(tool)) return refuse(`Unknown tool: ${tool}`, -32602);
28089
+ if (tool && this.gate) {
28090
+ const answer = await this.gate.wait();
28091
+ if (answer) return refuse(answer);
27989
28092
  }
27990
28093
  const headers = {};
27991
28094
  for (const name of FORWARDED) {
27992
28095
  const value = request.headers[name];
27993
28096
  if (typeof value === "string") headers[name] = value;
27994
28097
  }
28098
+ if (tool && this.gate?.takeAnsweredChooser())
28099
+ await fetch(`${origin}/mcp`, {
28100
+ method: "POST",
28101
+ headers,
28102
+ body: JSON.stringify({
28103
+ jsonrpc: "2.0",
28104
+ id: "agentcomputer-answered",
28105
+ method: "tools/call",
28106
+ params: { name: "browser_file_upload", arguments: {} }
28107
+ })
28108
+ }).then((answer) => answer.text()).catch(() => {
28109
+ });
28110
+ if (tool && ANSWERS.has(tool)) this.gate?.agentAnswered();
27995
28111
  const upstream = await fetch(`${origin}/mcp`, {
27996
28112
  method: request.method,
27997
28113
  headers,
@@ -28005,22 +28121,17 @@ var Browser = class {
28005
28121
  }
28006
28122
  async stop() {
28007
28123
  this.#stopping = true;
28008
- if (this.#exited) return;
28009
- const gone = new Promise((done) => this.#child.once("exit", () => done()));
28010
- this.#child.kill("SIGTERM");
28011
- const timer = setTimeout(() => this.#child.kill("SIGKILL"), STOP_MS);
28012
- await gone;
28013
- clearTimeout(timer);
28124
+ await Promise.all([this.#mcp, this.#host].map((child) => child ? end(child) : void 0));
28014
28125
  }
28015
28126
  };
28016
28127
 
28017
28128
  // src/inside.ts
28018
28129
  import { createServer as createServer3 } from "node:http";
28019
28130
  import { homedir } from "node:os";
28020
- import { join as join6 } from "node:path";
28131
+ import { join as join7 } from "node:path";
28021
28132
 
28022
28133
  // src/runtime.ts
28023
- import { join as join5 } from "node:path";
28134
+ import { join as join6 } from "node:path";
28024
28135
 
28025
28136
  // node_modules/@agentorg/exec/dist/lib.js
28026
28137
  import { realpathSync } from "node:fs";
@@ -28030,13 +28141,13 @@ import { Http2ServerRequest, constants } from "node:http2";
28030
28141
  import { Readable as Readable2 } from "node:stream";
28031
28142
  import { randomBytes as randomBytes2 } from "node:crypto";
28032
28143
  import { lstat, readdir, readFile, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
28033
- import { basename, dirname as dirname2, join as join2, resolve, sep } from "node:path";
28144
+ import { basename, dirname as dirname2, join as join3, resolve, sep as sep2 } from "node:path";
28034
28145
  import { spawn as spawn2 } from "node:child_process";
28035
28146
  import { randomBytes } from "node:crypto";
28036
28147
  import { StringDecoder } from "node:string_decoder";
28037
28148
  import { readdirSync, readFileSync, statSync } from "node:fs";
28038
- import { join as join22, relative, resolve as resolve2, sep as sep2 } from "node:path";
28039
- import { fileURLToPath } from "node:url";
28149
+ import { join as join22, relative, resolve as resolve2, sep as sep22 } from "node:path";
28150
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
28040
28151
  import { isMainThread, parentPort, Worker, workerData } from "node:worker_threads";
28041
28152
  var __create3 = Object.create;
28042
28153
  var __defProp3 = Object.defineProperty;
@@ -28163,21 +28274,21 @@ var require_ignore = __commonJS2({
28163
28274
  prev = EMPTY;
28164
28275
  } else if (char === "[" && pattern[index + 1] === ":") {
28165
28276
  const nameStart = index + 2;
28166
- let end = nameStart;
28167
- while (end < length && pattern[end] !== "]") {
28168
- end++;
28277
+ let end2 = nameStart;
28278
+ while (end2 < length && pattern[end2] !== "]") {
28279
+ end2++;
28169
28280
  }
28170
- if (end === length) {
28281
+ if (end2 === length) {
28171
28282
  return null;
28172
28283
  }
28173
- if (end > nameStart && pattern[end - 1] === ":") {
28174
- const name = pattern.slice(nameStart, end - 1);
28284
+ if (end2 > nameStart && pattern[end2 - 1] === ":") {
28285
+ const name = pattern.slice(nameStart, end2 - 1);
28175
28286
  if (!Object.prototype.hasOwnProperty.call(POSIX_CLASSES, name)) {
28176
28287
  return null;
28177
28288
  }
28178
28289
  body += POSIX_CLASSES[name];
28179
28290
  prev = EMPTY;
28180
- index = end;
28291
+ index = end2;
28181
28292
  } else {
28182
28293
  body += escapeMember("[");
28183
28294
  prev = "[";
@@ -28468,40 +28579,40 @@ var require_ignore = __commonJS2({
28468
28579
  tokens.push({ wildcard: true });
28469
28580
  index += WILDCARD2.length;
28470
28581
  } else if (char === "[") {
28471
- let end = index + 1;
28472
- if (source[end] === "^") {
28473
- end++;
28582
+ let end2 = index + 1;
28583
+ if (source[end2] === "^") {
28584
+ end2++;
28474
28585
  }
28475
- if (source[end] === "]") {
28476
- end++;
28586
+ if (source[end2] === "]") {
28587
+ end2++;
28477
28588
  }
28478
- while (end < length && source[end] !== "]") {
28479
- end += source[end] === ESCAPE ? 2 : 1;
28589
+ while (end2 < length && source[end2] !== "]") {
28590
+ end2 += source[end2] === ESCAPE ? 2 : 1;
28480
28591
  }
28481
- end++;
28482
- tokens.push({ single: source.slice(index, end) });
28483
- index = end;
28592
+ end2++;
28593
+ tokens.push({ single: source.slice(index, end2) });
28594
+ index = end2;
28484
28595
  } else if (char === ESCAPE) {
28485
28596
  tokens.push({ single: source.slice(index, index + 2) });
28486
28597
  index += 2;
28487
28598
  } else if (char === "(") {
28488
28599
  let depth = 0;
28489
- let end = index;
28600
+ let end2 = index;
28490
28601
  do {
28491
- if (source[end] === ESCAPE) {
28492
- end++;
28493
- } else if (source[end] === "(") {
28602
+ if (source[end2] === ESCAPE) {
28603
+ end2++;
28604
+ } else if (source[end2] === "(") {
28494
28605
  depth++;
28495
- } else if (source[end] === ")") {
28606
+ } else if (source[end2] === ")") {
28496
28607
  depth--;
28497
28608
  }
28498
- end++;
28499
- } while (end < length && depth > 0);
28500
- if ("*+?".indexOf(source[end]) >= 0) {
28501
- end++;
28609
+ end2++;
28610
+ } while (end2 < length && depth > 0);
28611
+ if ("*+?".indexOf(source[end2]) >= 0) {
28612
+ end2++;
28502
28613
  }
28503
- tokens.push({ boundary: source.slice(index, end) });
28504
- index = end;
28614
+ tokens.push({ boundary: source.slice(index, end2) });
28615
+ index = end2;
28505
28616
  } else if (char === "^" || char === "$") {
28506
28617
  tokens.push({ boundary: char });
28507
28618
  index++;
@@ -28578,10 +28689,10 @@ var require_ignore = __commonJS2({
28578
28689
  return index < 0 || index === body.length - 1;
28579
28690
  };
28580
28691
  var basenameOf = (path) => {
28581
- const end = path.length - 1;
28692
+ const end2 = path.length - 1;
28582
28693
  const index = path.lastIndexOf(
28583
28694
  SLASH,
28584
- path[end] === SLASH ? end - 1 : end
28695
+ path[end2] === SLASH ? end2 - 1 : end2
28585
28696
  );
28586
28697
  return index < 0 ? path : path.slice(index + 1);
28587
28698
  };
@@ -28591,10 +28702,10 @@ var require_ignore = __commonJS2({
28591
28702
  slices.pop();
28592
28703
  return slices.length ? slices.join(SLASH) + SLASH : EMPTY;
28593
28704
  }
28594
- const end = path.length - 1;
28705
+ const end2 = path.length - 1;
28595
28706
  const cut2 = path.lastIndexOf(
28596
28707
  SLASH,
28597
- path.charCodeAt(end) === SLASH_CODE ? end - 1 : end
28708
+ path.charCodeAt(end2) === SLASH_CODE ? end2 - 1 : end2
28598
28709
  );
28599
28710
  return cut2 < 0 ? EMPTY : path.slice(0, cut2 + 1);
28600
28711
  };
@@ -28642,22 +28753,22 @@ var require_ignore = __commonJS2({
28642
28753
  };
28643
28754
  var isLineEnd = (char) => char === "\r" || char === "\n";
28644
28755
  var trimEnd = (body) => {
28645
- let end = body.length;
28646
- while (end && isLineEnd(body[end - 1])) {
28647
- end--;
28756
+ let end2 = body.length;
28757
+ while (end2 && isLineEnd(body[end2 - 1])) {
28758
+ end2--;
28648
28759
  }
28649
- const lineEnd = end;
28650
- while (end && body[end - 1] === SPACE2) {
28651
- end--;
28760
+ const lineEnd = end2;
28761
+ while (end2 && body[end2 - 1] === SPACE2) {
28762
+ end2--;
28652
28763
  }
28653
- if (end === lineEnd) {
28654
- return body.slice(0, end);
28764
+ if (end2 === lineEnd) {
28765
+ return body.slice(0, end2);
28655
28766
  }
28656
28767
  let backslashes = 0;
28657
- while (backslashes < end && body[end - backslashes - 1] === ESCAPE) {
28768
+ while (backslashes < end2 && body[end2 - backslashes - 1] === ESCAPE) {
28658
28769
  backslashes++;
28659
28770
  }
28660
- return backslashes % 2 ? body.slice(0, end - 1) + SPACE2 : body.slice(0, end);
28771
+ return backslashes % 2 ? body.slice(0, end2 - 1) + SPACE2 : body.slice(0, end2);
28661
28772
  };
28662
28773
  var createRule = ({
28663
28774
  pattern,
@@ -29678,8 +29789,8 @@ function nullish2(input2) {
29678
29789
  }
29679
29790
  function cleanRegex2(source) {
29680
29791
  const start = source.startsWith("^") ? 1 : 0;
29681
- const end = source.endsWith("$") ? source.length - 1 : source.length;
29682
- return source.slice(start, end);
29792
+ const end2 = source.endsWith("$") ? source.length - 1 : source.length;
29793
+ return source.slice(start, end2);
29683
29794
  }
29684
29795
  function floatSafeRemainder2(val, step) {
29685
29796
  const ratio = val / step;
@@ -46010,15 +46121,15 @@ var initializer22 = (inst, issues) => {
46010
46121
  if (_installedErrorProtos2.has(proto))
46011
46122
  return;
46012
46123
  _installedErrorProtos2.add(proto);
46013
- _lazyMethod2(proto, "format", (self) => (mapper) => formatError2(self, mapper));
46014
- _lazyMethod2(proto, "flatten", (self) => (mapper) => flattenError2(self, mapper));
46015
- _lazyMethod2(proto, "addIssue", (self) => (issue22) => {
46016
- self.issues.push(issue22);
46017
- self.message = JSON.stringify(self.issues, jsonStringifyReplacer2, 2);
46124
+ _lazyMethod2(proto, "format", (self2) => (mapper) => formatError2(self2, mapper));
46125
+ _lazyMethod2(proto, "flatten", (self2) => (mapper) => flattenError2(self2, mapper));
46126
+ _lazyMethod2(proto, "addIssue", (self2) => (issue22) => {
46127
+ self2.issues.push(issue22);
46128
+ self2.message = JSON.stringify(self2.issues, jsonStringifyReplacer2, 2);
46018
46129
  });
46019
- _lazyMethod2(proto, "addIssues", (self) => (issues2) => {
46020
- self.issues.push(...issues2);
46021
- self.message = JSON.stringify(self.issues, jsonStringifyReplacer2, 2);
46130
+ _lazyMethod2(proto, "addIssues", (self2) => (issues2) => {
46131
+ self2.issues.push(...issues2);
46132
+ self2.message = JSON.stringify(self2.issues, jsonStringifyReplacer2, 2);
46022
46133
  });
46023
46134
  Object.defineProperty(proto, "isEmpty", {
46024
46135
  configurable: true,
@@ -46860,7 +46971,7 @@ var ZodObject2 = /* @__PURE__ */ $constructor2("ZodObject", (inst, def) => {
46860
46971
  $ZodObjectJIT2.init(inst, def);
46861
46972
  ZodType2.init(inst, def);
46862
46973
  inst._zod.processJSONSchema = (ctx, json32, params) => objectProcessor2(inst, ctx, json32, params);
46863
- util_exports2.installLazyProp(inst, "shape", (self) => self._zod.def.shape, false);
46974
+ util_exports2.installLazyProp(inst, "shape", (self2) => self2._zod.def.shape, false);
46864
46975
  }, {
46865
46976
  keyof() {
46866
46977
  return _enum22(Object.keys(this._zod.def.shape));
@@ -55005,10 +55116,10 @@ var require_util2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
55005
55116
  }
55006
55117
  exports.alwaysValidSchema = alwaysValidSchema;
55007
55118
  function checkUnknownRules(it, schema = it.schema) {
55008
- const { opts, self } = it;
55119
+ const { opts, self: self2 } = it;
55009
55120
  if (!opts.strictSchema) return;
55010
55121
  if (typeof schema === "boolean") return;
55011
- const rules = self.RULES.keywords;
55122
+ const rules = self2.RULES.keywords;
55012
55123
  for (const key in schema) if (!rules[key]) checkStrictMode(it, `unknown keyword: "${key}"`);
55013
55124
  }
55014
55125
  exports.checkUnknownRules = checkUnknownRules;
@@ -55340,8 +55451,8 @@ var require_rules2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
55340
55451
  var require_applicability2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
55341
55452
  Object.defineProperty(exports, "__esModule", { value: true });
55342
55453
  exports.shouldUseRule = exports.shouldUseGroup = exports.schemaHasRulesForType = void 0;
55343
- function schemaHasRulesForType({ schema, self }, type) {
55344
- const group = self.RULES.types[type];
55454
+ function schemaHasRulesForType({ schema, self: self2 }, type) {
55455
+ const group = self2.RULES.types[type];
55345
55456
  return group && group !== true && shouldUseGroup(schema, group);
55346
55457
  }
55347
55458
  exports.schemaHasRulesForType = schemaHasRulesForType;
@@ -55754,14 +55865,14 @@ var require_keyword2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
55754
55865
  return !schemaType.length || schemaType.some((st) => st === "array" ? Array.isArray(schema) : st === "object" ? schema && typeof schema == "object" && !Array.isArray(schema) : typeof schema == st || allowUndefined && typeof schema == "undefined");
55755
55866
  }
55756
55867
  exports.validSchemaType = validSchemaType;
55757
- function validateKeywordUsage({ schema, opts, self, errSchemaPath }, def, keyword) {
55868
+ function validateKeywordUsage({ schema, opts, self: self2, errSchemaPath }, def, keyword) {
55758
55869
  if (Array.isArray(def.keyword) ? !def.keyword.includes(keyword) : def.keyword !== keyword) throw new Error("ajv implementation error");
55759
55870
  const deps = def.dependencies;
55760
55871
  if (deps === null || deps === void 0 ? void 0 : deps.some((kwd) => !Object.prototype.hasOwnProperty.call(schema, kwd))) throw new Error(`parent schema must have dependencies of ${keyword}: ${deps.join(",")}`);
55761
55872
  if (def.validateSchema) {
55762
55873
  if (!def.validateSchema(schema[keyword])) {
55763
- const msg = `keyword "${keyword}" value is invalid at path "${errSchemaPath}": ` + self.errorsText(def.validateSchema.errors);
55764
- if (opts.validateSchema === "log") self.logger.error(msg);
55874
+ const msg = `keyword "${keyword}" value is invalid at path "${errSchemaPath}": ` + self2.errorsText(def.validateSchema.errors);
55875
+ if (opts.validateSchema === "log") self2.logger.error(msg);
55765
55876
  else throw new Error(msg);
55766
55877
  }
55767
55878
  }
@@ -56145,9 +56256,9 @@ var require_validate2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
56145
56256
  }
56146
56257
  (0, boolSchema_1.boolOrEmptySchema)(it, valid);
56147
56258
  }
56148
- function schemaCxtHasRules({ schema, self }) {
56259
+ function schemaCxtHasRules({ schema, self: self2 }) {
56149
56260
  if (typeof schema == "boolean") return !schema;
56150
- for (const key in schema) if (self.RULES.all[key]) return true;
56261
+ for (const key in schema) if (self2.RULES.all[key]) return true;
56151
56262
  return false;
56152
56263
  }
56153
56264
  function isSchemaObj(it) {
@@ -56172,8 +56283,8 @@ var require_validate2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
56172
56283
  schemaKeywords(it, types, !(0, dataType_1.coerceAndCheckDataType)(it, types), errsCount);
56173
56284
  }
56174
56285
  function checkRefsAndKeywords(it) {
56175
- const { schema, errSchemaPath, opts, self } = it;
56176
- if (schema.$ref && opts.ignoreKeywordsWithRef && (0, util_1.schemaHasRulesButRef)(schema, self.RULES)) self.logger.warn(`$ref: keywords ignored in schema at path "${errSchemaPath}"`);
56286
+ const { schema, errSchemaPath, opts, self: self2 } = it;
56287
+ if (schema.$ref && opts.ignoreKeywordsWithRef && (0, util_1.schemaHasRulesButRef)(schema, self2.RULES)) self2.logger.warn(`$ref: keywords ignored in schema at path "${errSchemaPath}"`);
56177
56288
  }
56178
56289
  function checkNoDefault(it) {
56179
56290
  const { schema, opts } = it;
@@ -56209,8 +56320,8 @@ var require_validate2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
56209
56320
  if (items instanceof codegen_1.Name) gen.assign((0, codegen_1._)`${evaluated}.items`, items);
56210
56321
  }
56211
56322
  function schemaKeywords(it, types, typeErrors, errsCount) {
56212
- const { gen, schema, data, allErrors, opts, self } = it;
56213
- const { RULES } = self;
56323
+ const { gen, schema, data, allErrors, opts, self: self2 } = it;
56324
+ const { RULES } = self2;
56214
56325
  if (schema.$ref && (opts.ignoreKeywordsWithRef || !(0, util_1.schemaHasRulesButRef)(schema, RULES))) {
56215
56326
  gen.block(() => keywordCode(it, "$ref", RULES.all.$ref.definition));
56216
56327
  return;
@@ -58232,10 +58343,10 @@ var require_ref2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
58232
58343
  schemaType: "string",
58233
58344
  code(cxt) {
58234
58345
  const { gen, schema: $ref, it } = cxt;
58235
- const { baseId, schemaEnv: env, validateName, opts, self } = it;
58346
+ const { baseId, schemaEnv: env, validateName, opts, self: self2 } = it;
58236
58347
  const { root } = env;
58237
58348
  if (($ref === "#" || $ref === "#/") && baseId === root.baseId) return callRootRef();
58238
- const schOrEnv = compile_1.resolveRef.call(self, root, baseId, $ref);
58349
+ const schOrEnv = compile_1.resolveRef.call(self2, root, baseId, $ref);
58239
58350
  if (schOrEnv === void 0) throw new ref_error_1.default(it.opts.uriResolver, baseId, $ref);
58240
58351
  if (schOrEnv instanceof compile_1.SchemaEnv) return callValidate(schOrEnv);
58241
58352
  return inlineRefSchema(schOrEnv);
@@ -59495,13 +59606,13 @@ var require_format$22 = /* @__PURE__ */ __commonJSMin2(((exports) => {
59495
59606
  },
59496
59607
  code(cxt, ruleType) {
59497
59608
  const { gen, data, $data, schema, schemaCode, it } = cxt;
59498
- const { opts, errSchemaPath, schemaEnv, self } = it;
59609
+ const { opts, errSchemaPath, schemaEnv, self: self2 } = it;
59499
59610
  if (!opts.validateFormats) return;
59500
59611
  if ($data) validate$DataFormat();
59501
59612
  else validateFormat();
59502
59613
  function validate$DataFormat() {
59503
59614
  const fmts = gen.scopeValue("formats", {
59504
- ref: self.formats,
59615
+ ref: self2.formats,
59505
59616
  code: opts.code.formats
59506
59617
  });
59507
59618
  const fDef = gen.const("fDef", (0, codegen_1._)`${fmts}[${schemaCode}]`);
@@ -59520,7 +59631,7 @@ var require_format$22 = /* @__PURE__ */ __commonJSMin2(((exports) => {
59520
59631
  }
59521
59632
  }
59522
59633
  function validateFormat() {
59523
- const formatDef = self.formats[schema];
59634
+ const formatDef = self2.formats[schema];
59524
59635
  if (!formatDef) {
59525
59636
  unknownFormat();
59526
59637
  return;
@@ -59530,7 +59641,7 @@ var require_format$22 = /* @__PURE__ */ __commonJSMin2(((exports) => {
59530
59641
  if (fmtType === ruleType) cxt.pass(validCondition());
59531
59642
  function unknownFormat() {
59532
59643
  if (opts.strictSchema === false) {
59533
- self.logger.warn(unknownMsg());
59644
+ self2.logger.warn(unknownMsg());
59534
59645
  return;
59535
59646
  }
59536
59647
  throw new Error(unknownMsg());
@@ -59956,9 +60067,9 @@ var require_dynamicAnchor2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
59956
60067
  }
59957
60068
  exports.dynamicAnchor = dynamicAnchor;
59958
60069
  function _getValidate(cxt) {
59959
- const { schemaEnv, schema, self } = cxt.it;
60070
+ const { schemaEnv, schema, self: self2 } = cxt.it;
59960
60071
  const { root, baseId, localRefs, meta: meta3 } = schemaEnv.root;
59961
- const { schemaId } = self.opts;
60072
+ const { schemaId } = self2.opts;
59962
60073
  const sch = new compile_1.SchemaEnv({
59963
60074
  schema,
59964
60075
  schemaId,
@@ -59967,7 +60078,7 @@ var require_dynamicAnchor2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
59967
60078
  localRefs,
59968
60079
  meta: meta3
59969
60080
  });
59970
- compile_1.compileSchema.call(self, sch);
60081
+ compile_1.compileSchema.call(self2, sch);
59971
60082
  return (0, ref_1.getValidate)(cxt, sch);
59972
60083
  }
59973
60084
  exports.default = def;
@@ -61267,14 +61378,14 @@ var require_limit2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
61267
61378
  error: error62,
61268
61379
  code(cxt) {
61269
61380
  const { gen, data, schemaCode, keyword, it } = cxt;
61270
- const { opts, self } = it;
61381
+ const { opts, self: self2 } = it;
61271
61382
  if (!opts.validateFormats) return;
61272
- const fCxt = new ajv_1.KeywordCxt(it, self.RULES.all.format.definition, "format");
61383
+ const fCxt = new ajv_1.KeywordCxt(it, self2.RULES.all.format.definition, "format");
61273
61384
  if (fCxt.$data) validate$DataFormat();
61274
61385
  else validateFormat();
61275
61386
  function validate$DataFormat() {
61276
61387
  const fmts = gen.scopeValue("formats", {
61277
- ref: self.formats,
61388
+ ref: self2.formats,
61278
61389
  code: opts.code.formats
61279
61390
  });
61280
61391
  const fmt = gen.const("fmt", (0, codegen_1._)`${fmts}[${fCxt.schemaCode}]`);
@@ -61282,7 +61393,7 @@ var require_limit2 = /* @__PURE__ */ __commonJSMin2(((exports) => {
61282
61393
  }
61283
61394
  function validateFormat() {
61284
61395
  const format = fCxt.schema;
61285
- const fmtDef = self.formats[format];
61396
+ const fmtDef = self2.formats[format];
61286
61397
  if (!fmtDef || fmtDef === true) return;
61287
61398
  if (typeof fmtDef != "object" || fmtDef instanceof RegExp || typeof fmtDef.compare != "function") throw new Error(`"${keyword}": format "${format}" does not define "compare" function`);
61288
61399
  const fmt = gen.scopeValue("formats", {
@@ -63892,10 +64003,10 @@ var isHttpWhitespace = (code) => code === 9 || code === 10 || code === 13 || cod
63892
64003
  var normalizeHeaderValue = (value) => {
63893
64004
  if (!isHttpWhitespace(value.charCodeAt(0)) && !isHttpWhitespace(value.charCodeAt(value.length - 1))) return value;
63894
64005
  let start = 0;
63895
- let end = value.length;
63896
- while (start < end && isHttpWhitespace(value.charCodeAt(start))) start++;
63897
- while (end > start && isHttpWhitespace(value.charCodeAt(end - 1))) end--;
63898
- return value.slice(start, end);
64006
+ let end2 = value.length;
64007
+ while (start < end2 && isHttpWhitespace(value.charCodeAt(start))) start++;
64008
+ while (end2 > start && isHttpWhitespace(value.charCodeAt(end2 - 1))) end2--;
64009
+ return value.slice(start, end2);
63899
64010
  };
63900
64011
  var forbiddenHeaderValue = /[\0\r\n]/;
63901
64012
  var GlobalHeaders = globalThis.Headers;
@@ -65885,11 +65996,11 @@ async function inside(root, path) {
65885
65996
  throw refused2();
65886
65997
  const above = dirname2(at);
65887
65998
  if (above === at) throw refused2();
65888
- return join2(await real(above), basename(at));
65999
+ return join3(await real(above), basename(at));
65889
66000
  }
65890
66001
  };
65891
66002
  const found = await real(wanted);
65892
- if (found !== root && !found.startsWith(root + sep)) throw refused2();
66003
+ if (found !== root && !found.startsWith(root + sep2)) throw refused2();
65893
66004
  return found;
65894
66005
  }
65895
66006
  function createFiles(root) {
@@ -65919,7 +66030,7 @@ ${cut(shown.join("\n"), MAX_READ_CHARS)}`;
65919
66030
  const lines = await Promise.all(
65920
66031
  entries.slice(0, MAX_ENTRIES).map(async (entry) => {
65921
66032
  if (entry.isDirectory()) return `${entry.name}/`;
65922
- const { size } = await lstat(join2(folder, entry.name));
66033
+ const { size } = await lstat(join3(folder, entry.name));
65923
66034
  return `${entry.name} ${size}`;
65924
66035
  })
65925
66036
  );
@@ -65956,7 +66067,7 @@ ${cut(shown.join("\n"), MAX_READ_CHARS)}`;
65956
66067
  after = before.split(input2.old_text).join(input2.new_text);
65957
66068
  }
65958
66069
  if (after === before) throw new ExecRefused("That edit changes nothing.");
65959
- const temporary = join2(dirname2(path), `.agentexec-${randomBytes2(6).toString("hex")}`);
66070
+ const temporary = join3(dirname2(path), `.agentexec-${randomBytes2(6).toString("hex")}`);
65960
66071
  try {
65961
66072
  await writeFile(temporary, after, found ? { mode: found.mode } : {});
65962
66073
  await rename(temporary, path);
@@ -66003,7 +66114,7 @@ function run(job) {
66003
66114
  const path = join22(folder, entry.name);
66004
66115
  const suffix = entry.isDirectory() ? "/" : "";
66005
66116
  const ignored = here.some(
66006
- (rule) => rule.ignore.ignores(relative(rule.base, path).split(sep2).join("/") + suffix)
66117
+ (rule) => rule.ignore.ignores(relative(rule.base, path).split(sep22).join("/") + suffix)
66007
66118
  );
66008
66119
  if (ignored) continue;
66009
66120
  try {
@@ -66022,7 +66133,7 @@ async function search(root, input2) {
66022
66133
  const path = await inside(root, input2.path ?? ".");
66023
66134
  return new Promise((done, failed) => {
66024
66135
  const workerData2 = { ...input2, path, root, agentexecSearch: true };
66025
- const worker = new Worker(fileURLToPath(import.meta.url), { workerData: workerData2 });
66136
+ const worker = new Worker(fileURLToPath2(import.meta.url), { workerData: workerData2 });
66026
66137
  const timer = setTimeout(() => {
66027
66138
  void worker.terminate();
66028
66139
  failed(new ExecRefused(`That search took over ${DEADLINE_MS / 1e3} s, so it was stopped.`));
@@ -66191,10 +66302,345 @@ function createAgentExec(options) {
66191
66302
  };
66192
66303
  }
66193
66304
 
66305
+ // src/screencast.ts
66306
+ async function startScreencast(page, onFrame) {
66307
+ await page.screencast.start({
66308
+ quality: 70,
66309
+ onFrame: ({ data, viewportWidth, viewportHeight }) => onFrame({ data, width: viewportWidth, height: viewportHeight })
66310
+ });
66311
+ return () => page.screencast.stop().catch(() => {
66312
+ });
66313
+ }
66314
+
66315
+ // src/browser-live.ts
66316
+ var WAIT_MS = 25e3;
66317
+ var IDLE_MS = 6e4;
66318
+ var STEP_MS = 2e3;
66319
+ var MAX_BUFFERED = 4 * 1024 * 1024;
66320
+ var sleep3 = (ms) => new Promise((done) => setTimeout(done, ms));
66321
+ var within = (work, ms) => Promise.race([work, sleep3(ms).then(() => void 0)]);
66322
+ var BrowserLive = class {
66323
+ #endpoint;
66324
+ #sockets = /* @__PURE__ */ new Map();
66325
+ #viewer;
66326
+ #context;
66327
+ #ids = /* @__PURE__ */ new Map();
66328
+ #nextId = 1;
66329
+ #shown;
66330
+ #stopCast;
66331
+ #size = { width: 0, height: 0 };
66332
+ #dialog;
66333
+ #chooser;
66334
+ #choice;
66335
+ #swallowUp = false;
66336
+ #driver;
66337
+ #lastInput = 0;
66338
+ #agentWaiting = 0;
66339
+ #answeredChooser = false;
66340
+ #steps = Promise.resolve();
66341
+ constructor(endpoint) {
66342
+ this.#endpoint = endpoint;
66343
+ }
66344
+ // ---- The agent's side
66345
+ async wait() {
66346
+ if (!this.#held()) return void 0;
66347
+ this.#agentWaiting++;
66348
+ this.#announceDriver();
66349
+ try {
66350
+ const deadline = Date.now() + WAIT_MS;
66351
+ while (this.#held() && Date.now() < deadline) await sleep3(200);
66352
+ return this.#held() ? "A person has the browser now, so this didn't run. Try again later." : "A person used the browser, so this didn't run and the page may have changed. Take a new snapshot before you act.";
66353
+ } finally {
66354
+ this.#agentWaiting--;
66355
+ this.#announceDriver();
66356
+ }
66357
+ }
66358
+ takeAnsweredChooser() {
66359
+ const answered2 = this.#answeredChooser;
66360
+ this.#answeredChooser = false;
66361
+ return answered2;
66362
+ }
66363
+ agentAnswered() {
66364
+ this.#dialog = void 0;
66365
+ this.#chooser = void 0;
66366
+ this.#broadcast({ type: "dialog", open: false });
66367
+ this.#broadcast({ type: "file-chooser", open: false });
66368
+ }
66369
+ // ---- The person's side
66370
+ open(ws, mode) {
66371
+ this.#sockets.set(ws, mode);
66372
+ ws.on("close", () => this.#left(ws));
66373
+ ws.on("message", (data, binary) => {
66374
+ if (binary || this.#sockets.get(ws) !== "operate") return;
66375
+ let message;
66376
+ try {
66377
+ message = JSON.parse(data.toString());
66378
+ } catch {
66379
+ return;
66380
+ }
66381
+ this.#input(ws, message);
66382
+ });
66383
+ this.#begin().then(
66384
+ () => this.#greet(ws),
66385
+ () => ws.close(1011, "The browser can't be reached.")
66386
+ );
66387
+ }
66388
+ async close() {
66389
+ for (const ws of this.#sockets.keys()) ws.close(1001, "It stopped.");
66390
+ await this.#end();
66391
+ }
66392
+ #held() {
66393
+ return this.#driver !== void 0 && Date.now() - this.#lastInput < IDLE_MS;
66394
+ }
66395
+ #send(ws, message) {
66396
+ if (ws.readyState === ws.OPEN) ws.send(JSON.stringify(message));
66397
+ }
66398
+ #broadcast(message) {
66399
+ for (const ws of this.#sockets.keys()) this.#send(ws, message);
66400
+ }
66401
+ #announceDriver() {
66402
+ for (const ws of this.#sockets.keys())
66403
+ this.#send(ws, {
66404
+ type: "driver",
66405
+ you: ws === this.#driver && this.#held(),
66406
+ held: this.#held(),
66407
+ agentWaiting: this.#agentWaiting > 0
66408
+ });
66409
+ }
66410
+ async #begin() {
66411
+ this.#viewer ??= (async () => {
66412
+ const viewer = await playwright().chromium.connect(await this.#endpoint);
66413
+ const context = viewer.contexts()[0] ?? await viewer.newContext();
66414
+ this.#context = context;
66415
+ for (const page of context.pages()) this.#track(page);
66416
+ context.on("page", (page) => {
66417
+ this.#track(page);
66418
+ void this.#show(page);
66419
+ });
66420
+ await this.#show(context.pages().at(-1) ?? await context.newPage());
66421
+ return viewer;
66422
+ })();
66423
+ await this.#viewer;
66424
+ }
66425
+ async #end() {
66426
+ const viewer = this.#viewer;
66427
+ this.#viewer = void 0;
66428
+ await this.#stopCast?.();
66429
+ this.#stopCast = void 0;
66430
+ this.#shown = void 0;
66431
+ this.#ids.clear();
66432
+ await (await viewer?.catch(() => void 0))?.close().catch(() => {
66433
+ });
66434
+ }
66435
+ #left(ws) {
66436
+ this.#sockets.delete(ws);
66437
+ if (this.#driver === ws) {
66438
+ this.#driver = void 0;
66439
+ this.#announceDriver();
66440
+ }
66441
+ if (this.#sockets.size === 0) void this.#end();
66442
+ }
66443
+ async #greet(ws) {
66444
+ await this.#tabs(ws);
66445
+ if (this.#size.width) this.#send(ws, { type: "viewport", ...this.#size });
66446
+ if (this.#dialog)
66447
+ this.#send(ws, {
66448
+ type: "dialog",
66449
+ open: true,
66450
+ kind: this.#dialog.type(),
66451
+ message: this.#dialog.message()
66452
+ });
66453
+ if (this.#chooser)
66454
+ this.#send(ws, { type: "file-chooser", open: true, multiple: this.#chooser.isMultiple() });
66455
+ this.#announceDriver();
66456
+ }
66457
+ #track(page) {
66458
+ if (this.#ids.has(page)) return;
66459
+ this.#ids.set(page, this.#nextId++);
66460
+ page.on("dialog", (dialog) => {
66461
+ this.#dialog = dialog;
66462
+ this.#broadcast({
66463
+ type: "dialog",
66464
+ open: true,
66465
+ kind: dialog.type(),
66466
+ message: dialog.message(),
66467
+ ...dialog.defaultValue() ? { defaultValue: dialog.defaultValue() } : {}
66468
+ });
66469
+ });
66470
+ page.on("filechooser", (chooser) => {
66471
+ this.#chooser = chooser;
66472
+ this.#broadcast({ type: "file-chooser", open: true, multiple: chooser.isMultiple() });
66473
+ });
66474
+ page.on("framenavigated", (frame) => {
66475
+ if (frame === page.mainFrame()) void this.#tabs();
66476
+ });
66477
+ page.on("close", () => {
66478
+ this.#ids.delete(page);
66479
+ if (this.#shown === page) void this.#show(this.#context?.pages().at(-1));
66480
+ else void this.#tabs();
66481
+ });
66482
+ }
66483
+ /** Which page the frames are of: the newest by default, or the one the person picked. */
66484
+ async #show(page) {
66485
+ if (page === this.#shown) return;
66486
+ await this.#stopCast?.();
66487
+ this.#stopCast = void 0;
66488
+ this.#shown = page;
66489
+ this.#choice = void 0;
66490
+ if (page) {
66491
+ this.#stopCast = await startScreencast(page, (frame) => {
66492
+ if (frame.width !== this.#size.width || frame.height !== this.#size.height) {
66493
+ this.#size = { width: frame.width, height: frame.height };
66494
+ this.#broadcast({ type: "viewport", ...this.#size });
66495
+ }
66496
+ for (const ws of this.#sockets.keys())
66497
+ if (ws.readyState === ws.OPEN && ws.bufferedAmount < MAX_BUFFERED) ws.send(frame.data);
66498
+ }).catch(() => void 0);
66499
+ }
66500
+ await this.#tabs();
66501
+ }
66502
+ async #tabs(only) {
66503
+ const tabs = await Promise.all(
66504
+ [...this.#ids].map(async ([page, id]) => ({
66505
+ id,
66506
+ url: page.url(),
66507
+ title: await within(page.title(), STEP_MS).catch(() => void 0) ?? ""
66508
+ }))
66509
+ );
66510
+ const message = {
66511
+ type: "tabs",
66512
+ tabs,
66513
+ shown: (this.#shown && this.#ids.get(this.#shown)) ?? null
66514
+ };
66515
+ if (only) this.#send(only, message);
66516
+ else this.#broadcast(message);
66517
+ }
66518
+ /** Each step in order, none waiting on another for long: a dialog blocks the page's input. */
66519
+ #step(work) {
66520
+ this.#steps = this.#steps.then(() => within(work(), STEP_MS)).catch(() => {
66521
+ });
66522
+ }
66523
+ #input(ws, message) {
66524
+ if (message.type === "release") {
66525
+ if (this.#driver === ws) this.#driver = void 0;
66526
+ return this.#announceDriver();
66527
+ }
66528
+ const changed = this.#driver !== ws || !this.#held();
66529
+ this.#driver = ws;
66530
+ this.#lastInput = Date.now();
66531
+ if (changed) this.#announceDriver();
66532
+ const page = this.#shown;
66533
+ switch (message.type) {
66534
+ case "mouse":
66535
+ if (!page) return;
66536
+ return this.#step(() => this.#mouse(page, message));
66537
+ case "key":
66538
+ if (!page) return;
66539
+ return this.#step(
66540
+ () => message.action === "down" ? page.keyboard.down(message.key) : page.keyboard.up(message.key)
66541
+ );
66542
+ case "text":
66543
+ if (!page) return;
66544
+ return this.#step(() => page.keyboard.insertText(message.text));
66545
+ case "dialog": {
66546
+ const dialog = this.#dialog;
66547
+ this.#dialog = void 0;
66548
+ this.#broadcast({ type: "dialog", open: false });
66549
+ if (!dialog) return;
66550
+ return this.#step(
66551
+ () => message.accept ? dialog.accept(message.text ?? void 0) : dialog.dismiss()
66552
+ );
66553
+ }
66554
+ case "files": {
66555
+ const chooser = this.#chooser;
66556
+ this.#chooser = void 0;
66557
+ this.#broadcast({ type: "file-chooser", open: false });
66558
+ if (!chooser) return;
66559
+ this.#answeredChooser = true;
66560
+ return this.#step(
66561
+ () => chooser.setFiles(
66562
+ message.files.map((file2) => ({
66563
+ name: file2.name,
66564
+ mimeType: file2.mimeType ?? "application/octet-stream",
66565
+ buffer: Buffer.from(file2.data, "base64")
66566
+ }))
66567
+ )
66568
+ );
66569
+ }
66570
+ case "choice": {
66571
+ const choice = this.#choice;
66572
+ this.#choice = void 0;
66573
+ if (!choice) return;
66574
+ return this.#step(() => choice.selectOption(message.values));
66575
+ }
66576
+ case "tab":
66577
+ return this.#step(() => this.#tab(message));
66578
+ case "navigate":
66579
+ if (!page) return;
66580
+ return this.#step(async () => {
66581
+ if (message.to === "back") await page.goBack();
66582
+ else if (message.to === "forward") await page.goForward();
66583
+ else if (message.to === "reload") await page.reload();
66584
+ else await page.goto(message.to);
66585
+ });
66586
+ }
66587
+ }
66588
+ async #mouse(page, message) {
66589
+ const { x, y } = message;
66590
+ if (message.action === "move") return page.mouse.move(x, y);
66591
+ if (message.action === "wheel")
66592
+ return page.mouse.wheel(message.deltaX ?? 0, message.deltaY ?? 0);
66593
+ const button = message.button ?? "left";
66594
+ if (message.action === "up") {
66595
+ if (this.#swallowUp) {
66596
+ this.#swallowUp = false;
66597
+ return;
66598
+ }
66599
+ return page.mouse.up({ button });
66600
+ }
66601
+ if (button === "left") {
66602
+ const choice = await page.evaluate(
66603
+ ([px, py]) => {
66604
+ const list = document.elementFromPoint(px, py);
66605
+ if (list?.tagName !== "SELECT" || list.disabled) return null;
66606
+ return {
66607
+ multiple: list.multiple,
66608
+ options: Array.from(list.options).map((option) => ({
66609
+ value: option.value,
66610
+ label: option.label,
66611
+ selected: option.selected
66612
+ }))
66613
+ };
66614
+ },
66615
+ [x, y]
66616
+ ).catch(() => null);
66617
+ if (choice) {
66618
+ const handle = await page.evaluateHandle(
66619
+ ([px, py]) => document.elementFromPoint(px, py),
66620
+ [x, y]
66621
+ );
66622
+ this.#choice = handle.asElement() ?? void 0;
66623
+ this.#swallowUp = true;
66624
+ return this.#broadcast({ type: "choice", ...choice });
66625
+ }
66626
+ }
66627
+ await page.mouse.move(x, y);
66628
+ return page.mouse.down({ button });
66629
+ }
66630
+ async #tab(message) {
66631
+ const byId = (id) => [...this.#ids].find(([, known]) => known === id)?.[0];
66632
+ if (message.action === "show") return this.#show(byId(message.id));
66633
+ if (message.action === "close") return byId(message.id)?.close();
66634
+ const page = await this.#context?.newPage();
66635
+ if (page && message.url) await page.goto(message.url).catch(() => {
66636
+ });
66637
+ }
66638
+ };
66639
+
66194
66640
  // src/live.ts
66195
66641
  import { chmodSync, existsSync, statSync as statSync2 } from "node:fs";
66196
- import { createRequire as createRequire2 } from "node:module";
66197
- import { dirname as dirname3, join as join3 } from "node:path";
66642
+ import { createRequire as createRequire3 } from "node:module";
66643
+ import { dirname as dirname3, join as join4 } from "node:path";
66198
66644
 
66199
66645
  // node_modules/ws/wrapper.mjs
66200
66646
  var import_stream2 = __toESM(require_stream(), 1);
@@ -66207,7 +66653,11 @@ var import_websocket = __toESM(require_websocket(), 1);
66207
66653
  var import_websocket_server = __toESM(require_websocket_server(), 1);
66208
66654
 
66209
66655
  // src/live.ts
66210
- var PROTOCOLS = { commands: "commands@1", terminal: "pty@1" };
66656
+ var PROTOCOLS = {
66657
+ commands: "commands@1",
66658
+ terminal: "pty@1",
66659
+ browser: "screencast@1"
66660
+ };
66211
66661
  var MAX_EVENTS = 2e3;
66212
66662
  var MAX_SCROLLBACK = 64 * 1024;
66213
66663
  var OUTPUT = 48;
@@ -66217,24 +66667,24 @@ var sockets = new import_websocket_server.default({ noServer: true });
66217
66667
  var pty;
66218
66668
  var loadPty = () => {
66219
66669
  pty ??= (async () => {
66220
- const require2 = createRequire2(import.meta.url);
66221
- let loaded;
66670
+ const require2 = createRequire3(import.meta.url);
66671
+ let loaded2;
66222
66672
  try {
66223
- loaded = require2("node-pty");
66673
+ loaded2 = require2("node-pty");
66224
66674
  } catch {
66225
66675
  return "The terminal needs node-pty, which isn't installed with this service.";
66226
66676
  }
66227
66677
  const root = dirname3(require2.resolve("node-pty/package.json"));
66228
66678
  for (const helper of [
66229
- join3(root, "prebuilds", `${process.platform}-${process.arch}`, "spawn-helper"),
66230
- join3(root, "build", "Release", "spawn-helper")
66679
+ join4(root, "prebuilds", `${process.platform}-${process.arch}`, "spawn-helper"),
66680
+ join4(root, "build", "Release", "spawn-helper")
66231
66681
  ])
66232
66682
  try {
66233
66683
  if (existsSync(helper) && (statSync2(helper).mode & 73) === 0) chmodSync(helper, 493);
66234
66684
  } catch {
66235
66685
  return `The terminal needs ${helper} to be executable, and it isn't.`;
66236
66686
  }
66237
- return loaded;
66687
+ return loaded2;
66238
66688
  })();
66239
66689
  return pty;
66240
66690
  };
@@ -66246,23 +66696,30 @@ var Live = class {
66246
66696
  #shells = /* @__PURE__ */ new Map();
66247
66697
  #shell;
66248
66698
  #scrollback = "";
66249
- constructor(exec, workspace, terminal) {
66699
+ #browser;
66700
+ constructor(exec, workspace, terminal, browser) {
66250
66701
  this.#workspace = workspace;
66251
66702
  this.#terminal = terminal && exec !== void 0;
66703
+ this.#browser = browser;
66252
66704
  exec?.onCommand((event) => this.#heard(event));
66253
66705
  }
66254
66706
  async surfaces() {
66255
- if (!this.#terminal) return [];
66256
- const loaded = await loadPty();
66257
- return [
66258
- { surface: "commands", protocol: PROTOCOLS.commands, operate: false },
66259
- {
66260
- surface: "terminal",
66261
- protocol: PROTOCOLS.terminal,
66262
- operate: true,
66263
- ...typeof loaded === "string" ? { unavailable: loaded } : {}
66264
- }
66265
- ];
66707
+ const surfaces = [];
66708
+ if (this.#terminal) {
66709
+ const loaded2 = await loadPty();
66710
+ surfaces.push(
66711
+ { surface: "commands", protocol: PROTOCOLS.commands, operate: false },
66712
+ {
66713
+ surface: "terminal",
66714
+ protocol: PROTOCOLS.terminal,
66715
+ operate: true,
66716
+ ...typeof loaded2 === "string" ? { unavailable: loaded2 } : {}
66717
+ }
66718
+ );
66719
+ }
66720
+ if (this.#browser)
66721
+ surfaces.push({ surface: "browser", protocol: PROTOCOLS.browser, operate: true });
66722
+ return surfaces;
66266
66723
  }
66267
66724
  /** Take an upgraded request as a socket on one surface. */
66268
66725
  open(surface, mode, request, socket, head) {
@@ -66270,10 +66727,13 @@ var Live = class {
66270
66727
  sockets.handleUpgrade(request, socket, head, (ws) => {
66271
66728
  ws.on("error", () => ws.terminate());
66272
66729
  if (surface === "commands") this.#watch(ws);
66273
- else this.#attach(ws, mode).catch(() => ws.terminate());
66730
+ else if (surface === "browser" && this.#browser) this.#browser.open(ws, mode);
66731
+ else if (surface === "terminal") this.#attach(ws, mode).catch(() => ws.terminate());
66732
+ else ws.close(1011, `There's no ${surface} here.`);
66274
66733
  });
66275
66734
  }
66276
66735
  close() {
66736
+ void this.#browser?.close();
66277
66737
  for (const ws of [...this.#watchers, ...this.#shells.keys()]) ws.close(1001, "It stopped.");
66278
66738
  this.#shell?.kill();
66279
66739
  this.#shell = void 0;
@@ -66292,13 +66752,13 @@ var Live = class {
66292
66752
  }
66293
66753
  /** pty@1: one shell for the computer, shared by every socket on it. */
66294
66754
  async #attach(ws, mode) {
66295
- const loaded = await loadPty();
66296
- if (typeof loaded === "string") return ws.close(1011, loaded);
66755
+ const loaded2 = await loadPty();
66756
+ if (typeof loaded2 === "string") return ws.close(1011, loaded2);
66297
66757
  if (!this.#shell) {
66298
66758
  this.#scrollback = "";
66299
66759
  let shell;
66300
66760
  try {
66301
- shell = loaded.spawn(process.env.SHELL || "/bin/bash", ["-l"], {
66761
+ shell = loaded2.spawn(process.env.SHELL || "/bin/bash", ["-l"], {
66302
66762
  name: "xterm-256color",
66303
66763
  cols: 80,
66304
66764
  rows: 24,
@@ -66341,7 +66801,7 @@ var Live = class {
66341
66801
  // src/store.ts
66342
66802
  import { createHash, randomBytes as randomBytes3, timingSafeEqual } from "node:crypto";
66343
66803
  import { chmodSync as chmodSync2, mkdirSync, readFileSync as readFileSync2, renameSync, writeFileSync } from "node:fs";
66344
- import { join as join4 } from "node:path";
66804
+ import { join as join5 } from "node:path";
66345
66805
  var newToken = () => randomBytes3(32).toString("base64url");
66346
66806
  var digestOf = (token) => createHash("sha256").update(token).digest("hex");
66347
66807
  var sameToken = (token, digest) => timingSafeEqual(Buffer.from(digestOf(token), "hex"), Buffer.from(digest, "hex"));
@@ -66356,7 +66816,7 @@ var privateFolder = (dir) => {
66356
66816
  return dir;
66357
66817
  };
66358
66818
  function controlToken(data) {
66359
- const file2 = join4(data, "control-token");
66819
+ const file2 = join5(data, "control-token");
66360
66820
  try {
66361
66821
  return readFileSync2(file2, "utf8").trim();
66362
66822
  } catch (error62) {
@@ -66395,7 +66855,7 @@ var ProcessRuntime = class {
66395
66855
  let browser;
66396
66856
  let browserDown = false;
66397
66857
  if (spec.browser) {
66398
- const own3 = privateFolder(join5(folder, "browser"));
66858
+ const own3 = privateFolder(join6(folder, "browser"));
66399
66859
  browser = new Browser(
66400
66860
  this.#config,
66401
66861
  own3,
@@ -66414,7 +66874,12 @@ var ProcessRuntime = class {
66414
66874
  throw error62;
66415
66875
  }
66416
66876
  }
66417
- const live = new Live(exec, spec.workspace, spec.access === "terminal");
66877
+ let browserLive;
66878
+ if (browser) {
66879
+ browserLive = new BrowserLive(browser.endpoint);
66880
+ browser.gate = browserLive;
66881
+ }
66882
+ const live = new Live(exec, spec.workspace, spec.access === "terminal", browserLive);
66418
66883
  return {
66419
66884
  browserTools: browser?.tools ?? [],
66420
66885
  surfaces: await live.surfaces(),
@@ -66447,7 +66912,7 @@ async function serveInside(options) {
66447
66912
  ...options,
66448
66913
  ...options.access === "none" ? {} : { workspace: "/workspace" }
66449
66914
  },
66450
- privateFolder(join6(homedir(), ".agentcomputer")),
66915
+ privateFolder(join7(homedir(), ".agentcomputer")),
66451
66916
  {
66452
66917
  log: (line) => process.stdout.write(`${line}
66453
66918
  `),
@@ -66482,7 +66947,7 @@ async function serveInside(options) {
66482
66947
  socket.on("error", () => socket.destroy());
66483
66948
  const given = /^Bearer (\S+)$/.exec(request.headers.authorization ?? "")?.[1];
66484
66949
  const url3 = new URL(request.url ?? "/", "http://localhost");
66485
- const surface = /^\/live\/(commands|terminal)$/.exec(url3.pathname)?.[1];
66950
+ const surface = /^\/live\/(commands|terminal|browser)$/.exec(url3.pathname)?.[1];
66486
66951
  const mode = url3.searchParams.get("mode");
66487
66952
  if (!given || !sameToken(given, digest) || !surface || mode !== "watch" && mode !== "operate")
66488
66953
  return void socket.end("HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n");
@@ -66526,7 +66991,7 @@ var UPGRADE_HEADERS = [
66526
66991
  "sec-websocket-protocol"
66527
66992
  ];
66528
66993
  var nameOf = (id) => `agentcomputer-${id}`;
66529
- var sleep3 = (ms) => new Promise((done) => setTimeout(done, ms));
66994
+ var sleep4 = (ms) => new Promise((done) => setTimeout(done, ms));
66530
66995
  var ContainerRuntime = class {
66531
66996
  isolation = "container";
66532
66997
  #image;
@@ -66590,7 +67055,7 @@ var ContainerRuntime = class {
66590
67055
  }
66591
67056
  /** The token between the service and this container, which a restart has to find again. */
66592
67057
  #tokenIn(folder) {
66593
- const file2 = join7(folder, "inner-token");
67058
+ const file2 = join8(folder, "inner-token");
66594
67059
  try {
66595
67060
  return readFileSync3(file2, "utf8");
66596
67061
  } catch {
@@ -66663,7 +67128,7 @@ var ContainerRuntime = class {
66663
67128
  if (answer.ok) return await answer.json();
66664
67129
  } catch {
66665
67130
  }
66666
- await sleep3(100);
67131
+ await sleep4(100);
66667
67132
  }
66668
67133
  throw new Error("Its container didn't start. Its logs say why.");
66669
67134
  }
@@ -66720,7 +67185,7 @@ async function forward(url3, authorization, request, response) {
66720
67185
  }
66721
67186
 
66722
67187
  // src/handlers.ts
66723
- var VERSION2 = "0.0.4";
67188
+ var VERSION2 = "0.0.6";
66724
67189
  function createHandlers(computers) {
66725
67190
  return {
66726
67191
  getInfo: async () => ({ version: VERSION2, isolation: computers.isolation }),
@@ -67550,13 +68015,13 @@ var Computer = class _Computer {
67550
68015
  };
67551
68016
 
67552
68017
  // src/service.ts
67553
- import { readFileSync as readFileSync5, rmSync as rmSync2 } from "node:fs";
68018
+ import { readFileSync as readFileSync5, rmSync as rmSync3 } from "node:fs";
67554
68019
  import {
67555
68020
  createServer as createServer5,
67556
68021
  STATUS_CODES as STATUS_CODES3
67557
68022
  } from "node:http";
67558
68023
  import { createServer as createTlsServer } from "node:https";
67559
- import { join as join9 } from "node:path";
68024
+ import { join as join10 } from "node:path";
67560
68025
 
67561
68026
  // node_modules/@modelcontextprotocol/server/dist/chunk-vYduTEsO.mjs
67562
68027
  var __create4 = Object.create;
@@ -71017,7 +71482,7 @@ var REQUEST_STATE_ONLY_LEG_PACING_MS3 = 250;
71017
71482
  function inputRequiredRoundsExceededMessage3(method, maxRounds) {
71018
71483
  return `Multi-round-trip request '${method}' still required input after ${maxRounds} rounds (inputRequired.maxRounds)`;
71019
71484
  }
71020
- function sleep4(ms, signal) {
71485
+ function sleep5(ms, signal) {
71021
71486
  return new Promise((resolve6, reject) => {
71022
71487
  if (signal?.aborted) {
71023
71488
  reject(signal.reason instanceof SdkError3 ? signal.reason : new SdkError3(SdkErrorCode3.RequestTimeout, String(signal.reason)));
@@ -73199,10 +73664,10 @@ var require_util3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
73199
73664
  }
73200
73665
  exports.alwaysValidSchema = alwaysValidSchema;
73201
73666
  function checkUnknownRules(it, schema = it.schema) {
73202
- const { opts, self } = it;
73667
+ const { opts, self: self2 } = it;
73203
73668
  if (!opts.strictSchema) return;
73204
73669
  if (typeof schema === "boolean") return;
73205
- const rules = self.RULES.keywords;
73670
+ const rules = self2.RULES.keywords;
73206
73671
  for (const key in schema) if (!rules[key]) checkStrictMode(it, `unknown keyword: "${key}"`);
73207
73672
  }
73208
73673
  exports.checkUnknownRules = checkUnknownRules;
@@ -73534,8 +73999,8 @@ var require_rules3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
73534
73999
  var require_applicability3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
73535
74000
  Object.defineProperty(exports, "__esModule", { value: true });
73536
74001
  exports.shouldUseRule = exports.shouldUseGroup = exports.schemaHasRulesForType = void 0;
73537
- function schemaHasRulesForType({ schema, self }, type) {
73538
- const group = self.RULES.types[type];
74002
+ function schemaHasRulesForType({ schema, self: self2 }, type) {
74003
+ const group = self2.RULES.types[type];
73539
74004
  return group && group !== true && shouldUseGroup(schema, group);
73540
74005
  }
73541
74006
  exports.schemaHasRulesForType = schemaHasRulesForType;
@@ -73948,14 +74413,14 @@ var require_keyword3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
73948
74413
  return !schemaType.length || schemaType.some((st) => st === "array" ? Array.isArray(schema) : st === "object" ? schema && typeof schema == "object" && !Array.isArray(schema) : typeof schema == st || allowUndefined && typeof schema == "undefined");
73949
74414
  }
73950
74415
  exports.validSchemaType = validSchemaType;
73951
- function validateKeywordUsage({ schema, opts, self, errSchemaPath }, def, keyword) {
74416
+ function validateKeywordUsage({ schema, opts, self: self2, errSchemaPath }, def, keyword) {
73952
74417
  if (Array.isArray(def.keyword) ? !def.keyword.includes(keyword) : def.keyword !== keyword) throw new Error("ajv implementation error");
73953
74418
  const deps = def.dependencies;
73954
74419
  if (deps === null || deps === void 0 ? void 0 : deps.some((kwd) => !Object.prototype.hasOwnProperty.call(schema, kwd))) throw new Error(`parent schema must have dependencies of ${keyword}: ${deps.join(",")}`);
73955
74420
  if (def.validateSchema) {
73956
74421
  if (!def.validateSchema(schema[keyword])) {
73957
- const msg = `keyword "${keyword}" value is invalid at path "${errSchemaPath}": ` + self.errorsText(def.validateSchema.errors);
73958
- if (opts.validateSchema === "log") self.logger.error(msg);
74422
+ const msg = `keyword "${keyword}" value is invalid at path "${errSchemaPath}": ` + self2.errorsText(def.validateSchema.errors);
74423
+ if (opts.validateSchema === "log") self2.logger.error(msg);
73959
74424
  else throw new Error(msg);
73960
74425
  }
73961
74426
  }
@@ -74339,9 +74804,9 @@ var require_validate3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
74339
74804
  }
74340
74805
  (0, boolSchema_1.boolOrEmptySchema)(it, valid);
74341
74806
  }
74342
- function schemaCxtHasRules({ schema, self }) {
74807
+ function schemaCxtHasRules({ schema, self: self2 }) {
74343
74808
  if (typeof schema == "boolean") return !schema;
74344
- for (const key in schema) if (self.RULES.all[key]) return true;
74809
+ for (const key in schema) if (self2.RULES.all[key]) return true;
74345
74810
  return false;
74346
74811
  }
74347
74812
  function isSchemaObj(it) {
@@ -74366,8 +74831,8 @@ var require_validate3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
74366
74831
  schemaKeywords(it, types, !(0, dataType_1.coerceAndCheckDataType)(it, types), errsCount);
74367
74832
  }
74368
74833
  function checkRefsAndKeywords(it) {
74369
- const { schema, errSchemaPath, opts, self } = it;
74370
- if (schema.$ref && opts.ignoreKeywordsWithRef && (0, util_1.schemaHasRulesButRef)(schema, self.RULES)) self.logger.warn(`$ref: keywords ignored in schema at path "${errSchemaPath}"`);
74834
+ const { schema, errSchemaPath, opts, self: self2 } = it;
74835
+ if (schema.$ref && opts.ignoreKeywordsWithRef && (0, util_1.schemaHasRulesButRef)(schema, self2.RULES)) self2.logger.warn(`$ref: keywords ignored in schema at path "${errSchemaPath}"`);
74371
74836
  }
74372
74837
  function checkNoDefault(it) {
74373
74838
  const { schema, opts } = it;
@@ -74403,8 +74868,8 @@ var require_validate3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
74403
74868
  if (items instanceof codegen_1.Name) gen.assign((0, codegen_1._)`${evaluated}.items`, items);
74404
74869
  }
74405
74870
  function schemaKeywords(it, types, typeErrors, errsCount) {
74406
- const { gen, schema, data, allErrors, opts, self } = it;
74407
- const { RULES } = self;
74871
+ const { gen, schema, data, allErrors, opts, self: self2 } = it;
74872
+ const { RULES } = self2;
74408
74873
  if (schema.$ref && (opts.ignoreKeywordsWithRef || !(0, util_1.schemaHasRulesButRef)(schema, RULES))) {
74409
74874
  gen.block(() => keywordCode(it, "$ref", RULES.all.$ref.definition));
74410
74875
  return;
@@ -76426,10 +76891,10 @@ var require_ref3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
76426
76891
  schemaType: "string",
76427
76892
  code(cxt) {
76428
76893
  const { gen, schema: $ref, it } = cxt;
76429
- const { baseId, schemaEnv: env, validateName, opts, self } = it;
76894
+ const { baseId, schemaEnv: env, validateName, opts, self: self2 } = it;
76430
76895
  const { root } = env;
76431
76896
  if (($ref === "#" || $ref === "#/") && baseId === root.baseId) return callRootRef();
76432
- const schOrEnv = compile_1.resolveRef.call(self, root, baseId, $ref);
76897
+ const schOrEnv = compile_1.resolveRef.call(self2, root, baseId, $ref);
76433
76898
  if (schOrEnv === void 0) throw new ref_error_1.default(it.opts.uriResolver, baseId, $ref);
76434
76899
  if (schOrEnv instanceof compile_1.SchemaEnv) return callValidate(schOrEnv);
76435
76900
  return inlineRefSchema(schOrEnv);
@@ -77689,13 +78154,13 @@ var require_format$23 = /* @__PURE__ */ __commonJSMin3(((exports) => {
77689
78154
  },
77690
78155
  code(cxt, ruleType) {
77691
78156
  const { gen, data, $data, schema, schemaCode, it } = cxt;
77692
- const { opts, errSchemaPath, schemaEnv, self } = it;
78157
+ const { opts, errSchemaPath, schemaEnv, self: self2 } = it;
77693
78158
  if (!opts.validateFormats) return;
77694
78159
  if ($data) validate$DataFormat();
77695
78160
  else validateFormat();
77696
78161
  function validate$DataFormat() {
77697
78162
  const fmts = gen.scopeValue("formats", {
77698
- ref: self.formats,
78163
+ ref: self2.formats,
77699
78164
  code: opts.code.formats
77700
78165
  });
77701
78166
  const fDef = gen.const("fDef", (0, codegen_1._)`${fmts}[${schemaCode}]`);
@@ -77714,7 +78179,7 @@ var require_format$23 = /* @__PURE__ */ __commonJSMin3(((exports) => {
77714
78179
  }
77715
78180
  }
77716
78181
  function validateFormat() {
77717
- const formatDef = self.formats[schema];
78182
+ const formatDef = self2.formats[schema];
77718
78183
  if (!formatDef) {
77719
78184
  unknownFormat();
77720
78185
  return;
@@ -77724,7 +78189,7 @@ var require_format$23 = /* @__PURE__ */ __commonJSMin3(((exports) => {
77724
78189
  if (fmtType === ruleType) cxt.pass(validCondition());
77725
78190
  function unknownFormat() {
77726
78191
  if (opts.strictSchema === false) {
77727
- self.logger.warn(unknownMsg());
78192
+ self2.logger.warn(unknownMsg());
77728
78193
  return;
77729
78194
  }
77730
78195
  throw new Error(unknownMsg());
@@ -78150,9 +78615,9 @@ var require_dynamicAnchor3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
78150
78615
  }
78151
78616
  exports.dynamicAnchor = dynamicAnchor;
78152
78617
  function _getValidate(cxt) {
78153
- const { schemaEnv, schema, self } = cxt.it;
78618
+ const { schemaEnv, schema, self: self2 } = cxt.it;
78154
78619
  const { root, baseId, localRefs, meta: meta3 } = schemaEnv.root;
78155
- const { schemaId } = self.opts;
78620
+ const { schemaId } = self2.opts;
78156
78621
  const sch = new compile_1.SchemaEnv({
78157
78622
  schema,
78158
78623
  schemaId,
@@ -78161,7 +78626,7 @@ var require_dynamicAnchor3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
78161
78626
  localRefs,
78162
78627
  meta: meta3
78163
78628
  });
78164
- compile_1.compileSchema.call(self, sch);
78629
+ compile_1.compileSchema.call(self2, sch);
78165
78630
  return (0, ref_1.getValidate)(cxt, sch);
78166
78631
  }
78167
78632
  exports.default = def;
@@ -79461,14 +79926,14 @@ var require_limit3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
79461
79926
  error: error62,
79462
79927
  code(cxt) {
79463
79928
  const { gen, data, schemaCode, keyword, it } = cxt;
79464
- const { opts, self } = it;
79929
+ const { opts, self: self2 } = it;
79465
79930
  if (!opts.validateFormats) return;
79466
- const fCxt = new ajv_1.KeywordCxt(it, self.RULES.all.format.definition, "format");
79931
+ const fCxt = new ajv_1.KeywordCxt(it, self2.RULES.all.format.definition, "format");
79467
79932
  if (fCxt.$data) validate$DataFormat();
79468
79933
  else validateFormat();
79469
79934
  function validate$DataFormat() {
79470
79935
  const fmts = gen.scopeValue("formats", {
79471
- ref: self.formats,
79936
+ ref: self2.formats,
79472
79937
  code: opts.code.formats
79473
79938
  });
79474
79939
  const fmt = gen.const("fmt", (0, codegen_1._)`${fmts}[${fCxt.schemaCode}]`);
@@ -79476,7 +79941,7 @@ var require_limit3 = /* @__PURE__ */ __commonJSMin3(((exports) => {
79476
79941
  }
79477
79942
  function validateFormat() {
79478
79943
  const format = fCxt.schema;
79479
- const fmtDef = self.formats[format];
79944
+ const fmtDef = self2.formats[format];
79480
79945
  if (!fmtDef || fmtDef === true) return;
79481
79946
  if (typeof fmtDef != "object" || fmtDef instanceof RegExp || typeof fmtDef.compare != "function") throw new Error(`"${keyword}": format "${format}" does not define "compare" function`);
79482
79947
  const fmt = gen.scopeValue("formats", {
@@ -80014,7 +80479,7 @@ var LegacyInputRequiredShim2 = class {
80014
80479
  } finally {
80015
80480
  roundAbort.dispose();
80016
80481
  }
80017
- } else await sleep4(REQUEST_STATE_ONLY_LEG_PACING_MS3, outerSignal);
80482
+ } else await sleep5(REQUEST_STATE_ONLY_LEG_PACING_MS3, outerSignal);
80018
80483
  let ctxNext = {
80019
80484
  ...ctx,
80020
80485
  mcpReq: {
@@ -82105,10 +82570,10 @@ var isHttpWhitespace2 = (code) => code === 9 || code === 10 || code === 13 || co
82105
82570
  var normalizeHeaderValue2 = (value) => {
82106
82571
  if (!isHttpWhitespace2(value.charCodeAt(0)) && !isHttpWhitespace2(value.charCodeAt(value.length - 1))) return value;
82107
82572
  let start = 0;
82108
- let end = value.length;
82109
- while (start < end && isHttpWhitespace2(value.charCodeAt(start))) start++;
82110
- while (end > start && isHttpWhitespace2(value.charCodeAt(end - 1))) end--;
82111
- return value.slice(start, end);
82573
+ let end2 = value.length;
82574
+ while (start < end2 && isHttpWhitespace2(value.charCodeAt(start))) start++;
82575
+ while (end2 > start && isHttpWhitespace2(value.charCodeAt(end2 - 1))) end2--;
82576
+ return value.slice(start, end2);
82112
82577
  };
82113
82578
  var forbiddenHeaderValue2 = /[\0\r\n]/;
82114
82579
  var GlobalHeaders2 = globalThis.Headers;
@@ -83371,8 +83836,8 @@ var NodeStreamableHTTPServerTransport2 = class {
83371
83836
 
83372
83837
  // src/computers.ts
83373
83838
  import { randomBytes as randomBytes4 } from "node:crypto";
83374
- import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync4, rmSync, statSync as statSync3 } from "node:fs";
83375
- import { isAbsolute, join as join8, resolve as resolve4 } from "node:path";
83839
+ import { appendFileSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync4, rmSync as rmSync2, statSync as statSync3 } from "node:fs";
83840
+ import { isAbsolute, join as join9, resolve as resolve4 } from "node:path";
83376
83841
  var TOOLS = {
83377
83842
  read: ["read", "list", "search"],
83378
83843
  files: ["read", "list", "search", "edit"],
@@ -83394,7 +83859,7 @@ var Computers = class {
83394
83859
  this.#data = data;
83395
83860
  this.#base = base;
83396
83861
  this.#runtime = runtime;
83397
- this.#file = join8(data, "computers.json");
83862
+ this.#file = join9(data, "computers.json");
83398
83863
  if (existsSync2(this.#file))
83399
83864
  for (const entry of JSON.parse(readFileSync4(this.#file, "utf8")))
83400
83865
  this.#stored.set(entry.id, entry);
@@ -83449,7 +83914,7 @@ var Computers = class {
83449
83914
  ...timeout === void 0 ? {} : { endAt: expiry(timeout) }
83450
83915
  };
83451
83916
  if (!workspace && access !== "none") {
83452
- stored.workspace = join8(this.#folder(id), "workspace");
83917
+ stored.workspace = join9(this.#folder(id), "workspace");
83453
83918
  mkdirSync2(stored.workspace, { recursive: true, mode: 448 });
83454
83919
  }
83455
83920
  this.#stored.set(id, stored);
@@ -83459,7 +83924,7 @@ var Computers = class {
83459
83924
  await this.#halt(id);
83460
83925
  this.#stored.delete(id);
83461
83926
  await this.#runtime.remove(id);
83462
- rmSync(this.#folder(id), { recursive: true, force: true });
83927
+ rmSync2(this.#folder(id), { recursive: true, force: true });
83463
83928
  throw new ApiError(500, error62 instanceof Error ? error62.message : String(error62));
83464
83929
  }
83465
83930
  this.#save();
@@ -83527,7 +83992,7 @@ var Computers = class {
83527
83992
  await this.#runtime.remove(id);
83528
83993
  this.#stored.delete(id);
83529
83994
  this.#save();
83530
- rmSync(this.#folder(id), { recursive: true, force: true });
83995
+ rmSync2(this.#folder(id), { recursive: true, force: true });
83531
83996
  }
83532
83997
  logs(id) {
83533
83998
  this.#found(id);
@@ -83600,10 +84065,10 @@ var Computers = class {
83600
84065
  return stored;
83601
84066
  }
83602
84067
  #folder(id) {
83603
- return privateFolder(join8(this.#data, "computers", id));
84068
+ return privateFolder(join9(this.#data, "computers", id));
83604
84069
  }
83605
84070
  #logFile(id) {
83606
- return join8(this.#folder(id), "log");
84071
+ return join9(this.#folder(id), "log");
83607
84072
  }
83608
84073
  #log(id, line) {
83609
84074
  if (!this.#stored.has(id)) return;
@@ -83695,7 +84160,7 @@ var OPENAPI = {
83695
84160
  "openapi": "3.1.0",
83696
84161
  "info": {
83697
84162
  "title": "AgentComputer",
83698
- "version": "0.0.4",
84163
+ "version": "0.0.6",
83699
84164
  "description": "Computers for agents. This file is the source of truth: the HTTP API, the MCP control tools and the SDK are all generated from it. An operation with `x-mcp-tool` is also an MCP tool of that name.",
83700
84165
  "license": {
83701
84166
  "name": "Apache-2.0",
@@ -84356,9 +84821,10 @@ var OPENAPI = {
84356
84821
  "type": "string",
84357
84822
  "enum": [
84358
84823
  "commands",
84359
- "terminal"
84824
+ "terminal",
84825
+ "browser"
84360
84826
  ],
84361
- "description": "commands: the agent's commands as they run, read-only, in commands@1. terminal: a shell of your own in its workspace, as its user, in pty@1."
84827
+ "description": "commands: the agent's commands as they run, read-only, in commands@1. terminal: a shell of your own in its workspace, as its user, in pty@1. browser: its browser, in screencast@1: binary messages are JPEG frames of the page shown, text messages are ScreencastEvent one way and ScreencastInput the other. Operating it makes you the driver: the agent's browser calls wait up to 25 seconds while you are, then answer that a person has or had it. You stop being the driver when you send release, close the socket, or send nothing for 60 seconds."
84362
84828
  },
84363
84829
  "LiveMode": {
84364
84830
  "type": "string",
@@ -84444,6 +84910,400 @@ var OPENAPI = {
84444
84910
  }
84445
84911
  }
84446
84912
  },
84913
+ "ScreencastEvent": {
84914
+ "description": "What the service sends on a screencast@1 socket, as JSON text.",
84915
+ "oneOf": [
84916
+ {
84917
+ "type": "object",
84918
+ "description": "The open tabs, and which one the frames are of.",
84919
+ "required": [
84920
+ "type",
84921
+ "tabs",
84922
+ "shown"
84923
+ ],
84924
+ "properties": {
84925
+ "type": {
84926
+ "const": "tabs"
84927
+ },
84928
+ "tabs": {
84929
+ "type": "array",
84930
+ "items": {
84931
+ "type": "object",
84932
+ "required": [
84933
+ "id",
84934
+ "url",
84935
+ "title"
84936
+ ],
84937
+ "properties": {
84938
+ "id": {
84939
+ "type": "integer"
84940
+ },
84941
+ "url": {
84942
+ "type": "string"
84943
+ },
84944
+ "title": {
84945
+ "type": "string"
84946
+ }
84947
+ }
84948
+ }
84949
+ },
84950
+ "shown": {
84951
+ "type": [
84952
+ "integer",
84953
+ "null"
84954
+ ]
84955
+ }
84956
+ }
84957
+ },
84958
+ {
84959
+ "type": "object",
84960
+ "description": "The size of the page in the frames, in the coordinates input uses.",
84961
+ "required": [
84962
+ "type",
84963
+ "width",
84964
+ "height"
84965
+ ],
84966
+ "properties": {
84967
+ "type": {
84968
+ "const": "viewport"
84969
+ },
84970
+ "width": {
84971
+ "type": "integer"
84972
+ },
84973
+ "height": {
84974
+ "type": "integer"
84975
+ }
84976
+ }
84977
+ },
84978
+ {
84979
+ "type": "object",
84980
+ "description": "A dialog the page opened, which blocks it until it's answered, or that it closed.",
84981
+ "required": [
84982
+ "type",
84983
+ "open"
84984
+ ],
84985
+ "properties": {
84986
+ "type": {
84987
+ "const": "dialog"
84988
+ },
84989
+ "open": {
84990
+ "type": "boolean"
84991
+ },
84992
+ "kind": {
84993
+ "type": "string",
84994
+ "enum": [
84995
+ "alert",
84996
+ "confirm",
84997
+ "prompt",
84998
+ "beforeunload"
84999
+ ]
85000
+ },
85001
+ "message": {
85002
+ "type": "string"
85003
+ },
85004
+ "defaultValue": {
85005
+ "type": "string"
85006
+ }
85007
+ }
85008
+ },
85009
+ {
85010
+ "type": "object",
85011
+ "description": "The page asked for files, or stopped asking.",
85012
+ "required": [
85013
+ "type",
85014
+ "open"
85015
+ ],
85016
+ "properties": {
85017
+ "type": {
85018
+ "const": "file-chooser"
85019
+ },
85020
+ "open": {
85021
+ "type": "boolean"
85022
+ },
85023
+ "multiple": {
85024
+ "type": "boolean"
85025
+ }
85026
+ }
85027
+ },
85028
+ {
85029
+ "type": "object",
85030
+ "description": "A list to choose from, after a press on one: a page's own list isn't in the frames.",
85031
+ "required": [
85032
+ "type",
85033
+ "multiple",
85034
+ "options"
85035
+ ],
85036
+ "properties": {
85037
+ "type": {
85038
+ "const": "choice"
85039
+ },
85040
+ "multiple": {
85041
+ "type": "boolean"
85042
+ },
85043
+ "options": {
85044
+ "type": "array",
85045
+ "items": {
85046
+ "type": "object",
85047
+ "required": [
85048
+ "value",
85049
+ "label",
85050
+ "selected"
85051
+ ],
85052
+ "properties": {
85053
+ "value": {
85054
+ "type": "string"
85055
+ },
85056
+ "label": {
85057
+ "type": "string"
85058
+ },
85059
+ "selected": {
85060
+ "type": "boolean"
85061
+ }
85062
+ }
85063
+ }
85064
+ }
85065
+ }
85066
+ },
85067
+ {
85068
+ "type": "object",
85069
+ "description": "Who holds the browser, and whether the agent is waiting for it.",
85070
+ "required": [
85071
+ "type",
85072
+ "you",
85073
+ "held",
85074
+ "agentWaiting"
85075
+ ],
85076
+ "properties": {
85077
+ "type": {
85078
+ "const": "driver"
85079
+ },
85080
+ "you": {
85081
+ "type": "boolean"
85082
+ },
85083
+ "held": {
85084
+ "type": "boolean"
85085
+ },
85086
+ "agentWaiting": {
85087
+ "type": "boolean"
85088
+ }
85089
+ }
85090
+ }
85091
+ ]
85092
+ },
85093
+ "ScreencastInput": {
85094
+ "description": "What an operate socket sends on screencast@1, as JSON text. A watch socket's is dropped.",
85095
+ "oneOf": [
85096
+ {
85097
+ "type": "object",
85098
+ "required": [
85099
+ "type",
85100
+ "action",
85101
+ "x",
85102
+ "y"
85103
+ ],
85104
+ "properties": {
85105
+ "type": {
85106
+ "const": "mouse"
85107
+ },
85108
+ "action": {
85109
+ "type": "string",
85110
+ "enum": [
85111
+ "move",
85112
+ "down",
85113
+ "up",
85114
+ "wheel"
85115
+ ]
85116
+ },
85117
+ "x": {
85118
+ "type": "number"
85119
+ },
85120
+ "y": {
85121
+ "type": "number"
85122
+ },
85123
+ "button": {
85124
+ "type": "string",
85125
+ "enum": [
85126
+ "left",
85127
+ "right",
85128
+ "middle"
85129
+ ]
85130
+ },
85131
+ "deltaX": {
85132
+ "type": "number"
85133
+ },
85134
+ "deltaY": {
85135
+ "type": "number"
85136
+ }
85137
+ }
85138
+ },
85139
+ {
85140
+ "type": "object",
85141
+ "required": [
85142
+ "type",
85143
+ "action",
85144
+ "key"
85145
+ ],
85146
+ "properties": {
85147
+ "type": {
85148
+ "const": "key"
85149
+ },
85150
+ "action": {
85151
+ "type": "string",
85152
+ "enum": [
85153
+ "down",
85154
+ "up"
85155
+ ]
85156
+ },
85157
+ "key": {
85158
+ "type": "string",
85159
+ "description": "A key name",
85160
+ "as Playwright's keyboard takes it.": null
85161
+ }
85162
+ }
85163
+ },
85164
+ {
85165
+ "type": "object",
85166
+ "required": [
85167
+ "type",
85168
+ "text"
85169
+ ],
85170
+ "properties": {
85171
+ "type": {
85172
+ "const": "text"
85173
+ },
85174
+ "text": {
85175
+ "type": "string"
85176
+ }
85177
+ }
85178
+ },
85179
+ {
85180
+ "type": "object",
85181
+ "required": [
85182
+ "type",
85183
+ "accept"
85184
+ ],
85185
+ "properties": {
85186
+ "type": {
85187
+ "const": "dialog"
85188
+ },
85189
+ "accept": {
85190
+ "type": "boolean"
85191
+ },
85192
+ "text": {
85193
+ "type": "string"
85194
+ }
85195
+ }
85196
+ },
85197
+ {
85198
+ "type": "object",
85199
+ "description": "The files for an open file chooser. None cancels it.",
85200
+ "required": [
85201
+ "type",
85202
+ "files"
85203
+ ],
85204
+ "properties": {
85205
+ "type": {
85206
+ "const": "files"
85207
+ },
85208
+ "files": {
85209
+ "type": "array",
85210
+ "items": {
85211
+ "type": "object",
85212
+ "required": [
85213
+ "name",
85214
+ "data"
85215
+ ],
85216
+ "properties": {
85217
+ "name": {
85218
+ "type": "string"
85219
+ },
85220
+ "mimeType": {
85221
+ "type": "string"
85222
+ },
85223
+ "data": {
85224
+ "type": "string",
85225
+ "description": "Base64."
85226
+ }
85227
+ }
85228
+ }
85229
+ }
85230
+ }
85231
+ },
85232
+ {
85233
+ "type": "object",
85234
+ "required": [
85235
+ "type",
85236
+ "values"
85237
+ ],
85238
+ "properties": {
85239
+ "type": {
85240
+ "const": "choice"
85241
+ },
85242
+ "values": {
85243
+ "type": "array",
85244
+ "items": {
85245
+ "type": "string"
85246
+ }
85247
+ }
85248
+ }
85249
+ },
85250
+ {
85251
+ "type": "object",
85252
+ "required": [
85253
+ "type",
85254
+ "action"
85255
+ ],
85256
+ "properties": {
85257
+ "type": {
85258
+ "const": "tab"
85259
+ },
85260
+ "action": {
85261
+ "type": "string",
85262
+ "enum": [
85263
+ "show",
85264
+ "open",
85265
+ "close"
85266
+ ]
85267
+ },
85268
+ "id": {
85269
+ "type": "integer"
85270
+ },
85271
+ "url": {
85272
+ "type": "string"
85273
+ }
85274
+ }
85275
+ },
85276
+ {
85277
+ "type": "object",
85278
+ "required": [
85279
+ "type",
85280
+ "to"
85281
+ ],
85282
+ "properties": {
85283
+ "type": {
85284
+ "const": "navigate"
85285
+ },
85286
+ "to": {
85287
+ "type": "string",
85288
+ "description": "A URL",
85289
+ "or back": null,
85290
+ "forward or reload.": null
85291
+ }
85292
+ }
85293
+ },
85294
+ {
85295
+ "type": "object",
85296
+ "required": [
85297
+ "type"
85298
+ ],
85299
+ "properties": {
85300
+ "type": {
85301
+ "const": "release"
85302
+ }
85303
+ }
85304
+ }
85305
+ ]
85306
+ },
84447
85307
  "ComputerLogs": {
84448
85308
  "type": "object",
84449
85309
  "required": [
@@ -84983,9 +85843,10 @@ var OPERATIONS = [
84983
85843
  "type": "string",
84984
85844
  "enum": [
84985
85845
  "commands",
84986
- "terminal"
85846
+ "terminal",
85847
+ "browser"
84987
85848
  ],
84988
- "description": "commands: the agent's commands as they run, read-only, in commands@1. terminal: a shell of your own in its workspace, as its user, in pty@1."
85849
+ "description": "commands: the agent's commands as they run, read-only, in commands@1. terminal: a shell of your own in its workspace, as its user, in pty@1. browser: its browser, in screencast@1: binary messages are JPEG frames of the page shown, text messages are ScreencastEvent one way and ScreencastInput the other. Operating it makes you the driver: the agent's browser calls wait up to 25 seconds while you are, then answer that a person has or had it. You stop being the driver when you send release, close the socket, or send nothing for 60 seconds."
84989
85850
  },
84990
85851
  "protocol": {
84991
85852
  "type": "string"
@@ -85522,9 +86383,10 @@ var OPERATIONS = [
85522
86383
  "type": "string",
85523
86384
  "enum": [
85524
86385
  "commands",
85525
- "terminal"
86386
+ "terminal",
86387
+ "browser"
85526
86388
  ],
85527
- "description": "commands: the agent's commands as they run, read-only, in commands@1. terminal: a shell of your own in its workspace, as its user, in pty@1."
86389
+ "description": "commands: the agent's commands as they run, read-only, in commands@1. terminal: a shell of your own in its workspace, as its user, in pty@1. browser: its browser, in screencast@1: binary messages are JPEG frames of the page shown, text messages are ScreencastEvent one way and ScreencastInput the other. Operating it makes you the driver: the agent's browser calls wait up to 25 seconds while you are, then answer that a person has or had it. You stop being the driver when you send release, close the socket, or send nothing for 60 seconds."
85528
86390
  },
85529
86391
  "mode": {
85530
86392
  "allOf": [
@@ -85567,9 +86429,10 @@ var OPERATIONS = [
85567
86429
  "type": "string",
85568
86430
  "enum": [
85569
86431
  "commands",
85570
- "terminal"
86432
+ "terminal",
86433
+ "browser"
85571
86434
  ],
85572
- "description": "commands: the agent's commands as they run, read-only, in commands@1. terminal: a shell of your own in its workspace, as its user, in pty@1."
86435
+ "description": "commands: the agent's commands as they run, read-only, in commands@1. terminal: a shell of your own in its workspace, as its user, in pty@1. browser: its browser, in screencast@1: binary messages are JPEG frames of the page shown, text messages are ScreencastEvent one way and ScreencastInput the other. Operating it makes you the driver: the agent's browser calls wait up to 25 seconds while you are, then answer that a person has or had it. You stop being the driver when you send release, close the socket, or send nothing for 60 seconds."
85573
86436
  },
85574
86437
  "mode": {
85575
86438
  "type": "string",
@@ -85789,7 +86652,7 @@ ${JSON.stringify({ code: status, message })}
85789
86652
  const scheme = options.tls ? "https" : "http";
85790
86653
  base = options.publicUrl?.replace(/\/+$/, "") ?? `${scheme}://${bound.family === "IPv6" ? `[${bound.address}]` : bound.address}:${bound.port}`;
85791
86654
  await computers.resume();
85792
- const record3 = join9(data, "server.json");
86655
+ const record3 = join10(data, "server.json");
85793
86656
  writePrivate(
85794
86657
  record3,
85795
86658
  JSON.stringify({ url: base, pid: process.pid, isolation: options.runtime.isolation })
@@ -85804,7 +86667,7 @@ ${JSON.stringify({ code: status, message })}
85804
86667
  process.stderr.write(`${String(error62)}
85805
86668
  `);
85806
86669
  });
85807
- rmSync2(record3, { force: true });
86670
+ rmSync3(record3, { force: true });
85808
86671
  process.exit(0);
85809
86672
  };
85810
86673
  for (const signal of ["SIGINT", "SIGTERM"]) process.once(signal, () => void stop());
@@ -85842,13 +86705,13 @@ var UsageError = class extends Error {
85842
86705
  function dataFolder(given) {
85843
86706
  const xdg = process.env.XDG_DATA_HOME;
85844
86707
  return resolve5(
85845
- given ?? process.env.AGENTCOMPUTER_DATA ?? (xdg && isAbsolute2(xdg) ? join10(xdg, "agentcomputer") : join10(homedir2(), ".local", "share", "agentcomputer"))
86708
+ given ?? process.env.AGENTCOMPUTER_DATA ?? (xdg && isAbsolute2(xdg) ? join11(xdg, "agentcomputer") : join11(homedir2(), ".local", "share", "agentcomputer"))
85846
86709
  );
85847
86710
  }
85848
86711
  function connectionTo(data) {
85849
86712
  try {
85850
- const { url: url3 } = JSON.parse(readFileSync6(join10(data, "server.json"), "utf8"));
85851
- return { apiUrl: url3, apiKey: readFileSync6(join10(data, "control-token"), "utf8").trim() };
86713
+ const { url: url3 } = JSON.parse(readFileSync6(join11(data, "server.json"), "utf8"));
86714
+ return { apiUrl: url3, apiKey: readFileSync6(join11(data, "control-token"), "utf8").trim() };
85852
86715
  } catch {
85853
86716
  throw new Error(
85854
86717
  `No service is running with its data in ${data}. Start one: agentcomputer serve`
@@ -85873,7 +86736,10 @@ async function main() {
85873
86736
  browser: { type: "boolean" },
85874
86737
  "browser-name": { type: "string" },
85875
86738
  "browser-path": { type: "string" },
85876
- "playwright-cli": { type: "string" },
86739
+ profile: { type: "string" },
86740
+ channel: { type: "string" },
86741
+ executable: { type: "string" },
86742
+ "no-sandbox": { type: "boolean" },
85877
86743
  access: { type: "string" },
85878
86744
  workspace: { type: "string" },
85879
86745
  name: { type: "string" },
@@ -85908,12 +86774,18 @@ async function main() {
85908
86774
  publicUrl: values["public-url"],
85909
86775
  allowOrigins: values["allow-origin"],
85910
86776
  runtime: isolation === "container" ? new ContainerRuntime(values.image ?? `${IMAGE}:${VERSION2}`) : new ProcessRuntime({
85911
- cli: values["playwright-cli"],
85912
86777
  browser: values["browser-name"],
85913
86778
  path: values["browser-path"]
85914
86779
  })
85915
86780
  });
85916
86781
  }
86782
+ if (command === "browser-host")
86783
+ return hostBrowser({
86784
+ profile: values.profile ?? "",
86785
+ channel: values.channel,
86786
+ executable: values.executable,
86787
+ sandbox: values["no-sandbox"] ? false : void 0
86788
+ });
85917
86789
  if (command === "inside")
85918
86790
  return serveInside({
85919
86791
  access: values.access,