local-commander-agent 0.3.45 → 0.3.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/runtime/agent.mjs CHANGED
@@ -2125,7 +2125,7 @@ var require_extension = __commonJS({
2125
2125
  if (dest[name2] === void 0) dest[name2] = [elem];
2126
2126
  else dest[name2].push(elem);
2127
2127
  }
2128
- function parse3(header) {
2128
+ function parse4(header) {
2129
2129
  const offers = /* @__PURE__ */ Object.create(null);
2130
2130
  let params = /* @__PURE__ */ Object.create(null);
2131
2131
  let mustUnescape = false;
@@ -2265,7 +2265,7 @@ var require_extension = __commonJS({
2265
2265
  }).join(", ");
2266
2266
  }).join(", ");
2267
2267
  }
2268
- module.exports = { format, parse: parse3 };
2268
+ module.exports = { format, parse: parse4 };
2269
2269
  }
2270
2270
  });
2271
2271
 
@@ -2276,9 +2276,9 @@ var require_websocket = __commonJS({
2276
2276
  var EventEmitter = __require("events");
2277
2277
  var https2 = __require("https");
2278
2278
  var http2 = __require("http");
2279
- var net2 = __require("net");
2279
+ var net3 = __require("net");
2280
2280
  var tls2 = __require("tls");
2281
- var { randomBytes: randomBytes10, createHash: createHash21 } = __require("crypto");
2281
+ var { randomBytes: randomBytes11, createHash: createHash21 } = __require("crypto");
2282
2282
  var { Duplex, Readable } = __require("stream");
2283
2283
  var { URL: URL2 } = __require("url");
2284
2284
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -2299,7 +2299,7 @@ var require_websocket = __commonJS({
2299
2299
  var {
2300
2300
  EventTarget: { addEventListener, removeEventListener }
2301
2301
  } = require_event_target();
2302
- var { format, parse: parse3 } = require_extension();
2302
+ var { format, parse: parse4 } = require_extension();
2303
2303
  var { toBuffer } = require_buffer_util();
2304
2304
  var kAborted = /* @__PURE__ */ Symbol("kAborted");
2305
2305
  var protocolVersions = [8, 13];
@@ -2829,7 +2829,7 @@ var require_websocket = __commonJS({
2829
2829
  }
2830
2830
  }
2831
2831
  const defaultPort = isSecure ? 443 : 80;
2832
- const key = randomBytes10(16).toString("base64");
2832
+ const key = randomBytes11(16).toString("base64");
2833
2833
  const request = isSecure ? https2.request : http2.request;
2834
2834
  const protocolSet = /* @__PURE__ */ new Set();
2835
2835
  let perMessageDeflate;
@@ -2989,7 +2989,7 @@ var require_websocket = __commonJS({
2989
2989
  }
2990
2990
  let extensions;
2991
2991
  try {
2992
- extensions = parse3(secWebSocketExtensions);
2992
+ extensions = parse4(secWebSocketExtensions);
2993
2993
  } catch (err) {
2994
2994
  const message2 = "Invalid Sec-WebSocket-Extensions header";
2995
2995
  abortHandshake(websocket, socket, message2);
@@ -3033,12 +3033,12 @@ var require_websocket = __commonJS({
3033
3033
  }
3034
3034
  function netConnect2(options) {
3035
3035
  options.path = options.socketPath;
3036
- return net2.connect(options);
3036
+ return net3.connect(options);
3037
3037
  }
3038
3038
  function tlsConnect(options) {
3039
3039
  options.path = void 0;
3040
3040
  if (!options.servername && options.servername !== "") {
3041
- options.servername = net2.isIP(options.host) ? "" : options.host;
3041
+ options.servername = net3.isIP(options.host) ? "" : options.host;
3042
3042
  }
3043
3043
  return tls2.connect(options);
3044
3044
  }
@@ -3281,7 +3281,7 @@ var require_subprotocol = __commonJS({
3281
3281
  "../../node_modules/ws/lib/subprotocol.js"(exports, module) {
3282
3282
  "use strict";
3283
3283
  var { tokenChars } = require_validation();
3284
- function parse3(header) {
3284
+ function parse4(header) {
3285
3285
  const protocols = /* @__PURE__ */ new Set();
3286
3286
  let start = -1;
3287
3287
  let end = -1;
@@ -3317,7 +3317,7 @@ var require_subprotocol = __commonJS({
3317
3317
  protocols.add(protocol2);
3318
3318
  return protocols;
3319
3319
  }
3320
- module.exports = { parse: parse3 };
3320
+ module.exports = { parse: parse4 };
3321
3321
  }
3322
3322
  });
3323
3323
 
@@ -4541,10 +4541,10 @@ function mergeDefs(...defs) {
4541
4541
  function cloneDef(schema) {
4542
4542
  return mergeDefs(schema._zod.def);
4543
4543
  }
4544
- function getElementAtPath(obj, path29) {
4545
- if (!path29)
4544
+ function getElementAtPath(obj, path30) {
4545
+ if (!path30)
4546
4546
  return obj;
4547
- return path29.reduce((acc, key) => acc?.[key], obj);
4547
+ return path30.reduce((acc, key) => acc?.[key], obj);
4548
4548
  }
4549
4549
  function promiseAllObject(promisesObj) {
4550
4550
  const keys = Object.keys(promisesObj);
@@ -4884,11 +4884,11 @@ function explicitlyAborted(x, startIndex = 0) {
4884
4884
  }
4885
4885
  return false;
4886
4886
  }
4887
- function prefixIssues(path29, issues) {
4887
+ function prefixIssues(path30, issues) {
4888
4888
  return issues.map((iss) => {
4889
4889
  var _a3;
4890
4890
  (_a3 = iss).path ?? (_a3.path = []);
4891
- iss.path.unshift(path29);
4891
+ iss.path.unshift(path30);
4892
4892
  return iss;
4893
4893
  });
4894
4894
  }
@@ -5338,16 +5338,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) {
5338
5338
  }
5339
5339
  function formatError(error62, mapper = (issue2) => issue2.message) {
5340
5340
  const fieldErrors = { _errors: [] };
5341
- const processError = (error63, path29 = []) => {
5341
+ const processError = (error63, path30 = []) => {
5342
5342
  for (const issue2 of error63.issues) {
5343
5343
  if (issue2.code === "invalid_union" && issue2.errors.length) {
5344
- issue2.errors.map((issues) => processError({ issues }, [...path29, ...issue2.path]));
5344
+ issue2.errors.map((issues) => processError({ issues }, [...path30, ...issue2.path]));
5345
5345
  } else if (issue2.code === "invalid_key") {
5346
- processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
5346
+ processError({ issues: issue2.issues }, [...path30, ...issue2.path]);
5347
5347
  } else if (issue2.code === "invalid_element") {
5348
- processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
5348
+ processError({ issues: issue2.issues }, [...path30, ...issue2.path]);
5349
5349
  } else {
5350
- const fullpath = [...path29, ...issue2.path];
5350
+ const fullpath = [...path30, ...issue2.path];
5351
5351
  if (fullpath.length === 0) {
5352
5352
  fieldErrors._errors.push(mapper(issue2));
5353
5353
  } else {
@@ -5386,17 +5386,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) {
5386
5386
  }
5387
5387
  function treeifyError(error62, mapper = (issue2) => issue2.message) {
5388
5388
  const result2 = { errors: [] };
5389
- const processError = (error63, path29 = []) => {
5389
+ const processError = (error63, path30 = []) => {
5390
5390
  var _a3;
5391
5391
  for (const issue2 of error63.issues) {
5392
5392
  if (issue2.code === "invalid_union" && issue2.errors.length) {
5393
- issue2.errors.map((issues) => processError({ issues }, [...path29, ...issue2.path]));
5393
+ issue2.errors.map((issues) => processError({ issues }, [...path30, ...issue2.path]));
5394
5394
  } else if (issue2.code === "invalid_key") {
5395
- processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
5395
+ processError({ issues: issue2.issues }, [...path30, ...issue2.path]);
5396
5396
  } else if (issue2.code === "invalid_element") {
5397
- processError({ issues: issue2.issues }, [...path29, ...issue2.path]);
5397
+ processError({ issues: issue2.issues }, [...path30, ...issue2.path]);
5398
5398
  } else {
5399
- const fullpath = [...path29, ...issue2.path];
5399
+ const fullpath = [...path30, ...issue2.path];
5400
5400
  if (fullpath.length === 0) {
5401
5401
  result2.errors.push(mapper(issue2));
5402
5402
  continue;
@@ -5435,8 +5435,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) {
5435
5435
  }
5436
5436
  function toDotPath(_path) {
5437
5437
  const segs = [];
5438
- const path29 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
5439
- for (const seg of path29) {
5438
+ const path30 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
5439
+ for (const seg of path30) {
5440
5440
  if (typeof seg === "number")
5441
5441
  segs.push(`[${seg}]`);
5442
5442
  else if (typeof seg === "symbol")
@@ -5570,18 +5570,18 @@ var validateAsync = async (schema, value, _ctx) => {
5570
5570
  return result2.issues.length === 0;
5571
5571
  };
5572
5572
  var _encode = (_Err) => {
5573
- const parse3 = _parse(_Err);
5573
+ const parse4 = _parse(_Err);
5574
5574
  const fn = (schema, value, _ctx, _params) => {
5575
5575
  const ctx = _ctx ? { ..._ctx, direction: "backward" } : { direction: "backward" };
5576
- return parse3(schema, value, ctx, finalizeParams(fn, _params));
5576
+ return parse4(schema, value, ctx, finalizeParams(fn, _params));
5577
5577
  };
5578
5578
  return fn;
5579
5579
  };
5580
5580
  var encode = /* @__PURE__ */ _encode($ZodRealError);
5581
5581
  var _decode = (_Err) => {
5582
- const parse3 = _parse(_Err);
5582
+ const parse4 = _parse(_Err);
5583
5583
  const fn = (schema, value, _ctx, _params) => {
5584
- return parse3(schema, value, _ctx, finalizeParams(fn, _params));
5584
+ return parse4(schema, value, _ctx, finalizeParams(fn, _params));
5585
5585
  };
5586
5586
  return fn;
5587
5587
  };
@@ -22538,13 +22538,13 @@ function resolveRef(ref, ctx) {
22538
22538
  if (!ref.startsWith("#")) {
22539
22539
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
22540
22540
  }
22541
- const path29 = ref.slice(1).split("/").filter(Boolean);
22542
- if (path29.length === 0) {
22541
+ const path30 = ref.slice(1).split("/").filter(Boolean);
22542
+ if (path30.length === 0) {
22543
22543
  return ctx.rootSchema;
22544
22544
  }
22545
22545
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
22546
- if (path29[0] === defsKey) {
22547
- const key = path29[1] === void 0 ? void 0 : decodeJSONPointerSegment(path29[1]);
22546
+ if (path30[0] === defsKey) {
22547
+ const key = path30[1] === void 0 ? void 0 : decodeJSONPointerSegment(path30[1]);
22548
22548
  if (!key || !ctx.defs[key]) {
22549
22549
  throw new Error(`Reference not found: ${ref}`);
22550
22550
  }
@@ -23179,7 +23179,7 @@ function visit(schema, fnOrHandlers) {
23179
23179
  return h ? h(node2, rewritten) : node2;
23180
23180
  };
23181
23181
  const cache2 = /* @__PURE__ */ new Map();
23182
- function run(s) {
23182
+ function run2(s) {
23183
23183
  const cached2 = cache2.get(s);
23184
23184
  if (cached2 === RESOLVING) {
23185
23185
  return new $ZodLazy({
@@ -23205,21 +23205,21 @@ function visit(schema, fnOrHandlers) {
23205
23205
  let changed = false;
23206
23206
  const newShape = {};
23207
23207
  for (const k of keys) {
23208
- const mapped = run(oldShape[k]);
23208
+ const mapped = run2(oldShape[k]);
23209
23209
  if (mapped !== oldShape[k])
23210
23210
  changed = true;
23211
23211
  newShape[k] = mapped;
23212
23212
  }
23213
23213
  let newCatchall = def.catchall;
23214
23214
  if (def.catchall) {
23215
- newCatchall = run(def.catchall);
23215
+ newCatchall = run2(def.catchall);
23216
23216
  if (newCatchall !== def.catchall)
23217
23217
  changed = true;
23218
23218
  }
23219
23219
  return changed ? clone(s, { ...def, shape: newShape, catchall: newCatchall }) : s;
23220
23220
  }
23221
23221
  case "array": {
23222
- const mapped = run(def.element);
23222
+ const mapped = run2(def.element);
23223
23223
  return mapped === def.element ? s : clone(s, { ...def, element: mapped });
23224
23224
  }
23225
23225
  case "tuple": {
@@ -23227,14 +23227,14 @@ function visit(schema, fnOrHandlers) {
23227
23227
  let changed = false;
23228
23228
  const newItems = [];
23229
23229
  for (const item of oldItems) {
23230
- const mapped = run(item);
23230
+ const mapped = run2(item);
23231
23231
  if (mapped !== item)
23232
23232
  changed = true;
23233
23233
  newItems.push(mapped);
23234
23234
  }
23235
23235
  let newRest = def.rest;
23236
23236
  if (def.rest) {
23237
- newRest = run(def.rest);
23237
+ newRest = run2(def.rest);
23238
23238
  if (newRest !== def.rest)
23239
23239
  changed = true;
23240
23240
  }
@@ -23242,12 +23242,12 @@ function visit(schema, fnOrHandlers) {
23242
23242
  }
23243
23243
  case "record":
23244
23244
  case "map": {
23245
- const newKey = run(def.keyType);
23246
- const newVal = run(def.valueType);
23245
+ const newKey = run2(def.keyType);
23246
+ const newVal = run2(def.valueType);
23247
23247
  return newKey === def.keyType && newVal === def.valueType ? s : clone(s, { ...def, keyType: newKey, valueType: newVal });
23248
23248
  }
23249
23249
  case "set": {
23250
- const newVal = run(def.valueType);
23250
+ const newVal = run2(def.valueType);
23251
23251
  return newVal === def.valueType ? s : clone(s, { ...def, valueType: newVal });
23252
23252
  }
23253
23253
  case "union": {
@@ -23255,7 +23255,7 @@ function visit(schema, fnOrHandlers) {
23255
23255
  let changed = false;
23256
23256
  const newOptions = [];
23257
23257
  for (const opt of oldOptions) {
23258
- const mapped = run(opt);
23258
+ const mapped = run2(opt);
23259
23259
  if (mapped !== opt)
23260
23260
  changed = true;
23261
23261
  newOptions.push(mapped);
@@ -23263,8 +23263,8 @@ function visit(schema, fnOrHandlers) {
23263
23263
  return changed ? clone(s, { ...def, options: newOptions }) : s;
23264
23264
  }
23265
23265
  case "intersection": {
23266
- const newLeft = run(def.left);
23267
- const newRight = run(def.right);
23266
+ const newLeft = run2(def.left);
23267
+ const newRight = run2(def.right);
23268
23268
  return newLeft === def.left && newRight === def.right ? s : clone(s, { ...def, left: newLeft, right: newRight });
23269
23269
  }
23270
23270
  case "optional":
@@ -23276,23 +23276,23 @@ function visit(schema, fnOrHandlers) {
23276
23276
  case "nonoptional":
23277
23277
  case "promise":
23278
23278
  case "success": {
23279
- const newInner = run(def.innerType);
23279
+ const newInner = run2(def.innerType);
23280
23280
  return newInner === def.innerType ? s : clone(s, { ...def, innerType: newInner });
23281
23281
  }
23282
23282
  case "pipe": {
23283
- const newIn = run(def.in);
23284
- const newOut = run(def.out);
23283
+ const newIn = run2(def.in);
23284
+ const newOut = run2(def.out);
23285
23285
  return newIn === def.in && newOut === def.out ? s : clone(s, { ...def, in: newIn, out: newOut });
23286
23286
  }
23287
23287
  case "function": {
23288
- const newInput = run(def.input);
23289
- const newOutput = run(def.output);
23288
+ const newInput = run2(def.input);
23289
+ const newOutput = run2(def.output);
23290
23290
  return newInput === def.input && newOutput === def.output ? s : clone(s, { ...def, input: newInput, output: newOutput });
23291
23291
  }
23292
23292
  case "lazy": {
23293
23293
  const original = def.getter;
23294
23294
  const { _cachedInner, ...rest } = def;
23295
- return clone(s, { ...rest, getter: () => run(original()) });
23295
+ return clone(s, { ...rest, getter: () => run2(original()) });
23296
23296
  }
23297
23297
  // A leaf by choice: `parts` are regex fragments, not data positions.
23298
23298
  case "template_literal":
@@ -23323,7 +23323,7 @@ function visit(schema, fnOrHandlers) {
23323
23323
  }
23324
23324
  }
23325
23325
  }
23326
- return run(schema);
23326
+ return run2(schema);
23327
23327
  }
23328
23328
 
23329
23329
  // ../../node_modules/zod/v4/classic/deep-partial.js
@@ -25164,8 +25164,8 @@ async function openNetworkPanel(binaryDirectory, identity) {
25164
25164
  }
25165
25165
 
25166
25166
  // agent/src/main.ts
25167
- import path28 from "node:path";
25168
- import os7 from "node:os";
25167
+ import path29 from "node:path";
25168
+ import os8 from "node:os";
25169
25169
 
25170
25170
  // agent/src/posix-store.ts
25171
25171
  import { constants } from "node:fs";
@@ -25584,7 +25584,7 @@ async function acquirePosixJournalGuard(directory, helper) {
25584
25584
  }
25585
25585
 
25586
25586
  // agent/src/main.ts
25587
- import { mkdir as mkdir14, open as open13, readFile as readFile11, realpath as realpath10, rm as rm9 } from "node:fs/promises";
25587
+ import { mkdir as mkdir14, open as open13, readFile as readFile12, realpath as realpath10, rm as rm10 } from "node:fs/promises";
25588
25588
  import { fileURLToPath } from "node:url";
25589
25589
 
25590
25590
  // packages/operations/src/crypto.ts
@@ -25721,13 +25721,13 @@ var exec2 = promisify2(execFile2);
25721
25721
  async function darwinSupervisorLiveness(helper, pids, records = []) {
25722
25722
  if (process.platform !== "darwin" || !process.getuid?.() || process.getuid() !== process.geteuid?.()) return null;
25723
25723
  const remaining = new Set(pids), uid = process.getuid(), deadline = Date.now() + 1e4, env = buildChildEnvironment(process.env);
25724
- const run = (file2, args) => exec2(
25724
+ const run2 = (file2, args) => exec2(
25725
25725
  file2,
25726
25726
  args,
25727
25727
  { env, timeout: Math.max(1, Math.min(7e3, deadline - Date.now())), maxBuffer: 8192, encoding: "utf8", windowsHide: true }
25728
25728
  );
25729
25729
  try {
25730
- const boot = (await run("/usr/sbin/sysctl", ["-n", "kern.bootsessionuuid"])).stdout.trim();
25730
+ const boot = (await run2("/usr/sbin/sysctl", ["-n", "kern.bootsessionuuid"])).stdout.trim();
25731
25731
  if (!bootSession.test(boot)) return null;
25732
25732
  for (const pid of remaining) {
25733
25733
  if (Date.now() >= deadline) break;
@@ -25736,9 +25736,9 @@ async function darwinSupervisorLiveness(helper, pids, records = []) {
25736
25736
  const proof2 = matches2[0].containment;
25737
25737
  if (!validDarwinContainment(proof2) || proof2.uid !== uid || proof2.bootSession !== boot) continue;
25738
25738
  try {
25739
- await run(helper, ["--reap", proof2.coalition]);
25740
- if ((await run(helper, ["--count", proof2.coalition])).stdout.trim() !== "0") continue;
25741
- await run("/bin/launchctl", ["bootout", "gui/" + uid + "/" + proof2.label]).catch(() => {
25739
+ await run2(helper, ["--reap", proof2.coalition]);
25740
+ if ((await run2(helper, ["--count", proof2.coalition])).stdout.trim() !== "0") continue;
25741
+ await run2("/bin/launchctl", ["bootout", "gui/" + uid + "/" + proof2.label]).catch(() => {
25742
25742
  });
25743
25743
  remaining.delete(pid);
25744
25744
  } catch {
@@ -26445,10 +26445,12 @@ var ToolCallSchema = external_exports.discriminatedUnion("name", [
26445
26445
  external_exports.object({ name: external_exports.literal("git_log"), args: external_exports.object({ path: path5.optional(), limit: external_exports.number().int().min(1).max(50).default(15) }).strict() }).strict(),
26446
26446
  external_exports.object({ name: external_exports.literal("project_snapshot"), args: external_exports.object({ path: path5.optional(), startup: external_exports.boolean().optional(), taskId: external_exports.string().regex(/^[A-Za-z0-9_-]{1,100}$/).optional() }).strict() }).strict(),
26447
26447
  external_exports.object({ name: external_exports.literal("command_run"), args: external_exports.object({ command: external_exports.string().min(1).max(260).refine((v) => !/[\r\n\0]/.test(v)), args: external_exports.array(external_exports.string().max(8192).refine((v) => !v.includes("\0"))).max(128).default([]), cwd: path5.optional(), timeoutMs: external_exports.number().int().min(100).max(864e5).default(6e4) }).strict() }).strict(),
26448
+ // Still image of the device's primary display; the agent requires an owner Full Access workspace.
26449
+ external_exports.object({ name: external_exports.literal("take_screenshot"), args: external_exports.object({}).strict() }).strict(),
26448
26450
  external_exports.object({ name: external_exports.literal("localhost_request"), args: external_exports.object({ url: external_exports.string().url().max(2048), method: external_exports.enum(["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"]).default("GET"), headers: external_exports.record(external_exports.string().max(128), external_exports.string().max(2048)).optional(), body: external_exports.string().max(6e4).optional() }).strict() }).strict()
26449
26451
  ]);
26450
26452
  function scopeForTool(call) {
26451
- if (call.name === "command_run") return "commands:execute";
26453
+ if (call.name === "command_run" || call.name === "take_screenshot") return "commands:execute";
26452
26454
  if (call.name === "localhost_request") return "localhost:access";
26453
26455
  return call.name === "fs_write" || call.name === "fs_replace" ? "files:write" : "files:read";
26454
26456
  }
@@ -26464,10 +26466,12 @@ var ServerFrameSchema = external_exports.discriminatedUnion("type", [
26464
26466
  external_exports.object({ type: external_exports.literal("workspace_ack"), version: external_exports.literal(1), requestId: uuid11, workspaceGrantId: uuid11, accepted: external_exports.boolean(), code: external_exports.string().max(64).optional() }).strict(),
26465
26467
  external_exports.object({ type: external_exports.literal("revoke"), version: external_exports.literal(1), reason: external_exports.enum(["device_revoked", "account_revoked", "server_shutdown", "connection_replaced"]) }).strict()
26466
26468
  ]);
26469
+ var WORKSPACE_ACCESS_MODE_CAPABILITY = "workspaceAccessModeV1";
26470
+ var WorkspaceAccessModeSchema = external_exports.enum(["full", "scoped"]);
26467
26471
  var ClientFrameSchema = external_exports.discriminatedUnion("type", [
26468
26472
  external_exports.object({ type: external_exports.literal("ready"), version: external_exports.literal(1), safeSlots: external_exports.number().int().min(1).max(128), platform: external_exports.literal("win32"), agentVersion: external_exports.string().regex(/^[A-Za-z0-9._+-]{1,64}$/), supervisor: external_exports.boolean() }).strict(),
26469
26473
  external_exports.object({ type: external_exports.literal("heartbeat"), version: external_exports.literal(1), connectionEpoch: epoch2 }).strict(),
26470
- external_exports.object({ type: external_exports.literal("workspace_grant"), version: external_exports.literal(1), requestId: uuid11, workspaceGrantId: uuid11, rootHash: hash3, displayName: external_exports.string().min(1).max(120), policyVersion: external_exports.number().int().min(1).max(2147483647) }).strict(),
26474
+ external_exports.object({ type: external_exports.literal("workspace_grant"), version: external_exports.literal(1), requestId: uuid11, workspaceGrantId: uuid11, rootHash: hash3, displayName: external_exports.string().min(1).max(120), policyVersion: external_exports.number().int().min(1).max(2147483647), accessMode: WorkspaceAccessModeSchema.optional() }).strict(),
26471
26475
  external_exports.object({ type: external_exports.literal("workspace_revoke"), version: external_exports.literal(1), requestId: uuid11, workspaceGrantId: uuid11 }).strict(),
26472
26476
  external_exports.object({ type: external_exports.literal("prepared"), version: external_exports.literal(1), binding: ExecutionBindingSchema }).strict(),
26473
26477
  external_exports.object({ type: external_exports.literal("accepted"), version: external_exports.literal(1), binding: ExecutionBindingSchema }).strict(),
@@ -26552,6 +26556,7 @@ function guardAction(binding2, tool, config2, observedAt) {
26552
26556
  throw Error("GUARD_IDENTITY_REQUIRED");
26553
26557
  }
26554
26558
  const name2 = tool.call.name;
26559
+ if (name2 === "take_screenshot") throw Error("GUARD_ACTION_UNSUPPORTED");
26555
26560
  const kind = name2 === "command_run" ? "execute" : name2 === "localhost_request" ? "localhost-access" : name2 === "fs_write" || name2 === "fs_replace" ? "write" : name2.startsWith("git_") ? "git-read" : "read";
26556
26561
  const resourceKind = kind === "execute" ? "workspace" : kind === "localhost-access" ? "localhost-service" : kind === "git-read" ? "git-repository" : name2 === "fs_read" || kind === "write" ? "file" : "workspace";
26557
26562
  return { payloadHash: guardHash(tool.effective), request: BoundActionRequestSchema.parse({
@@ -27027,9 +27032,9 @@ var NativeJournal = class _NativeJournal {
27027
27032
  if (!validPid(pid)) throw failure2("JOURNAL_INPUT_INVALID");
27028
27033
  if (e.state !== "running" || !e.supervisors) throw failure2("JOURNAL_STATE_INVALID");
27029
27034
  if (containment !== void 0) {
27030
- const linux = validLinuxContainment(containment), darwin = !linux && validDarwinContainment(containment);
27031
- if (!linux && !darwin || !e.supervisors.includes(pid) || e.linuxSupervisors?.some((s) => s.pid === pid) || e.darwinSupervisors?.some((s) => s.pid === pid)) throw failure2("JOURNAL_INPUT_INVALID");
27032
- if (linux) (e.linuxSupervisors ??= []).push({ pid, containment: clone2(containment) });
27035
+ const linux2 = validLinuxContainment(containment), darwin = !linux2 && validDarwinContainment(containment);
27036
+ if (!linux2 && !darwin || !e.supervisors.includes(pid) || e.linuxSupervisors?.some((s) => s.pid === pid) || e.darwinSupervisors?.some((s) => s.pid === pid)) throw failure2("JOURNAL_INPUT_INVALID");
27037
+ if (linux2) (e.linuxSupervisors ??= []).push({ pid, containment: clone2(containment) });
27033
27038
  else (e.darwinSupervisors ??= []).push({ pid, containment: clone2(containment) });
27034
27039
  } else {
27035
27040
  if (e.supervisors.length >= MAX_SUPERVISORS) throw failure2("JOURNAL_SUPERVISOR_LIMIT");
@@ -27233,6 +27238,7 @@ import { constants as constants4 } from "node:fs";
27233
27238
 
27234
27239
  // agent/src/posix-consent.ts
27235
27240
  import { openSync, closeSync } from "node:fs";
27241
+ import { spawnSync as spawnSync2 } from "node:child_process";
27236
27242
  import { isatty, ReadStream, WriteStream } from "node:tty";
27237
27243
  import { createInterface } from "node:readline/promises";
27238
27244
  import path8 from "node:path";
@@ -27335,7 +27341,7 @@ async function planPermissionChange(current2, programs, input2) {
27335
27341
  }
27336
27342
 
27337
27343
  // agent/src/posix-consent.ts
27338
- async function terminal2(run, timeoutMs2, signal) {
27344
+ async function terminal2(run2, timeoutMs2, signal) {
27339
27345
  if (!process.getuid || process.getuid() === 0 || process.geteuid?.() !== process.getuid() || signal?.aborted) throw Error("OWNER_REVIEW_UNAVAILABLE");
27340
27346
  let readFd;
27341
27347
  try {
@@ -27371,7 +27377,7 @@ async function terminal2(run, timeoutMs2, signal) {
27371
27377
  };
27372
27378
  input2.on("data", bound);
27373
27379
  try {
27374
- return await run(async (prompt) => {
27380
+ return await run2(async (prompt) => {
27375
27381
  if (stop.signal.aborted) throw Error("OWNER_REVIEW_CANCELLED");
27376
27382
  return review.question(prompt, { signal: stop.signal });
27377
27383
  });
@@ -27400,16 +27406,41 @@ async function choosePosixFolder() {
27400
27406
  return await ask("Read/write folder: " + permissionLabel(folder) + "\nType APPROVE to accept: ") === "APPROVE" ? folder : null;
27401
27407
  }, 12e4);
27402
27408
  }
27409
+ var ACCESS_TEXT = "Local Commander lets your AI work on this computer.\n\nFull Access: files, commands and localhost with your account's rights (not an OS sandbox).\nChoose Folder: read and write one folder only.\n\nThis replaces the previous selection and lasts until you change or revoke it.";
27410
+ function selection(folder, full) {
27411
+ if (!path8.isAbsolute(folder) || folder.length > 4096 || /[\u0000-\u001f]/.test(folder)) throw Error("WORKSPACE_INVALID");
27412
+ return { mode: full ? "all-drives" : "folders", paths: [full ? "/" : folder] };
27413
+ }
27414
+ function macDialog() {
27415
+ const script = [
27416
+ "on run argv",
27417
+ 'set answer to button returned of (display dialog (item 1 of argv) with title "Local Commander" buttons {"Cancel", "Choose Folder\uFFFD", "Full Access"} default button "Full Access" cancel button "Cancel" with icon note)',
27418
+ 'if answer is "Full Access" then return "full"',
27419
+ 'return "folder:" & POSIX path of (choose folder with prompt "Choose the folder Local Commander may read and write")',
27420
+ "end run"
27421
+ ];
27422
+ const result2 = spawnSync2(
27423
+ "/usr/bin/osascript",
27424
+ [...script.flatMap((line) => ["-e", line]), ACCESS_TEXT],
27425
+ { encoding: "utf8", timeout: 24e4, maxBuffer: 16384, shell: false }
27426
+ );
27427
+ if (result2.error) return void 0;
27428
+ if (result2.status !== 0) return /\(-128\)/.test(result2.stderr) ? null : void 0;
27429
+ const out = result2.stdout.replace(/\n$/, "");
27430
+ if (out === "full") return selection("/", true);
27431
+ if (out.startsWith("folder:")) return selection(out.slice(7).replace(/(.)\/$/, "$1"), false);
27432
+ return void 0;
27433
+ }
27403
27434
  async function choosePosixAccess() {
27435
+ if (process.platform === "darwin") {
27436
+ const chosen = macDialog();
27437
+ if (chosen !== void 0) return chosen;
27438
+ }
27404
27439
  return terminal2(async (ask) => {
27405
- if (process.platform === "darwin") await ask("Local Commander runs each command as its own launchd job and stops that job's processes when the command ends; work handed to other services is not stopped. Press Enter to review access: ");
27406
- const choice = await ask("Local Commander access\n1. One folder: read and write files\n2. Full Access: account capabilities across this computer, including commands and localhost\nEnter 1 or 2 (empty cancels): ");
27407
- if (choice !== "1" && choice !== "2") return null;
27408
- const folder = choice === "2" ? "/" : await ask("Absolute folder path: ");
27409
- if (!path8.isAbsolute(folder) || folder.length > 4096 || /[\u0000-\u001f]/.test(folder)) throw Error("WORKSPACE_INVALID");
27410
- const summary = choice === "2" ? "Full Access allows programs to use your account's capabilities across this computer. This is not an OS sandbox." : "Allow reading and writing files in " + permissionLabel(folder) + ".";
27411
- if (await ask(summary + "\nThis replaces the previous folder/command/localhost selection and persists until revoked.\nType APPROVE to accept: ") !== "APPROVE") return null;
27412
- return { mode: choice === "2" ? "all-drives" : "folders", paths: [folder] };
27440
+ const answer = await ask("\n" + ACCESS_TEXT + "\n\nPress Enter for Full Access, type a folder path for one folder, or n to cancel: ");
27441
+ if (answer === "") return selection("/", true);
27442
+ if (/^(n|no|cancel)$/i.test(answer)) return null;
27443
+ return selection(answer, false);
27413
27444
  }, 24e4);
27414
27445
  }
27415
27446
 
@@ -28876,9 +28907,9 @@ var HostMemory = class {
28876
28907
  };
28877
28908
 
28878
28909
  // agent/src/tools.ts
28879
- import { constants as constants7 } from "node:fs";
28880
- import { lstat as lstat7, open as open6, readdir as readdir4, realpath as realpath7, rename as rename4, rm as rm5 } from "node:fs/promises";
28881
- import path17 from "node:path";
28910
+ import { constants as constants8 } from "node:fs";
28911
+ import { lstat as lstat8, open as open6, readdir as readdir5, realpath as realpath7, rename as rename4, rm as rm6 } from "node:fs/promises";
28912
+ import path18 from "node:path";
28882
28913
  import { createHash as createHash14, randomUUID as randomUUID7 } from "node:crypto";
28883
28914
 
28884
28915
  // src/guard.ts
@@ -29322,6 +29353,1249 @@ async function runSupervised(helper, request, options = {}) {
29322
29353
  });
29323
29354
  }
29324
29355
 
29356
+ // agent/src/screen-capture.ts
29357
+ import { execFile as execFile4 } from "node:child_process";
29358
+ import { randomBytes as randomBytes6 } from "node:crypto";
29359
+ import { constants as constants7 } from "node:fs";
29360
+ import { access as access3, lstat as lstat7, mkdtemp, readFile as readFile6, readdir as readdir4, rm as rm5, unlink as unlink2 } from "node:fs/promises";
29361
+ import os4 from "node:os";
29362
+ import path17 from "node:path";
29363
+
29364
+ // agent/src/dbus-portal.ts
29365
+ import net from "node:net";
29366
+ function sessionBusSocket(address) {
29367
+ for (const entry of (address ?? "").split(";")) {
29368
+ if (!entry.startsWith("unix:")) continue;
29369
+ for (const part of entry.slice(5).split(",")) {
29370
+ const at = part.indexOf("="), key = part.slice(0, at), value = decodeURIComponent(part.slice(at + 1));
29371
+ if (at > 0 && value && key === "path") return value;
29372
+ if (at > 0 && value && key === "abstract") return "\0" + value;
29373
+ }
29374
+ }
29375
+ return null;
29376
+ }
29377
+ var Writer = class {
29378
+ bytes = [];
29379
+ align(n) {
29380
+ while (this.bytes.length % n) this.bytes.push(0);
29381
+ }
29382
+ byte(v) {
29383
+ this.bytes.push(v & 255);
29384
+ }
29385
+ u32(v) {
29386
+ this.align(4);
29387
+ this.bytes.push(v & 255, v >>> 8 & 255, v >>> 16 & 255, v >>> 24 & 255);
29388
+ }
29389
+ str(v) {
29390
+ const b = Buffer.from(v, "utf8");
29391
+ this.u32(b.length);
29392
+ this.bytes.push(...b, 0);
29393
+ }
29394
+ sig(v) {
29395
+ this.byte(v.length);
29396
+ this.bytes.push(...Buffer.from(v, "ascii"), 0);
29397
+ }
29398
+ /** Basic value or variant: `s`, `o`, `g`, `u`, `b`, `v` ([signature, value]). */
29399
+ put(type, value) {
29400
+ if (type === "s" || type === "o") this.str(String(value));
29401
+ else if (type === "g") this.sig(String(value));
29402
+ else if (type === "u") this.u32(Number(value));
29403
+ else if (type === "b") this.u32(value ? 1 : 0);
29404
+ else if (type === "v") {
29405
+ const [inner, v] = value;
29406
+ this.sig(inner);
29407
+ this.put(inner, v);
29408
+ } else throw Error("type " + type);
29409
+ }
29410
+ /** a{sv} */
29411
+ dict(entries) {
29412
+ this.u32(0);
29413
+ const lengthAt = this.bytes.length - 4;
29414
+ this.align(8);
29415
+ const start = this.bytes.length;
29416
+ for (const [key, value] of entries) {
29417
+ this.align(8);
29418
+ this.str(key);
29419
+ this.put("v", value);
29420
+ }
29421
+ const length = this.bytes.length - start;
29422
+ this.bytes.splice(lengthAt, 4, length & 255, length >>> 8 & 255, length >>> 16 & 255, length >>> 24 & 255);
29423
+ }
29424
+ };
29425
+ var Reader = class {
29426
+ constructor(data, at, le) {
29427
+ this.data = data;
29428
+ this.at = at;
29429
+ this.le = le;
29430
+ }
29431
+ data;
29432
+ at;
29433
+ le;
29434
+ align(n) {
29435
+ this.at = Math.ceil(this.at / n) * n;
29436
+ }
29437
+ u32() {
29438
+ this.align(4);
29439
+ const v = this.le ? this.data.readUInt32LE(this.at) : this.data.readUInt32BE(this.at);
29440
+ this.at += 4;
29441
+ return v;
29442
+ }
29443
+ /** Reads one complete type from `sig` starting at `i`; returns the value and the index after the type. */
29444
+ read(sig2, i) {
29445
+ const c = sig2[i];
29446
+ const fixed = { y: 1, n: 2, q: 2, b: 4, i: 4, u: 4, h: 4, x: 8, t: 8, d: 8 };
29447
+ if (c in fixed) {
29448
+ const size = fixed[c];
29449
+ this.align(size);
29450
+ const v = size === 1 ? this.data[this.at] : size === 2 ? this.le ? this.data.readUInt16LE(this.at) : this.data.readUInt16BE(this.at) : size === 4 ? this.le ? this.data.readUInt32LE(this.at) : this.data.readUInt32BE(this.at) : null;
29451
+ this.at += size;
29452
+ return [c === "b" ? v === 1 : v, i + 1];
29453
+ }
29454
+ if (c === "s" || c === "o") {
29455
+ const n = this.u32(), v = this.data.toString("utf8", this.at, this.at + n);
29456
+ this.at += n + 1;
29457
+ return [v, i + 1];
29458
+ }
29459
+ if (c === "g") {
29460
+ const n = this.data[this.at], v = this.data.toString("ascii", this.at + 1, this.at + 1 + n);
29461
+ this.at += n + 2;
29462
+ return [v, i + 1];
29463
+ }
29464
+ if (c === "v") {
29465
+ const [inner] = this.read("g", 0);
29466
+ return [this.read(inner, 0)[0], i + 1];
29467
+ }
29468
+ if (c === "(" || c === "{") {
29469
+ this.align(8);
29470
+ const close = c === "(" ? ")" : "}", values = [];
29471
+ let j = i + 1;
29472
+ while (sig2[j] !== close) {
29473
+ const [v, next] = this.read(sig2, j);
29474
+ values.push(v);
29475
+ j = next;
29476
+ }
29477
+ return [values, j + 1];
29478
+ }
29479
+ if (c === "a") {
29480
+ const n = this.u32(), element = sig2[i + 1];
29481
+ this.align("xtd({".includes(element) ? 8 : element === "n" || element === "q" ? 2 : element === "y" || element === "g" || element === "v" ? 1 : 4);
29482
+ const end = this.at + n, values = [];
29483
+ let next = skip(sig2, i + 1);
29484
+ while (this.at < end) {
29485
+ const [v, j] = this.read(sig2, i + 1);
29486
+ values.push(v);
29487
+ next = j;
29488
+ }
29489
+ return [values, next];
29490
+ }
29491
+ throw Error("signature " + sig2);
29492
+ }
29493
+ };
29494
+ function skip(sig2, i) {
29495
+ const c = sig2[i];
29496
+ if (c === "a") return skip(sig2, i + 1);
29497
+ if (c === "(" || c === "{") {
29498
+ let j = i + 1;
29499
+ while (sig2[j] !== (c === "(" ? ")" : "}")) j = skip(sig2, j);
29500
+ return j + 1;
29501
+ }
29502
+ return i + 1;
29503
+ }
29504
+ function parse3(data) {
29505
+ const le = data[0] === 108, r = new Reader(data, 4, le), bodyLength = r.u32(), serial = r.u32();
29506
+ const [fields] = r.read("a(yv)", 0);
29507
+ const message2 = { type: data[1], serial, signature: "", body: [] };
29508
+ for (const [code, value] of fields) {
29509
+ if (code === 1) message2.path = String(value);
29510
+ else if (code === 2) message2.interface = String(value);
29511
+ else if (code === 3) message2.member = String(value);
29512
+ else if (code === 4) message2.errorName = String(value);
29513
+ else if (code === 5) message2.replySerial = Number(value);
29514
+ else if (code === 8) message2.signature = String(value);
29515
+ }
29516
+ r.align(8);
29517
+ const end = r.at + bodyLength;
29518
+ for (let i = 0; i < message2.signature.length && r.at < end; ) {
29519
+ const [v, next] = r.read(message2.signature, i);
29520
+ message2.body.push(v);
29521
+ i = next;
29522
+ }
29523
+ return message2;
29524
+ }
29525
+ function frameLength(data) {
29526
+ if (data.length < 16) return 0;
29527
+ const le = data[0] === 108, u = (at) => le ? data.readUInt32LE(at) : data.readUInt32BE(at);
29528
+ const length = Math.ceil((16 + u(12)) / 8) * 8 + u(4);
29529
+ return data.length >= length ? length : 0;
29530
+ }
29531
+ async function portalScreenshot(socket, uid, token, signal) {
29532
+ const connection = net.createConnection({ path: socket });
29533
+ try {
29534
+ return await new Promise((resolve, reject) => {
29535
+ let serial = 0, buffer = Buffer.alloc(0), authenticated = false, requestPath = "";
29536
+ const pending = /* @__PURE__ */ new Map();
29537
+ const fail7 = (error62) => reject(error62 instanceof Error ? error62 : Error(String(error62)));
29538
+ const abort = () => fail7(Error("ABORTED"));
29539
+ if (signal.aborted) return abort();
29540
+ signal.addEventListener("abort", abort, { once: true });
29541
+ connection.on("error", fail7);
29542
+ connection.on("close", () => fail7(Error("CLOSED")));
29543
+ const call = (destination, path30, iface, member, signature = "", body = () => {
29544
+ }) => new Promise((done, failed) => {
29545
+ const payload2 = new Writer();
29546
+ body(payload2);
29547
+ const header = new Writer(), fields = [[1, "o", path30], [2, "s", iface], [3, "s", member], [6, "s", destination]];
29548
+ if (signature) fields.push([8, "g", signature]);
29549
+ header.byte(108);
29550
+ header.byte(1);
29551
+ header.byte(0);
29552
+ header.byte(1);
29553
+ header.u32(payload2.bytes.length);
29554
+ header.u32(++serial);
29555
+ header.u32(0);
29556
+ const lengthAt = header.bytes.length - 4;
29557
+ header.align(8);
29558
+ const start = header.bytes.length;
29559
+ for (const [code, type, value] of fields) {
29560
+ header.align(8);
29561
+ header.byte(code);
29562
+ header.sig(type);
29563
+ header.put(type, value);
29564
+ }
29565
+ const length = header.bytes.length - start;
29566
+ header.bytes.splice(lengthAt, 4, length & 255, length >>> 8 & 255, length >>> 16 & 255, length >>> 24 & 255);
29567
+ header.align(8);
29568
+ pending.set(serial, (reply) => reply.type === 3 ? failed(Error(reply.errorName ?? "DBUS_ERROR")) : done(reply));
29569
+ connection.write(Buffer.from([...header.bytes, ...payload2.bytes]));
29570
+ });
29571
+ const bus = (member, signature, body) => call("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", member, signature, body);
29572
+ connection.on("data", (chunk) => {
29573
+ try {
29574
+ receive(chunk);
29575
+ } catch (error62) {
29576
+ fail7(error62);
29577
+ }
29578
+ });
29579
+ const receive = (chunk) => {
29580
+ buffer = Buffer.concat([buffer, chunk]);
29581
+ if (buffer.length > 1048576) return fail7(Error("OVERSIZED"));
29582
+ if (!authenticated) {
29583
+ const end = buffer.indexOf("\r\n");
29584
+ if (end < 0) return;
29585
+ const line = buffer.toString("ascii", 0, end);
29586
+ buffer = buffer.subarray(end + 2);
29587
+ if (!line.startsWith("OK ")) return fail7(Error("AUTH"));
29588
+ authenticated = true;
29589
+ connection.write("BEGIN\r\n");
29590
+ void (async () => {
29591
+ const unique = String((await bus("Hello")).body[0]);
29592
+ requestPath = "/org/freedesktop/portal/desktop/request/" + unique.slice(1).replace(/\./g, "_") + "/" + token;
29593
+ await bus("AddMatch", "s", (w) => w.put("s", "type='signal',interface='org.freedesktop.portal.Request',member='Response',path='" + requestPath + "'"));
29594
+ const handle = await call(
29595
+ "org.freedesktop.portal.Desktop",
29596
+ "/org/freedesktop/portal/desktop",
29597
+ "org.freedesktop.portal.Screenshot",
29598
+ "Screenshot",
29599
+ "sa{sv}",
29600
+ (w) => {
29601
+ w.put("s", "");
29602
+ w.dict([["handle_token", ["s", token]], ["interactive", ["b", false]]]);
29603
+ }
29604
+ );
29605
+ if (handle.body[0] !== requestPath) {
29606
+ requestPath = String(handle.body[0]);
29607
+ await bus("AddMatch", "s", (w) => w.put("s", "type='signal',interface='org.freedesktop.portal.Request',member='Response',path='" + requestPath + "'"));
29608
+ }
29609
+ })().catch(fail7);
29610
+ }
29611
+ for (let length = frameLength(buffer); authenticated && length; length = frameLength(buffer)) {
29612
+ const message2 = parse3(buffer.subarray(0, length));
29613
+ buffer = buffer.subarray(length);
29614
+ if ((message2.type === 2 || message2.type === 3) && message2.replySerial !== void 0) {
29615
+ pending.get(message2.replySerial)?.(message2);
29616
+ pending.delete(message2.replySerial);
29617
+ } else if (message2.type === 4 && message2.member === "Response" && message2.path === requestPath && message2.signature === "ua{sv}") {
29618
+ const results2 = message2.body[1], uri = results2.find(([key]) => key === "uri")?.[1];
29619
+ resolve({ code: Number(message2.body[0]), uri: typeof uri === "string" ? uri : void 0 });
29620
+ }
29621
+ }
29622
+ };
29623
+ connection.on("connect", () => connection.write("\0AUTH EXTERNAL " + Buffer.from(String(uid), "ascii").toString("hex") + "\r\n"));
29624
+ });
29625
+ } finally {
29626
+ connection.destroy();
29627
+ }
29628
+ }
29629
+
29630
+ // agent/src/screen-image.ts
29631
+ import { inflateSync } from "node:zlib";
29632
+ var MAX_EDGE = 16384;
29633
+ var MAX_PIXELS = 67108864;
29634
+ function sizeOk(width, height) {
29635
+ return Number.isSafeInteger(width) && Number.isSafeInteger(height) && width > 0 && height > 0 && width <= MAX_EDGE && height <= MAX_EDGE && width * height <= MAX_PIXELS;
29636
+ }
29637
+ function decodePng(data) {
29638
+ if (data.length < 33 || data.readUInt32BE(0) !== 2303741511 || data.readUInt32BE(4) !== 218765834) return null;
29639
+ let width = 0, height = 0, channels = 0;
29640
+ const idat = [];
29641
+ for (let at = 8; at + 12 <= data.length; ) {
29642
+ const length = data.readUInt32BE(at), type = data.toString("latin1", at + 4, at + 8), body = at + 8;
29643
+ if (body + length + 4 > data.length) return null;
29644
+ if (type === "IHDR") {
29645
+ if (length !== 13) return null;
29646
+ width = data.readUInt32BE(body);
29647
+ height = data.readUInt32BE(body + 4);
29648
+ const depth = data[body + 8], color = data[body + 9], interlace = data[body + 12];
29649
+ channels = color === 0 ? 1 : color === 2 ? 3 : color === 4 ? 2 : color === 6 ? 4 : 0;
29650
+ if (depth !== 8 || !channels || interlace !== 0 || data[body + 10] !== 0 || data[body + 11] !== 0 || !sizeOk(width, height)) return null;
29651
+ } else if (type === "IDAT") idat.push(data.subarray(body, body + length));
29652
+ else if (type === "IEND") break;
29653
+ at = body + length + 4;
29654
+ }
29655
+ if (!channels || !idat.length) return null;
29656
+ const stride = width * channels, expected = (stride + 1) * height;
29657
+ let raw;
29658
+ try {
29659
+ raw = inflateSync(Buffer.concat(idat), { maxOutputLength: expected });
29660
+ } catch {
29661
+ return null;
29662
+ }
29663
+ if (raw.length !== expected) return null;
29664
+ const rgb = Buffer.alloc(width * height * 3);
29665
+ let previous = Buffer.alloc(stride), current2 = Buffer.alloc(stride);
29666
+ for (let y = 0; y < height; y++) {
29667
+ const filter = raw[y * (stride + 1)], line = raw.subarray(y * (stride + 1) + 1, (y + 1) * (stride + 1));
29668
+ for (let x = 0; x < stride; x++) {
29669
+ const a = x >= channels ? current2[x - channels] : 0, b = previous[x], c = x >= channels ? previous[x - channels] : 0;
29670
+ let value = line[x];
29671
+ if (filter === 1) value += a;
29672
+ else if (filter === 2) value += b;
29673
+ else if (filter === 3) value += a + b >> 1;
29674
+ else if (filter === 4) {
29675
+ const p = a + b - c, pa = Math.abs(p - a), pb = Math.abs(p - b), pc = Math.abs(p - c);
29676
+ value += pa <= pb && pa <= pc ? a : pb <= pc ? b : c;
29677
+ } else if (filter !== 0) return null;
29678
+ current2[x] = value & 255;
29679
+ }
29680
+ for (let x = 0, o = y * width * 3; x < width; x++, o += 3) {
29681
+ const i = x * channels;
29682
+ if (channels <= 2) rgb[o] = rgb[o + 1] = rgb[o + 2] = current2[i];
29683
+ else {
29684
+ rgb[o] = current2[i];
29685
+ rgb[o + 1] = current2[i + 1];
29686
+ rgb[o + 2] = current2[i + 2];
29687
+ }
29688
+ }
29689
+ [previous, current2] = [current2, previous];
29690
+ }
29691
+ return { width, height, rgb };
29692
+ }
29693
+ function decodeXwd(data) {
29694
+ if (data.length < 100) return null;
29695
+ const field = (index) => data.readUInt32BE(index * 4);
29696
+ const headerSize = field(0), version2 = field(1), format = field(2), width = field(4), height = field(5), byteOrder = field(7);
29697
+ const bitsPerPixel = field(11), bytesPerLine = field(12), visualClass = field(13), masks = [field(14), field(15), field(16)], colors = field(19);
29698
+ if (version2 !== 7 || format !== 2 || headerSize < 100 || ![4, 5].includes(visualClass) || ![24, 32].includes(bitsPerPixel) || !sizeOk(width, height) || colors > 65536) return null;
29699
+ const pixelBytes = bitsPerPixel / 8, start = headerSize + colors * 12;
29700
+ if (bytesPerLine < width * pixelBytes || start + bytesPerLine * height > data.length || masks.some((mask) => !mask)) return null;
29701
+ const shifts = masks.map((mask) => {
29702
+ let shift = 0;
29703
+ while (!(mask >>> shift & 1)) shift++;
29704
+ return shift;
29705
+ });
29706
+ const scales = masks.map((mask, i) => 255 / (mask >>> shifts[i]));
29707
+ const rgb = Buffer.alloc(width * height * 3);
29708
+ for (let y = 0; y < height; y++) for (let x = 0, at = start + y * bytesPerLine, o = y * width * 3; x < width; x++, at += pixelBytes, o += 3) {
29709
+ const pixel = pixelBytes === 4 ? byteOrder === 0 ? data.readUInt32LE(at) : data.readUInt32BE(at) : byteOrder === 0 ? data[at] | data[at + 1] << 8 | data[at + 2] << 16 : data[at] << 16 | data[at + 1] << 8 | data[at + 2];
29710
+ for (let c = 0; c < 3; c++) rgb[o + c] = Math.round(((pixel & masks[c]) >>> 0 >>> shifts[c]) * scales[c]);
29711
+ }
29712
+ return { width, height, rgb };
29713
+ }
29714
+ function downscale(image, edge) {
29715
+ const scale = Math.min(1, edge / Math.max(image.width, image.height));
29716
+ if (scale >= 1) return image;
29717
+ const width = Math.max(1, Math.round(image.width * scale)), height = Math.max(1, Math.round(image.height * scale));
29718
+ const xs = Array.from({ length: width + 1 }, (_, x) => Math.min(image.width, Math.floor(x * image.width / width)));
29719
+ const ys = Array.from({ length: height + 1 }, (_, y) => Math.min(image.height, Math.floor(y * image.height / height)));
29720
+ const rgb = Buffer.alloc(width * height * 3), sums = new Float64Array(width * 3);
29721
+ for (let y = 0; y < height; y++) {
29722
+ sums.fill(0);
29723
+ for (let sy = ys[y]; sy < ys[y + 1]; sy++) for (let x = 0; x < width; x++) for (let sx = xs[x]; sx < xs[x + 1]; sx++) {
29724
+ const i = (sy * image.width + sx) * 3;
29725
+ sums[x * 3] = sums[x * 3] + image.rgb[i];
29726
+ sums[x * 3 + 1] = sums[x * 3 + 1] + image.rgb[i + 1];
29727
+ sums[x * 3 + 2] = sums[x * 3 + 2] + image.rgb[i + 2];
29728
+ }
29729
+ for (let x = 0; x < width; x++) {
29730
+ const count3 = (ys[y + 1] - ys[y]) * (xs[x + 1] - xs[x]);
29731
+ for (let c = 0; c < 3; c++) rgb[(y * width + x) * 3 + c] = Math.round(sums[x * 3 + c] / count3);
29732
+ }
29733
+ }
29734
+ return { width, height, rgb };
29735
+ }
29736
+ var ZIGZAG = [
29737
+ 0,
29738
+ 1,
29739
+ 5,
29740
+ 6,
29741
+ 14,
29742
+ 15,
29743
+ 27,
29744
+ 28,
29745
+ 2,
29746
+ 4,
29747
+ 7,
29748
+ 13,
29749
+ 16,
29750
+ 26,
29751
+ 29,
29752
+ 42,
29753
+ 3,
29754
+ 8,
29755
+ 12,
29756
+ 17,
29757
+ 25,
29758
+ 30,
29759
+ 41,
29760
+ 43,
29761
+ 9,
29762
+ 11,
29763
+ 18,
29764
+ 24,
29765
+ 31,
29766
+ 40,
29767
+ 44,
29768
+ 53,
29769
+ 10,
29770
+ 19,
29771
+ 23,
29772
+ 32,
29773
+ 39,
29774
+ 45,
29775
+ 52,
29776
+ 54,
29777
+ 20,
29778
+ 22,
29779
+ 33,
29780
+ 38,
29781
+ 46,
29782
+ 51,
29783
+ 55,
29784
+ 60,
29785
+ 21,
29786
+ 34,
29787
+ 37,
29788
+ 47,
29789
+ 50,
29790
+ 56,
29791
+ 59,
29792
+ 61,
29793
+ 35,
29794
+ 36,
29795
+ 48,
29796
+ 49,
29797
+ 57,
29798
+ 58,
29799
+ 62,
29800
+ 63
29801
+ ];
29802
+ var LUMA_QUANT = [
29803
+ 16,
29804
+ 11,
29805
+ 10,
29806
+ 16,
29807
+ 24,
29808
+ 40,
29809
+ 51,
29810
+ 61,
29811
+ 12,
29812
+ 12,
29813
+ 14,
29814
+ 19,
29815
+ 26,
29816
+ 58,
29817
+ 60,
29818
+ 55,
29819
+ 14,
29820
+ 13,
29821
+ 16,
29822
+ 24,
29823
+ 40,
29824
+ 57,
29825
+ 69,
29826
+ 56,
29827
+ 14,
29828
+ 17,
29829
+ 22,
29830
+ 29,
29831
+ 51,
29832
+ 87,
29833
+ 80,
29834
+ 62,
29835
+ 18,
29836
+ 22,
29837
+ 37,
29838
+ 56,
29839
+ 68,
29840
+ 109,
29841
+ 103,
29842
+ 77,
29843
+ 24,
29844
+ 35,
29845
+ 55,
29846
+ 64,
29847
+ 81,
29848
+ 104,
29849
+ 113,
29850
+ 92,
29851
+ 49,
29852
+ 64,
29853
+ 78,
29854
+ 87,
29855
+ 103,
29856
+ 121,
29857
+ 120,
29858
+ 101,
29859
+ 72,
29860
+ 92,
29861
+ 95,
29862
+ 98,
29863
+ 112,
29864
+ 100,
29865
+ 103,
29866
+ 99
29867
+ ];
29868
+ var CHROMA_QUANT = [17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, ...Array(38).fill(99)];
29869
+ var AC_LUMA_VALUES = [
29870
+ 1,
29871
+ 2,
29872
+ 3,
29873
+ 0,
29874
+ 4,
29875
+ 17,
29876
+ 5,
29877
+ 18,
29878
+ 33,
29879
+ 49,
29880
+ 65,
29881
+ 6,
29882
+ 19,
29883
+ 81,
29884
+ 97,
29885
+ 7,
29886
+ 34,
29887
+ 113,
29888
+ 20,
29889
+ 50,
29890
+ 129,
29891
+ 145,
29892
+ 161,
29893
+ 8,
29894
+ 35,
29895
+ 66,
29896
+ 177,
29897
+ 193,
29898
+ 21,
29899
+ 82,
29900
+ 209,
29901
+ 240,
29902
+ 36,
29903
+ 51,
29904
+ 98,
29905
+ 114,
29906
+ 130,
29907
+ 9,
29908
+ 10,
29909
+ 22,
29910
+ 23,
29911
+ 24,
29912
+ 25,
29913
+ 26,
29914
+ 37,
29915
+ 38,
29916
+ 39,
29917
+ 40,
29918
+ 41,
29919
+ 42,
29920
+ 52,
29921
+ 53,
29922
+ 54,
29923
+ 55,
29924
+ 56,
29925
+ 57,
29926
+ 58,
29927
+ 67,
29928
+ 68,
29929
+ 69,
29930
+ 70,
29931
+ 71,
29932
+ 72,
29933
+ 73,
29934
+ 74,
29935
+ 83,
29936
+ 84,
29937
+ 85,
29938
+ 86,
29939
+ 87,
29940
+ 88,
29941
+ 89,
29942
+ 90,
29943
+ 99,
29944
+ 100,
29945
+ 101,
29946
+ 102,
29947
+ 103,
29948
+ 104,
29949
+ 105,
29950
+ 106,
29951
+ 115,
29952
+ 116,
29953
+ 117,
29954
+ 118,
29955
+ 119,
29956
+ 120,
29957
+ 121,
29958
+ 122,
29959
+ 131,
29960
+ 132,
29961
+ 133,
29962
+ 134,
29963
+ 135,
29964
+ 136,
29965
+ 137,
29966
+ 138,
29967
+ 146,
29968
+ 147,
29969
+ 148,
29970
+ 149,
29971
+ 150,
29972
+ 151,
29973
+ 152,
29974
+ 153,
29975
+ 154,
29976
+ 162,
29977
+ 163,
29978
+ 164,
29979
+ 165,
29980
+ 166,
29981
+ 167,
29982
+ 168,
29983
+ 169,
29984
+ 170,
29985
+ 178,
29986
+ 179,
29987
+ 180,
29988
+ 181,
29989
+ 182,
29990
+ 183,
29991
+ 184,
29992
+ 185,
29993
+ 186,
29994
+ 194,
29995
+ 195,
29996
+ 196,
29997
+ 197,
29998
+ 198,
29999
+ 199,
30000
+ 200,
30001
+ 201,
30002
+ 202,
30003
+ 210,
30004
+ 211,
30005
+ 212,
30006
+ 213,
30007
+ 214,
30008
+ 215,
30009
+ 216,
30010
+ 217,
30011
+ 218,
30012
+ 225,
30013
+ 226,
30014
+ 227,
30015
+ 228,
30016
+ 229,
30017
+ 230,
30018
+ 231,
30019
+ 232,
30020
+ 233,
30021
+ 234,
30022
+ 241,
30023
+ 242,
30024
+ 243,
30025
+ 244,
30026
+ 245,
30027
+ 246,
30028
+ 247,
30029
+ 248,
30030
+ 249,
30031
+ 250
30032
+ ];
30033
+ var AC_CHROMA_VALUES = [
30034
+ 0,
30035
+ 1,
30036
+ 2,
30037
+ 3,
30038
+ 17,
30039
+ 4,
30040
+ 5,
30041
+ 33,
30042
+ 49,
30043
+ 6,
30044
+ 18,
30045
+ 65,
30046
+ 81,
30047
+ 7,
30048
+ 97,
30049
+ 113,
30050
+ 19,
30051
+ 34,
30052
+ 50,
30053
+ 129,
30054
+ 8,
30055
+ 20,
30056
+ 66,
30057
+ 145,
30058
+ 161,
30059
+ 177,
30060
+ 193,
30061
+ 9,
30062
+ 35,
30063
+ 51,
30064
+ 82,
30065
+ 240,
30066
+ 21,
30067
+ 98,
30068
+ 114,
30069
+ 209,
30070
+ 10,
30071
+ 22,
30072
+ 36,
30073
+ 52,
30074
+ 225,
30075
+ 37,
30076
+ 241,
30077
+ 23,
30078
+ 24,
30079
+ 25,
30080
+ 26,
30081
+ 38,
30082
+ 39,
30083
+ 40,
30084
+ 41,
30085
+ 42,
30086
+ 53,
30087
+ 54,
30088
+ 55,
30089
+ 56,
30090
+ 57,
30091
+ 58,
30092
+ 67,
30093
+ 68,
30094
+ 69,
30095
+ 70,
30096
+ 71,
30097
+ 72,
30098
+ 73,
30099
+ 74,
30100
+ 83,
30101
+ 84,
30102
+ 85,
30103
+ 86,
30104
+ 87,
30105
+ 88,
30106
+ 89,
30107
+ 90,
30108
+ 99,
30109
+ 100,
30110
+ 101,
30111
+ 102,
30112
+ 103,
30113
+ 104,
30114
+ 105,
30115
+ 106,
30116
+ 115,
30117
+ 116,
30118
+ 117,
30119
+ 118,
30120
+ 119,
30121
+ 120,
30122
+ 121,
30123
+ 122,
30124
+ 130,
30125
+ 131,
30126
+ 132,
30127
+ 133,
30128
+ 134,
30129
+ 135,
30130
+ 136,
30131
+ 137,
30132
+ 138,
30133
+ 146,
30134
+ 147,
30135
+ 148,
30136
+ 149,
30137
+ 150,
30138
+ 151,
30139
+ 152,
30140
+ 153,
30141
+ 154,
30142
+ 162,
30143
+ 163,
30144
+ 164,
30145
+ 165,
30146
+ 166,
30147
+ 167,
30148
+ 168,
30149
+ 169,
30150
+ 170,
30151
+ 178,
30152
+ 179,
30153
+ 180,
30154
+ 181,
30155
+ 182,
30156
+ 183,
30157
+ 184,
30158
+ 185,
30159
+ 186,
30160
+ 194,
30161
+ 195,
30162
+ 196,
30163
+ 197,
30164
+ 198,
30165
+ 199,
30166
+ 200,
30167
+ 201,
30168
+ 202,
30169
+ 210,
30170
+ 211,
30171
+ 212,
30172
+ 213,
30173
+ 214,
30174
+ 215,
30175
+ 216,
30176
+ 217,
30177
+ 218,
30178
+ 226,
30179
+ 227,
30180
+ 228,
30181
+ 229,
30182
+ 230,
30183
+ 231,
30184
+ 232,
30185
+ 233,
30186
+ 234,
30187
+ 242,
30188
+ 243,
30189
+ 244,
30190
+ 245,
30191
+ 246,
30192
+ 247,
30193
+ 248,
30194
+ 249,
30195
+ 250
30196
+ ];
30197
+ var DC_VALUES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
30198
+ var HUFFMAN = [
30199
+ [0, [0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], DC_VALUES],
30200
+ [16, [0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125], AC_LUMA_VALUES],
30201
+ [1, [0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0], DC_VALUES],
30202
+ [17, [0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119], AC_CHROMA_VALUES]
30203
+ ];
30204
+ var CODES = HUFFMAN.map(([, counts, values]) => {
30205
+ const table2 = [];
30206
+ let code = 0, at = 0;
30207
+ counts.forEach((count3, index) => {
30208
+ for (let i = 0; i < count3; i++) table2[values[at++]] = [code++, index + 1];
30209
+ code <<= 1;
30210
+ });
30211
+ return table2;
30212
+ });
30213
+ var AAN = [1, 1.387039845, 1.306562965, 1.175875602, 1, 0.785694958, 0.5411961, 0.275899379];
30214
+ function quantTables(quality) {
30215
+ const factor = quality < 50 ? 5e3 / quality : 200 - quality * 2;
30216
+ const scaled = (base) => base.map((value) => Math.min(255, Math.max(1, Math.floor((value * factor + 50) / 100))));
30217
+ const divisors = (table2) => Float64Array.from(table2, (value, k) => 1 / (value * AAN[k >> 3] * AAN[k & 7] * 8));
30218
+ const luma = scaled(LUMA_QUANT), chroma = scaled(CHROMA_QUANT);
30219
+ return { luma, chroma, lumaDivisors: divisors(luma), chromaDivisors: divisors(chroma) };
30220
+ }
30221
+ var BitWriter = class {
30222
+ buffer = Buffer.alloc(65536);
30223
+ length = 0;
30224
+ bits = 0;
30225
+ count = 0;
30226
+ byte(value) {
30227
+ if (this.length === this.buffer.length) {
30228
+ const next = Buffer.alloc(this.buffer.length * 2);
30229
+ this.buffer.copy(next);
30230
+ this.buffer = next;
30231
+ }
30232
+ this.buffer[this.length++] = value;
30233
+ }
30234
+ bytes(values) {
30235
+ for (const value of values) this.byte(value);
30236
+ }
30237
+ write(code, length) {
30238
+ this.bits = (this.bits << length | code) >>> 0;
30239
+ this.count += length;
30240
+ while (this.count >= 8) {
30241
+ const value = this.bits >>> this.count - 8 & 255;
30242
+ this.byte(value);
30243
+ if (value === 255) this.byte(0);
30244
+ this.count -= 8;
30245
+ this.bits &= (1 << this.count) - 1;
30246
+ }
30247
+ }
30248
+ flush() {
30249
+ if (this.count > 0) this.write((1 << 8 - this.count) - 1, 8 - this.count);
30250
+ }
30251
+ result() {
30252
+ return Buffer.from(this.buffer.subarray(0, this.length));
30253
+ }
30254
+ };
30255
+ function transform2(block, divisors, out) {
30256
+ for (let pass = 0; pass < 2; pass++) for (let i = 0; i < 8; i++) {
30257
+ const step = pass ? 8 : 1, base = pass ? i : i * 8, at = (k) => base + k * step;
30258
+ const d0 = block[at(0)], d1 = block[at(1)], d2 = block[at(2)], d3 = block[at(3)], d4 = block[at(4)], d5 = block[at(5)], d6 = block[at(6)], d7 = block[at(7)];
30259
+ const t0 = d0 + d7, t7 = d0 - d7, t1 = d1 + d6, t6 = d1 - d6, t2 = d2 + d5, t5 = d2 - d5, t3 = d3 + d4, t4 = d3 - d4;
30260
+ const t10 = t0 + t3, t13 = t0 - t3, t11 = t1 + t2, t12 = t1 - t2;
30261
+ block[at(0)] = t10 + t11;
30262
+ block[at(4)] = t10 - t11;
30263
+ const z1 = (t12 + t13) * 0.707106781;
30264
+ block[at(2)] = t13 + z1;
30265
+ block[at(6)] = t13 - z1;
30266
+ const o10 = t4 + t5, o11 = t5 + t6, o12 = t6 + t7;
30267
+ const z5 = (o10 - o12) * 0.382683433, z2 = 0.5411961 * o10 + z5, z4 = 1.306562965 * o12 + z5, z3 = o11 * 0.707106781;
30268
+ const z11 = t7 + z3, z13 = t7 - z3;
30269
+ block[at(5)] = z13 + z2;
30270
+ block[at(3)] = z13 - z2;
30271
+ block[at(1)] = z11 + z4;
30272
+ block[at(7)] = z11 - z4;
30273
+ }
30274
+ for (let k = 0; k < 64; k++) out[ZIGZAG[k]] = Math.round(block[k] * divisors[k]);
30275
+ }
30276
+ function magnitude(value) {
30277
+ const absolute2 = Math.abs(value);
30278
+ let length = 0;
30279
+ while (absolute2 >> length) length++;
30280
+ return [value < 0 ? value + (1 << length) - 1 : value, length];
30281
+ }
30282
+ function encodeJpeg(image, quality) {
30283
+ const { width, height, rgb } = image, tables = quantTables(Math.min(100, Math.max(1, Math.round(quality))));
30284
+ const out = new BitWriter(), word = (value) => [value >> 8, value & 255];
30285
+ out.bytes([255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0]);
30286
+ out.bytes([255, 219, 0, 132]);
30287
+ for (const [id2, table2] of [[0, tables.luma], [1, tables.chroma]]) {
30288
+ const zig = new Array(64);
30289
+ table2.forEach((value, k) => {
30290
+ zig[ZIGZAG[k]] = value;
30291
+ });
30292
+ out.bytes([id2, ...zig]);
30293
+ }
30294
+ out.bytes([255, 192, 0, 17, 8, ...word(height), ...word(width), 3, 1, 34, 0, 2, 17, 1, 3, 17, 1]);
30295
+ out.bytes([255, 196, ...word(2 + HUFFMAN.reduce((sum, [, , values]) => sum + 17 + values.length, 0))]);
30296
+ for (const [id2, counts, values] of HUFFMAN) out.bytes([id2, ...counts, ...values]);
30297
+ out.bytes([255, 218, 0, 12, 3, 1, 0, 2, 17, 3, 17, 0, 63, 0]);
30298
+ const block = new Float64Array(64), coefficients = new Int32Array(64), dc = [0, 0, 0];
30299
+ const Y = new Float64Array(256), Cb = new Float64Array(256), Cr = new Float64Array(256);
30300
+ const encode5 = (component, divisors) => {
30301
+ transform2(block, divisors, coefficients);
30302
+ const dcCodes = CODES[component ? 2 : 0], acCodes = CODES[component ? 3 : 1];
30303
+ const diff = coefficients[0] - dc[component];
30304
+ dc[component] = coefficients[0];
30305
+ const [bits, size] = magnitude(diff);
30306
+ out.write(...dcCodes[size]);
30307
+ if (size) out.write(bits, size);
30308
+ let last = 63;
30309
+ while (last > 0 && coefficients[last] === 0) last--;
30310
+ for (let k = 1, zeros = 0; k <= last; k++) {
30311
+ if (coefficients[k] === 0) {
30312
+ zeros++;
30313
+ continue;
30314
+ }
30315
+ while (zeros >= 16) {
30316
+ out.write(...acCodes[240]);
30317
+ zeros -= 16;
30318
+ }
30319
+ const [value, length] = magnitude(coefficients[k]);
30320
+ out.write(...acCodes[(zeros << 4) + length]);
30321
+ out.write(value, length);
30322
+ zeros = 0;
30323
+ }
30324
+ if (last < 63) out.write(...acCodes[0]);
30325
+ };
30326
+ for (let my = 0; my < height; my += 16) for (let mx = 0; mx < width; mx += 16) {
30327
+ for (let y = 0; y < 16; y++) for (let x = 0; x < 16; x++) {
30328
+ const i = (Math.min(height - 1, my + y) * width + Math.min(width - 1, mx + x)) * 3, r = rgb[i], g = rgb[i + 1], b = rgb[i + 2];
30329
+ Y[y * 16 + x] = 0.299 * r + 0.587 * g + 0.114 * b - 128;
30330
+ Cb[y * 16 + x] = -0.168736 * r - 0.331264 * g + 0.5 * b;
30331
+ Cr[y * 16 + x] = 0.5 * r - 0.418688 * g - 0.081312 * b;
30332
+ }
30333
+ for (const [ox, oy] of [[0, 0], [8, 0], [0, 8], [8, 8]]) {
30334
+ for (let y = 0; y < 8; y++) for (let x = 0; x < 8; x++) block[y * 8 + x] = Y[(oy + y) * 16 + ox + x];
30335
+ encode5(0, tables.lumaDivisors);
30336
+ }
30337
+ for (const [component, plane] of [[1, Cb], [2, Cr]]) {
30338
+ for (let y = 0; y < 8; y++) for (let x = 0; x < 8; x++) {
30339
+ const at = y * 32 + x * 2;
30340
+ block[y * 8 + x] = (plane[at] + plane[at + 1] + plane[at + 16] + plane[at + 17]) / 4;
30341
+ }
30342
+ encode5(component, tables.chromaDivisors);
30343
+ }
30344
+ }
30345
+ out.flush();
30346
+ out.bytes([255, 217]);
30347
+ return out.result();
30348
+ }
30349
+ function fitJpeg(image, maxEdge, maxBytes) {
30350
+ for (const edge of [maxEdge, 1280, 1024, 800, 640]) {
30351
+ const scaled = downscale(image, edge);
30352
+ for (const quality of [75, 60, 45, 35]) {
30353
+ const data = encodeJpeg(scaled, quality);
30354
+ if (data.length <= maxBytes) return { data, width: scaled.width, height: scaled.height };
30355
+ }
30356
+ }
30357
+ return null;
30358
+ }
30359
+
30360
+ // agent/src/screen-capture.ts
30361
+ var SCREENSHOT_MAX_JPEG_BYTES = 131072;
30362
+ var SCREENSHOT_MAX_EDGE = 1568;
30363
+ function screenshotEnabled(env = process.env) {
30364
+ return env.LC_SCREENSHOT_ENABLED === "true";
30365
+ }
30366
+ var SCREENSHOT_ACCEPTANCE_FILE = "screenshot-acceptance-enabled";
30367
+ var SCREENSHOT_OWNER_OFF_FILE = "screenshot-disabled-by-owner";
30368
+ var ScreenCaptureError = class extends Error {
30369
+ constructor(code, detail) {
30370
+ super(code);
30371
+ this.code = code;
30372
+ this.detail = detail;
30373
+ this.name = "ScreenCaptureError";
30374
+ }
30375
+ code;
30376
+ detail;
30377
+ };
30378
+ var KNOWN = /^(SCREEN_UNAVAILABLE|SCREEN_LOCKED|SCREEN_ENCODER_UNAVAILABLE|SCREENSHOT_TOO_LARGE|ARGUMENT_INVALID)$/;
30379
+ function jpegSize(data) {
30380
+ if (data.length < 4 || data[0] !== 255 || data[1] !== 216 || data[data.length - 2] !== 255 || data[data.length - 1] !== 217) return null;
30381
+ for (let at = 2; at + 9 < data.length; ) {
30382
+ if (data[at] !== 255) return null;
30383
+ const marker = data[at + 1], length = data.readUInt16BE(at + 2);
30384
+ if (marker >= 192 && marker <= 207 && ![196, 200, 204].includes(marker)) {
30385
+ const height = data.readUInt16BE(at + 5), width = data.readUInt16BE(at + 7);
30386
+ return width > 0 && height > 0 ? { width, height } : null;
30387
+ }
30388
+ at += 2 + length;
30389
+ }
30390
+ return null;
30391
+ }
30392
+ function run(file2, args, signal, maxBuffer = 65536, env = buildChildEnvironment(process.env, process.platform)) {
30393
+ return new Promise((resolve, reject) => {
30394
+ execFile4(
30395
+ file2,
30396
+ args,
30397
+ { encoding: "buffer", timeout: 15e3, maxBuffer, windowsHide: true, shell: false, env, signal },
30398
+ (error62, stdout, stderr) => error62 ? reject(Object.assign(error62, { stdout, stderr })) : resolve({ stdout, stderr })
30399
+ );
30400
+ });
30401
+ }
30402
+ async function windows(bridge, signal) {
30403
+ if (!path17.isAbsolute(bridge)) throw new ScreenCaptureError("SCREEN_UNAVAILABLE");
30404
+ let stdout;
30405
+ try {
30406
+ ({ stdout } = await run(bridge, ["screenshot", String(SCREENSHOT_MAX_EDGE), String(SCREENSHOT_MAX_JPEG_BYTES)], signal, 262144));
30407
+ } catch (error62) {
30408
+ if (signal.aborted) throw new ScreenCaptureError("CANCELLED");
30409
+ const code = /^\{"error":"([A-Z_]+)"\}$/.exec(String(error62.stderr ?? ""))?.[1];
30410
+ throw new ScreenCaptureError(code && KNOWN.test(code) ? code : "SCREEN_UNAVAILABLE");
30411
+ }
30412
+ try {
30413
+ const value = JSON.parse(stdout.toString("utf8"));
30414
+ const data = Buffer.from(value.data, "base64"), size = jpegSize(data);
30415
+ if (!size || size.width !== value.width || size.height !== value.height || !Number.isSafeInteger(value.sourceWidth) || !Number.isSafeInteger(value.sourceHeight)) throw Error();
30416
+ return { data, width: size.width, height: size.height, sourceWidth: value.sourceWidth, sourceHeight: value.sourceHeight };
30417
+ } catch {
30418
+ throw new ScreenCaptureError("SCREEN_UNAVAILABLE");
30419
+ }
30420
+ }
30421
+ async function mac3(signal) {
30422
+ try {
30423
+ const preflight = await run("/usr/bin/osascript", ["-l", "JavaScript", "-e", "ObjC.import('CoreGraphics'); $.CGPreflightScreenCaptureAccess()"], signal);
30424
+ if (preflight.stdout.toString("utf8").trim() !== "true") {
30425
+ await run("/usr/bin/osascript", ["-l", "JavaScript", "-e", "ObjC.import('CoreGraphics'); $.CGRequestScreenCaptureAccess()"], signal).catch(() => {
30426
+ });
30427
+ throw new ScreenCaptureError("SCREEN_RECORDING_PERMISSION_REQUIRED");
30428
+ }
30429
+ } catch (error62) {
30430
+ if (error62 instanceof ScreenCaptureError) throw error62;
30431
+ throw new ScreenCaptureError(signal.aborted ? "CANCELLED" : "SCREEN_UNAVAILABLE");
30432
+ }
30433
+ const folder = await mkdtemp(path17.join(os4.tmpdir(), "lc-screen-"));
30434
+ try {
30435
+ const full = path17.join(folder, "full.png"), small = path17.join(folder, "small.jpg");
30436
+ try {
30437
+ await run("/usr/sbin/screencapture", ["-x", "-m", "-t", "png", full], signal);
30438
+ } catch {
30439
+ throw new ScreenCaptureError(signal.aborted ? "CANCELLED" : "SCREEN_UNAVAILABLE");
30440
+ }
30441
+ const source = (await run("/usr/bin/sips", ["-g", "pixelWidth", "-g", "pixelHeight", full], signal)).stdout.toString("utf8");
30442
+ const sourceWidth = Number(/pixelWidth: (\d+)/.exec(source)?.[1]), sourceHeight = Number(/pixelHeight: (\d+)/.exec(source)?.[1]);
30443
+ if (!sourceWidth || !sourceHeight) throw new ScreenCaptureError("SCREEN_UNAVAILABLE");
30444
+ for (const edge of [SCREENSHOT_MAX_EDGE, 1280, 1024, 800, 640]) {
30445
+ const target = Math.min(edge, Math.max(sourceWidth, sourceHeight));
30446
+ for (const quality of [75, 60, 45, 35]) {
30447
+ await run("/usr/bin/sips", ["-Z", String(target), "-s", "format", "jpeg", "-s", "formatOptions", String(quality), full, "--out", small], signal);
30448
+ const data = await readFile6(small), size = jpegSize(data);
30449
+ if (!size) throw new ScreenCaptureError("SCREEN_UNAVAILABLE");
30450
+ if (data.length <= SCREENSHOT_MAX_JPEG_BYTES) return { data, ...size, sourceWidth, sourceHeight };
30451
+ }
30452
+ }
30453
+ throw new ScreenCaptureError("SCREENSHOT_TOO_LARGE");
30454
+ } catch (error62) {
30455
+ if (error62 instanceof ScreenCaptureError) throw error62;
30456
+ throw new ScreenCaptureError(signal.aborted ? "CANCELLED" : "SCREEN_UNAVAILABLE");
30457
+ } finally {
30458
+ await rm5(folder, { recursive: true, force: true }).catch(() => {
30459
+ });
30460
+ }
30461
+ }
30462
+ var SESSION_KEYS = ["DISPLAY", "WAYLAND_DISPLAY", "XAUTHORITY", "XDG_RUNTIME_DIR", "DBUS_SESSION_BUS_ADDRESS", "XDG_SESSION_TYPE", "XDG_CURRENT_DESKTOP"];
30463
+ var SESSION_VALUE = /^[A-Za-z0-9_.:,;=@+/-]{1,256}$/;
30464
+ var LINUX_SOURCE_BYTES = 150994944;
30465
+ async function linuxTool(name2) {
30466
+ for (const directory of ["/usr/bin", "/bin", "/usr/local/bin"]) {
30467
+ const file2 = path17.posix.join(directory, name2);
30468
+ try {
30469
+ await access3(file2, constants7.X_OK);
30470
+ return file2;
30471
+ } catch {
30472
+ }
30473
+ }
30474
+ return null;
30475
+ }
30476
+ async function linuxSession(signal) {
30477
+ const session = {}, uid = process.getuid?.();
30478
+ const take = (key, value) => {
30479
+ if (value && !session[key] && SESSION_VALUE.test(value)) session[key] = value;
30480
+ };
30481
+ const base = buildChildEnvironment(process.env, "linux");
30482
+ for (const key of SESSION_KEYS) take(key, process.env[key]);
30483
+ if (!session.DISPLAY && !session.WAYLAND_DISPLAY) {
30484
+ const systemctl = await linuxTool("systemctl");
30485
+ if (systemctl) try {
30486
+ const { stdout } = await run(systemctl, ["--user", "show-environment"], signal, 262144, base);
30487
+ for (const line of stdout.toString("utf8").split("\n")) {
30488
+ const at = line.indexOf("=");
30489
+ if (at > 0 && SESSION_KEYS.includes(line.slice(0, at))) take(line.slice(0, at), line.slice(at + 1));
30490
+ }
30491
+ } catch {
30492
+ if (signal.aborted) throw new ScreenCaptureError("CANCELLED");
30493
+ }
30494
+ }
30495
+ if (uid !== void 0) take("XDG_RUNTIME_DIR", "/run/user/" + uid);
30496
+ if (!session.DISPLAY && !session.WAYLAND_DISPLAY) {
30497
+ if (session.XDG_RUNTIME_DIR) for (const name2 of ["wayland-0", "wayland-1"]) {
30498
+ const socket = await lstat7(path17.posix.join(session.XDG_RUNTIME_DIR, name2)).catch(() => null);
30499
+ if (socket?.isSocket() && socket.uid === uid) {
30500
+ session.WAYLAND_DISPLAY = name2;
30501
+ break;
30502
+ }
30503
+ }
30504
+ if (!session.WAYLAND_DISPLAY) {
30505
+ const servers = [];
30506
+ for (const name2 of await readdir4("/tmp/.X11-unix").catch(() => [])) {
30507
+ const n = /^X(\d{1,4})$/.exec(name2)?.[1], socket = n ? await lstat7("/tmp/.X11-unix/" + name2).catch(() => null) : null;
30508
+ if (n && socket?.isSocket()) servers.push({ n: Number(n), own: socket.uid === uid });
30509
+ }
30510
+ const server = servers.sort((a, b) => Number(b.own) - Number(a.own) || a.n - b.n)[0];
30511
+ if (server) session.DISPLAY = ":" + server.n;
30512
+ }
30513
+ }
30514
+ if (session.DISPLAY && !session.XAUTHORITY) {
30515
+ const file2 = path17.posix.join(os4.homedir(), ".Xauthority");
30516
+ if ((await lstat7(file2).catch(() => null))?.isFile()) take("XAUTHORITY", file2);
30517
+ }
30518
+ if (session.XDG_RUNTIME_DIR) take("DBUS_SESSION_BUS_ADDRESS", "unix:path=" + session.XDG_RUNTIME_DIR + "/bus");
30519
+ const wayland = !!session.WAYLAND_DISPLAY || session.XDG_SESSION_TYPE === "wayland";
30520
+ return { env: { ...base, ...session }, wayland, x11: !wayland && !!session.DISPLAY };
30521
+ }
30522
+ async function busSocket(env) {
30523
+ const socket = sessionBusSocket(env.DBUS_SESSION_BUS_ADDRESS);
30524
+ if (!socket || socket.startsWith("\0")) return socket;
30525
+ return (await lstat7(socket).catch(() => null))?.isSocket() ? socket : null;
30526
+ }
30527
+ async function portalCapture(socket, signal) {
30528
+ const token = "lc" + randomBytes6(8).toString("hex"), started = Date.now(), uid = process.getuid?.();
30529
+ if (uid === void 0) throw new ScreenCaptureError("SCREEN_UNAVAILABLE");
30530
+ let answer;
30531
+ try {
30532
+ answer = await portalScreenshot(socket, uid, token, AbortSignal.any([signal, AbortSignal.timeout(3e4)]));
30533
+ } catch {
30534
+ throw new ScreenCaptureError(signal.aborted ? "CANCELLED" : "SCREEN_UNAVAILABLE");
30535
+ }
30536
+ const { code, uri } = answer;
30537
+ if (code === 1) throw new ScreenCaptureError("SCREEN_RECORDING_PERMISSION_REQUIRED");
30538
+ if (code !== 0 || !uri?.startsWith("file://")) throw new ScreenCaptureError("SCREEN_UNAVAILABLE");
30539
+ const file2 = decodeURIComponent(new URL(uri).pathname), info = await lstat7(file2);
30540
+ const fresh = info.isFile() && info.uid === uid && info.mtimeMs >= started - 5e3;
30541
+ try {
30542
+ if (!fresh || info.size > LINUX_SOURCE_BYTES) throw new ScreenCaptureError("SCREEN_UNAVAILABLE");
30543
+ return await readFile6(file2);
30544
+ } finally {
30545
+ if (fresh) await unlink2(file2).catch(() => {
30546
+ });
30547
+ }
30548
+ }
30549
+ async function linux(signal) {
30550
+ const session = await linuxSession(signal);
30551
+ if (!session.wayland && !session.x11) throw new ScreenCaptureError("SCREENSHOT_UNSUPPORTED", { reason: "NO_DISPLAY" });
30552
+ const output2 = (args) => async (tool) => (await run(tool, args, signal, LINUX_SOURCE_BYTES, session.env)).stdout;
30553
+ const portal = (socket) => portalCapture(socket, signal);
30554
+ const methods = session.wayland ? [["grim", "grim", output2(["-t", "png", "-"])], ["portal", "", portal]] : [
30555
+ ["xwd", "xwd", output2(["-root", "-silent"])],
30556
+ ["import", "import", output2(["-silent", "-window", "root", "png:-"])],
30557
+ ["maim", "maim", output2(["-f", "png"])],
30558
+ ["portal", "", portal]
30559
+ ];
30560
+ const tried = [];
30561
+ for (const [name2, program, capture2] of methods) {
30562
+ const tool = program ? await linuxTool(program) : await busSocket(session.env);
30563
+ if (!tool) {
30564
+ tried.push(name2 + ":missing");
30565
+ continue;
30566
+ }
30567
+ let image;
30568
+ try {
30569
+ const source = await capture2(tool);
30570
+ image = decodePng(source) ?? decodeXwd(source);
30571
+ } catch (error62) {
30572
+ if (signal.aborted) throw new ScreenCaptureError("CANCELLED");
30573
+ if (error62 instanceof ScreenCaptureError && error62.code === "SCREEN_RECORDING_PERMISSION_REQUIRED") throw error62;
30574
+ tried.push(name2 + ":failed");
30575
+ continue;
30576
+ }
30577
+ if (!image) {
30578
+ tried.push(name2 + ":unreadable");
30579
+ continue;
30580
+ }
30581
+ const fitted = fitJpeg(image, SCREENSHOT_MAX_EDGE, SCREENSHOT_MAX_JPEG_BYTES);
30582
+ if (!fitted) throw new ScreenCaptureError("SCREENSHOT_TOO_LARGE");
30583
+ return { ...fitted, sourceWidth: image.width, sourceHeight: image.height };
30584
+ }
30585
+ throw new ScreenCaptureError("SCREENSHOT_UNSUPPORTED", {
30586
+ reason: tried.every((entry) => entry.endsWith(":missing")) ? "NO_CAPTURE_TOOL" : "CAPTURE_FAILED",
30587
+ session: session.wayland ? "wayland" : "x11",
30588
+ tried
30589
+ });
30590
+ }
30591
+ async function captureScreen(options) {
30592
+ if (options.signal.aborted) throw new ScreenCaptureError("CANCELLED");
30593
+ if (process.platform === "win32") return windows(options.ownerBridgePath, options.signal);
30594
+ if (process.platform === "darwin") return mac3(options.signal);
30595
+ if (process.platform === "linux") return linux(options.signal);
30596
+ throw new ScreenCaptureError("SCREENSHOT_UNSUPPORTED", { reason: "PLATFORM_UNSUPPORTED" });
30597
+ }
30598
+
29325
30599
  // agent/src/tools.ts
29326
30600
  var NativeToolError = class extends Error {
29327
30601
  constructor(code) {
@@ -29352,7 +30626,7 @@ function stopped(signal) {
29352
30626
  if (signal.aborted) fail3("CANCELLED");
29353
30627
  }
29354
30628
  async function readBoundedFile(file2, maxBytes, bridge, signal) {
29355
- const stat2 = await lstat7(file2);
30629
+ const stat2 = await lstat8(file2);
29356
30630
  if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.size > maxBytes) fail3("FILE_UNSUPPORTED_OR_TOO_LARGE");
29357
30631
  if (process.platform === "win32") {
29358
30632
  if (maxBytes <= 1048576 || stat2.size <= 1048576) return readWindowsFile(bridge, file2, Math.min(maxBytes, 1048576), signal);
@@ -29360,7 +30634,7 @@ async function readBoundedFile(file2, maxBytes, bridge, signal) {
29360
30634
  if (read.truncated) fail3("FILE_UNSUPPORTED_OR_TOO_LARGE");
29361
30635
  return read.data;
29362
30636
  }
29363
- const handle = await open6(file2, constants7.O_RDONLY | (constants7.O_NOFOLLOW ?? 0));
30637
+ const handle = await open6(file2, constants8.O_RDONLY | (constants8.O_NOFOLLOW ?? 0));
29364
30638
  try {
29365
30639
  const current2 = await handle.stat();
29366
30640
  if (!current2.isFile() || current2.size > maxBytes) fail3("FILE_UNSUPPORTED_OR_TOO_LARGE");
@@ -29412,13 +30686,13 @@ var NativeTools = class {
29412
30686
  constructor(options) {
29413
30687
  this.options = options;
29414
30688
  this.options = structuredClone(options);
29415
- this.memory = new HostMemory(path17.join(options.stateDirectory, "host-memory.json"), Object.keys(options.programs), Object.fromEntries(Object.entries(options.programs).map(([name2, program]) => [name2, program.executable])));
30689
+ this.memory = new HostMemory(path18.join(options.stateDirectory, "host-memory.json"), Object.keys(options.programs), Object.fromEntries(Object.entries(options.programs).map(([name2, program]) => [name2, program.executable])));
29416
30690
  }
29417
30691
  options;
29418
30692
  memory;
29419
30693
  async readFile(file2, maxBytes, signal) {
29420
30694
  try {
29421
- return await readBoundedFile(file2, maxBytes, this.options.ownerBridgePath ?? path17.join(path17.dirname(this.options.helperPath), "OwnerBridge.exe"), signal);
30695
+ return await readBoundedFile(file2, maxBytes, this.options.ownerBridgePath ?? path18.join(path18.dirname(this.options.helperPath), "OwnerBridge.exe"), signal);
29422
30696
  } catch (error62) {
29423
30697
  if (error62.code === "ENOENT") throw error62;
29424
30698
  if (error62 instanceof Error && /^[A-Z_]{1,40}$/.test(error62.message)) fail3(error62.message);
@@ -29428,31 +30702,31 @@ var NativeTools = class {
29428
30702
  /** Windows only: up to 64 files of at most 1 MiB in one bridge process, each with its own result. */
29429
30703
  async readFiles(files, maxTotalBytes, signal) {
29430
30704
  try {
29431
- return await readWindowsFiles(this.options.ownerBridgePath ?? path17.join(path17.dirname(this.options.helperPath), "OwnerBridge.exe"), files, 1048576, maxTotalBytes, signal);
30705
+ return await readWindowsFiles(this.options.ownerBridgePath ?? path18.join(path18.dirname(this.options.helperPath), "OwnerBridge.exe"), files, 1048576, maxTotalBytes, signal);
29432
30706
  } catch (error62) {
29433
30707
  if (error62 instanceof Error && /^[A-Z_]{1,40}$/.test(error62.message)) fail3(error62.message);
29434
30708
  throw error62;
29435
30709
  }
29436
30710
  }
29437
- async prepare(workspace2, candidate, selection) {
30711
+ async prepare(workspace2, candidate, selection2) {
29438
30712
  let prepared;
29439
30713
  try {
29440
30714
  let projectRoot;
29441
- if (selection) {
29442
- const target = ProjectTargetBindingSchema.parse(selection);
30715
+ if (selection2) {
30716
+ const target = ProjectTargetBindingSchema.parse(selection2);
29443
30717
  if (workspace2.rootHash !== target.workspaceRootHash) fail3("PROJECT_IDENTITY_MISMATCH");
29444
30718
  const identity = await this.prepareTool(workspace2, { name: "project_identity", args: { path: target.relativePath } });
29445
30719
  const proof2 = JSON.parse((await identity.run(AbortSignal.timeout(15e3))).stdout);
29446
30720
  if (!proof2.repositoryFingerprint) fail3("PROJECT_IDENTITY_UNKNOWN");
29447
30721
  if (proof2.repositoryFingerprint !== target.repositoryFingerprint) fail3("PROJECT_IDENTITY_MISMATCH");
29448
- projectRoot = path17.resolve(workspace2.root, target.relativePath);
30722
+ projectRoot = path18.resolve(workspace2.root, target.relativePath);
29449
30723
  const common = identity.claims.find((claim2) => claim2.namespace === "git")?.path;
29450
30724
  if (common) workspace2 = { ...workspace2, gitCommonDir: common };
29451
30725
  }
29452
30726
  prepared = await this.prepareTool(workspace2, candidate, projectRoot);
29453
30727
  } catch (error62) {
29454
30728
  const parsed = ToolCallSchema.safeParse(candidate);
29455
- if (parsed.success && parsed.data.name === "command_run") await this.memory.record({ ...parsed.data.args, cwd: path17.resolve(workspace2.root, parsed.data.args.cwd ?? ".") }, void 0, error62).catch(() => {
30729
+ if (parsed.success && parsed.data.name === "command_run") await this.memory.record({ ...parsed.data.args, cwd: path18.resolve(workspace2.root, parsed.data.args.cwd ?? ".") }, void 0, error62).catch(() => {
29456
30730
  });
29457
30731
  throw error62;
29458
30732
  }
@@ -29472,17 +30746,17 @@ var NativeTools = class {
29472
30746
  try {
29473
30747
  const canonical2 = await realpath7(workspace2.root);
29474
30748
  if (!equalPath3(canonical2, workspace2.root) || hash6(process.platform === "win32" ? canonical2.toLowerCase() : canonical2) !== workspace2.rootHash) fail3("WORKSPACE_CHANGED");
29475
- const runtimeDirectory = path17.dirname(this.options.helperPath);
30749
+ const runtimeDirectory = path18.dirname(this.options.helperPath);
29476
30750
  const protectedPaths = [
29477
30751
  this.options.stateDirectory,
29478
30752
  this.options.helperPath,
29479
- ...["agent.mjs", "node.exe", "OwnerBridge.exe", "LocalCommanderAgent.exe", "node", "owner-store", "posix-host", "job-host.mjs", "lifecycle.mjs", "manifest.json"].map((name2) => path17.join(runtimeDirectory, name2))
30753
+ ...["agent.mjs", "node.exe", "OwnerBridge.exe", "LocalCommanderAgent.exe", "node", "owner-store", "posix-host", "job-host.mjs", "lifecycle.mjs", "manifest.json"].map((name2) => path18.join(runtimeDirectory, name2))
29480
30754
  ];
29481
30755
  if (this.options.ownerBridgePath) protectedPaths.push(this.options.ownerBridgePath);
29482
- if (process.platform === "win32" && process.env.LOCALAPPDATA && path17.isAbsolute(process.env.LOCALAPPDATA)) {
29483
- protectedPaths.push(path17.join(process.env.LOCALAPPDATA, "LocalCommander"));
30756
+ if (process.platform === "win32" && process.env.LOCALAPPDATA && path18.isAbsolute(process.env.LOCALAPPDATA)) {
30757
+ protectedPaths.push(path18.join(process.env.LOCALAPPDATA, "LocalCommander"));
29484
30758
  }
29485
- if (process.platform !== "win32") protectedPaths.push(path17.join(process.env.LC_AGENT_DATA_DIR || posixDataHome(), "LocalCommander"));
30759
+ if (process.platform !== "win32") protectedPaths.push(path18.join(process.env.LC_AGENT_DATA_DIR || posixDataHome(), "LocalCommander"));
29486
30760
  guard = await PathGuard.create([canonical2], false, { protectedPaths });
29487
30761
  if (projectRoot) {
29488
30762
  const selected = await guard.resolveDirectory(projectRoot);
@@ -29571,7 +30845,7 @@ var NativeTools = class {
29571
30845
  }
29572
30846
  if (taken === first - 1 && first <= end) fail3("OUTPUT_LIMIT_EXCEEDED");
29573
30847
  const remaining = lines.length - (lines.length > 1 && lines.at(-1) === "" ? 1 : 0);
29574
- return result({ path: path17.relative(workspace2.root, filename), sha256: hash6(bytes3), startLine: first, endLine: Math.min(taken === first - 1 ? last : taken, lines.length), totalLines: lines.length, content: lines.slice(first - 1, taken).join("\n"), truncated: taken < remaining });
30848
+ return result({ path: path18.relative(workspace2.root, filename), sha256: hash6(bytes3), startLine: first, endLine: Math.min(taken === first - 1 ? last : taken, lines.length), totalLines: lines.length, content: lines.slice(first - 1, taken).join("\n"), truncated: taken < remaining });
29575
30849
  } };
29576
30850
  }
29577
30851
  if (call.name === "fs_write" || call.name === "fs_replace") {
@@ -29614,8 +30888,8 @@ var NativeTools = class {
29614
30888
  bytes3 = encodeText(pieces.join(newText), original.encoding);
29615
30889
  }
29616
30890
  if (bytes3.length > MAX_FILE_WRITE_BYTES) fail3("FILE_WRITE_LIMIT");
29617
- const temp = path17.join(path17.dirname(target), ".lc-write-" + randomUUID7() + ".tmp");
29618
- const handle = await open6(temp, constants7.O_CREAT | constants7.O_EXCL | constants7.O_WRONLY, 384);
30891
+ const temp = path18.join(path18.dirname(target), ".lc-write-" + randomUUID7() + ".tmp");
30892
+ const handle = await open6(temp, constants8.O_CREAT | constants8.O_EXCL | constants8.O_WRONLY, 384);
29619
30893
  try {
29620
30894
  await handle.writeFile(bytes3);
29621
30895
  await handle.sync();
@@ -29631,7 +30905,7 @@ var NativeTools = class {
29631
30905
  break;
29632
30906
  } catch (error62) {
29633
30907
  if (process.platform !== "win32" || !["EPERM", "EBUSY", "EACCES"].includes(error62.code ?? "")) throw error62;
29634
- if (attempt === 4) fail3((await lstat7(target)).mode & 128 ? "FILE_IN_USE" : "FILE_READ_ONLY");
30908
+ if (attempt === 4) fail3((await lstat8(target)).mode & 128 ? "FILE_IN_USE" : "FILE_READ_ONLY");
29635
30909
  await delay2(50 << attempt);
29636
30910
  stopped(signal);
29637
30911
  }
@@ -29646,18 +30920,18 @@ var NativeTools = class {
29646
30920
  }
29647
30921
  for (let attempt = 0; attempt < 3; attempt++) {
29648
30922
  try {
29649
- await rm5(temp);
30923
+ await rm6(temp);
29650
30924
  break;
29651
30925
  } catch {
29652
30926
  await delay2(100);
29653
30927
  }
29654
30928
  }
29655
30929
  }
29656
- return result({ path: path17.relative(workspace2.root, target), bytes: bytes3.length, sha256: hash6(bytes3), ...call.name === "fs_replace" ? { replacements } : {} });
30930
+ return result({ path: path18.relative(workspace2.root, target), bytes: bytes3.length, sha256: hash6(bytes3), ...call.name === "fs_replace" ? { replacements } : {} });
29657
30931
  } catch (e) {
29658
30932
  await handle.close().catch(() => {
29659
30933
  });
29660
- await rm5(temp, { force: true }).catch(() => {
30934
+ await rm6(temp, { force: true }).catch(() => {
29661
30935
  });
29662
30936
  throw e;
29663
30937
  }
@@ -29679,7 +30953,7 @@ var NativeTools = class {
29679
30953
  const lines = decodeText(bytes3).text.split(/\r?\n/);
29680
30954
  scanned++;
29681
30955
  for (let i = 0; i < lines.length && matches2.length < call.args.maxResults; i++) if ((call.args.caseSensitive ? lines[i] : lines[i].toLowerCase()).includes(query)) {
29682
- const match = { path: path17.relative(workspace2.root, filename), line: i + 1, text: lines[i].slice(0, 500) };
30956
+ const match = { path: path18.relative(workspace2.root, filename), line: i + 1, text: lines[i].slice(0, 500) };
29683
30957
  if ((room -= Buffer.byteLength(JSON.stringify(match)) + 1) < 0) {
29684
30958
  incomplete = true;
29685
30959
  break;
@@ -29722,7 +30996,7 @@ var NativeTools = class {
29722
30996
  continue;
29723
30997
  }
29724
30998
  try {
29725
- const filename = await guard.resolveExisting(path17.join(base, entry.path));
30999
+ const filename = await guard.resolveExisting(path18.join(base, entry.path));
29726
31000
  guard.assertSafeFile(filename);
29727
31001
  if (!batched) {
29728
31002
  searchFile(filename, await this.readFile(filename, 1048576, signal));
@@ -29746,6 +31020,42 @@ var NativeTools = class {
29746
31020
  return result({ matches: matches2, scannedFiles: scanned, truncated: listing.truncated || incomplete || matches2.length >= call.args.maxResults || scanned >= 300 });
29747
31021
  } };
29748
31022
  }
31023
+ if (call.name === "take_screenshot") {
31024
+ if (!screenshotEnabled() && !await lstat8(path18.join(this.options.stateDirectory, SCREENSHOT_ACCEPTANCE_FILE)).then((s) => s.isFile(), () => false)) fail3("SCREENSHOT_DISABLED");
31025
+ if (!workspace2.fullAccess) fail3("FULL_ACCESS_REQUIRED");
31026
+ if (await lstat8(path18.join(this.options.stateDirectory, SCREENSHOT_OWNER_OFF_FILE)).then(() => true, (error62) => error62.code !== "ENOENT")) fail3("SCREENSHOT_DISABLED_BY_OWNER");
31027
+ const bridge = this.options.ownerBridgePath ?? path18.join(path18.dirname(this.options.helperPath), "OwnerBridge.exe");
31028
+ return { call, claims: [{ path: path18.join(this.options.stateDirectory, "screen-capture"), mode: "read" }], run: async (signal) => {
31029
+ let shot;
31030
+ try {
31031
+ shot = await captureScreen({ ownerBridgePath: bridge, signal });
31032
+ } catch (error62) {
31033
+ if (error62 instanceof ScreenCaptureError && error62.detail) return {
31034
+ exitCode: 1,
31035
+ timedOut: false,
31036
+ cancelled: false,
31037
+ treeTerminated: true,
31038
+ stdout: JSON.stringify({ type: "screenshot_error", resultCode: error62.code, ...error62.detail }),
31039
+ stderr: "",
31040
+ stdoutTruncated: false,
31041
+ stderrTruncated: false,
31042
+ resultCode: error62.code
31043
+ };
31044
+ fail3(error62 instanceof Error && /^[A-Z_]{1,40}$/.test(error62.message) ? error62.message : "SCREEN_UNAVAILABLE");
31045
+ }
31046
+ return result({
31047
+ type: "screenshot",
31048
+ mimeType: "image/jpeg",
31049
+ width: shot.width,
31050
+ height: shot.height,
31051
+ sourceWidth: shot.sourceWidth,
31052
+ sourceHeight: shot.sourceHeight,
31053
+ bytes: shot.data.length,
31054
+ capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
31055
+ data: shot.data.toString("base64")
31056
+ });
31057
+ } };
31058
+ }
29749
31059
  if (call.name === "localhost_request") {
29750
31060
  const url2 = new URL(call.args.url), port = Number(url2.port || (url2.protocol === "https:" ? 443 : 80));
29751
31061
  if (!["http:", "https:"].includes(url2.protocol) || !["localhost", "127.0.0.1", "[::1]"].includes(url2.hostname) || url2.username || url2.password || url2.hash || (workspace2.fullAccess ? workspace2.deniedLocalhostPorts?.includes(port) : !workspace2.localhostPorts.includes(port)) || this.options.protectedPorts?.includes(port)) fail3("LOCALHOST_NOT_ALLOWED");
@@ -29816,9 +31126,9 @@ var NativeTools = class {
29816
31126
  else if (call.name === "git_diff") {
29817
31127
  argv = ["diff", "--no-ext-diff", "--no-textconv", ...call.args.staged ? ["--cached"] : []];
29818
31128
  if (call.args.file) {
29819
- const file2 = await resolve(path17.resolve(cwd, call.args.file));
29820
- const relative = path17.relative(cwd, file2);
29821
- if (relative.startsWith(".." + path17.sep) || relative === ".." || path17.isAbsolute(relative)) fail3("PATH_NOT_ALLOWED");
31129
+ const file2 = await resolve(path18.resolve(cwd, call.args.file));
31130
+ const relative = path18.relative(cwd, file2);
31131
+ if (relative.startsWith(".." + path18.sep) || relative === ".." || path18.isAbsolute(relative)) fail3("PATH_NOT_ALLOWED");
29822
31132
  argv.push("--", relative);
29823
31133
  } else argv.push("--stat");
29824
31134
  } else fail3("TOOL_MISSING");
@@ -29829,7 +31139,7 @@ var NativeTools = class {
29829
31139
  const listing = await this.list(guard, cwd, 1, call.args.startup ? 20 : 150, signal);
29830
31140
  let packageInfo = null;
29831
31141
  try {
29832
- const name2 = await guard.resolveExisting(path17.join(cwd, "package.json"));
31142
+ const name2 = await guard.resolveExisting(path18.join(cwd, "package.json"));
29833
31143
  guard.assertSafeFile(name2);
29834
31144
  const value = JSON.parse(utf8(await this.readFile(name2, 64e3, signal)));
29835
31145
  packageInfo = { name: typeof value.name === "string" ? value.name : null, version: typeof value.version === "string" ? value.version : null, scripts: value.scripts && typeof value.scripts === "object" ? Object.keys(value.scripts).slice(0, 100) : [] };
@@ -29849,7 +31159,7 @@ var NativeTools = class {
29849
31159
  }
29850
31160
  const contextFile = async (relative, limit, optional2 = false) => {
29851
31161
  try {
29852
- const file2 = await guard.resolveExisting(path17.join(primary, relative));
31162
+ const file2 = await guard.resolveExisting(path18.join(primary, relative));
29853
31163
  guard.assertSafeFile(file2);
29854
31164
  return utf8(await this.readFile(file2, limit, signal));
29855
31165
  } catch (error62) {
@@ -29882,19 +31192,19 @@ var NativeTools = class {
29882
31192
  } };
29883
31193
  }
29884
31194
  async resolveProgram(name2, workspace2, args) {
29885
- const entry = Object.entries(this.options.programs).find(([key, value]) => equalPath3(key, name2) || path17.isAbsolute(name2) && equalPath3(value.executable, path17.resolve(name2)));
31195
+ const entry = Object.entries(this.options.programs).find(([key, value]) => equalPath3(key, name2) || path18.isAbsolute(name2) && equalPath3(value.executable, path18.resolve(name2)));
29886
31196
  if (workspace2.fullAccess) {
29887
- const commandKey = (value) => process.platform === "win32" ? path17.basename(value).toLowerCase().replace(/\.(exe|com|cmd|bat)$/i, "") : path17.basename(value);
31197
+ const commandKey = (value) => process.platform === "win32" ? path18.basename(value).toLowerCase().replace(/\.(exe|com|cmd|bat)$/i, "") : path18.basename(value);
29888
31198
  const denied = new Set((workspace2.deniedCommands ?? []).map(commandKey));
29889
31199
  if (denied.has(commandKey(name2)) || entry && denied.has(commandKey(entry[0]))) fail3("COMMAND_NOT_ALLOWED");
29890
- const extension2 = path17.extname(name2).toLowerCase();
29891
- const candidate = entry?.[1].executable ?? (process.platform !== "win32" ? await resolvePosixExecutable(name2) : path17.isAbsolute(name2) ? name2 : /^[\w.-]+$/.test(name2) ? resolveWindowsLauncher(
31200
+ const extension2 = path18.extname(name2).toLowerCase();
31201
+ const candidate = entry?.[1].executable ?? (process.platform !== "win32" ? await resolvePosixExecutable(name2) : path18.isAbsolute(name2) ? name2 : /^[\w.-]+$/.test(name2) ? resolveWindowsLauncher(
29892
31202
  commandKey(name2),
29893
31203
  [".exe", ".com", ".cmd", ".bat"].includes(extension2) ? { ...process.env, PATHEXT: extension2 } : process.env
29894
31204
  )?.file : void 0);
29895
- if (!candidate || !path17.isAbsolute(candidate)) fail3("COMMAND_NOT_FOUND");
31205
+ if (!candidate || !path18.isAbsolute(candidate)) fail3("COMMAND_NOT_FOUND");
29896
31206
  const executable = await realpath7(candidate).catch(() => fail3("COMMAND_NOT_FOUND"));
29897
- if (!(await lstat7(executable)).isFile()) fail3("COMMAND_NOT_FOUND");
31207
+ if (!(await lstat8(executable)).isFile()) fail3("COMMAND_NOT_FOUND");
29898
31208
  if (denied.has(commandKey(executable))) fail3("COMMAND_NOT_ALLOWED");
29899
31209
  for (const key of workspace2.deniedCommands ?? []) {
29900
31210
  const configured = this.options.programs[key]?.executable;
@@ -29907,7 +31217,7 @@ var NativeTools = class {
29907
31217
  if (/\.(cmd|bat)$/i.test(executable)) {
29908
31218
  if ([executable, ...args].some((value) => /[&|<>^%!"\r\n]/.test(value))) fail3("INVALID_SCRIPT_ARGUMENTS");
29909
31219
  const literal2 = (value) => "'" + value.replaceAll("'", "''") + "'";
29910
- const shell = path17.join(process.env.SystemRoot ?? "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
31220
+ const shell = path18.join(process.env.SystemRoot ?? "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
29911
31221
  if (denied.has("powershell") || denied.has("cmd")) fail3("COMMAND_NOT_ALLOWED");
29912
31222
  const script = "& " + literal2(executable) + " @(" + args.map(literal2).join(",") + "); exit $LASTEXITCODE";
29913
31223
  return { executable: shell, args: ["-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(script, "utf16le").toString("base64")] };
@@ -29915,7 +31225,7 @@ var NativeTools = class {
29915
31225
  if (!/\.(exe|com)$/i.test(executable)) fail3("COMMAND_NOT_ALLOWED");
29916
31226
  return { executable, args: [...entry?.[1].prefixArgs ?? [], ...args] };
29917
31227
  }
29918
- if (!entry || !workspace2.allowedCommands.some((v) => equalPath3(v, entry[0])) || !path17.isAbsolute(entry[1].executable)) fail3("COMMAND_NOT_ALLOWED");
31228
+ if (!entry || !workspace2.allowedCommands.some((v) => equalPath3(v, entry[0])) || !path18.isAbsolute(entry[1].executable)) fail3("COMMAND_NOT_ALLOWED");
29919
31229
  return { executable: entry[1].executable, args: [...entry[1].prefixArgs ?? [], ...args] };
29920
31230
  }
29921
31231
  async memoryContext(workspace2) {
@@ -29930,13 +31240,13 @@ var NativeTools = class {
29930
31240
  async gitExecution(cwd, args) {
29931
31241
  if (!["win32", "linux", "darwin"].includes(process.platform)) fail3("COMMAND_NOT_ALLOWED");
29932
31242
  const configured = this.options.programs.git;
29933
- const candidates = configured ? [configured.executable] : process.platform === "win32" ? [[process.env.ProgramFiles, "Git"], [process.env["ProgramFiles(x86)"], "Git"], [process.env.LOCALAPPDATA, "Programs/Git"]].filter(([root]) => root && path17.isAbsolute(root)).map(([root, suffix]) => path17.join(root, suffix, "cmd", "git.exe")) : ["/usr/bin/git", "/usr/local/bin/git", "/opt/homebrew/bin/git"];
31243
+ const candidates = configured ? [configured.executable] : process.platform === "win32" ? [[process.env.ProgramFiles, "Git"], [process.env["ProgramFiles(x86)"], "Git"], [process.env.LOCALAPPDATA, "Programs/Git"]].filter(([root]) => root && path18.isAbsolute(root)).map(([root, suffix]) => path18.join(root, suffix, "cmd", "git.exe")) : ["/usr/bin/git", "/usr/local/bin/git", "/opt/homebrew/bin/git"];
29934
31244
  for (const source of candidates) {
29935
- if (!path17.isAbsolute(source)) continue;
31245
+ if (!path18.isAbsolute(source)) continue;
29936
31246
  const candidate = process.platform === "win32" ? source : await resolvePosixExecutable(source);
29937
31247
  if (!candidate) continue;
29938
31248
  try {
29939
- const stat2 = await lstat7(candidate);
31249
+ const stat2 = await lstat8(candidate);
29940
31250
  if (!stat2.isFile() || stat2.isSymbolicLink() || !equalPath3(candidate, await realpath7(candidate))) continue;
29941
31251
  } catch {
29942
31252
  continue;
@@ -29954,7 +31264,7 @@ var NativeTools = class {
29954
31264
  const current2 = queue.shift();
29955
31265
  let names;
29956
31266
  try {
29957
- names = await readdir4(current2.path, { withFileTypes: true });
31267
+ names = await readdir5(current2.path, { withFileTypes: true });
29958
31268
  } catch (error62) {
29959
31269
  if (current2.level === 0) throw error62;
29960
31270
  continue;
@@ -29966,7 +31276,7 @@ var NativeTools = class {
29966
31276
  break;
29967
31277
  }
29968
31278
  if (item.isSymbolicLink() || excluded.has(item.name.toLowerCase())) continue;
29969
- const candidate = path17.join(current2.path, item.name);
31279
+ const candidate = path18.join(current2.path, item.name);
29970
31280
  let resolved;
29971
31281
  try {
29972
31282
  resolved = await guard.resolveExisting(candidate);
@@ -29976,11 +31286,11 @@ var NativeTools = class {
29976
31286
  }
29977
31287
  if (!equalPath3(candidate, resolved)) continue;
29978
31288
  if (item.isDirectory()) {
29979
- entries.push({ path: path17.relative(root, resolved), type: "directory" });
31289
+ entries.push({ path: path18.relative(root, resolved), type: "directory" });
29980
31290
  if (current2.level < depth) queue.push({ path: resolved, level: current2.level + 1 });
29981
31291
  } else if (item.isFile()) {
29982
- const stat2 = await lstat7(resolved).catch(() => null);
29983
- if (stat2) entries.push({ path: path17.relative(root, resolved), type: "file", size: stat2.size });
31292
+ const stat2 = await lstat8(resolved).catch(() => null);
31293
+ if (stat2) entries.push({ path: path18.relative(root, resolved), type: "file", size: stat2.size });
29984
31294
  }
29985
31295
  }
29986
31296
  if (truncated) break;
@@ -29990,49 +31300,49 @@ var NativeTools = class {
29990
31300
  async gitCommonDir(cwd, workspace2, guard) {
29991
31301
  let directory = cwd;
29992
31302
  while (guard.isWithin(directory, workspace2.root)) {
29993
- const dotGit = path17.join(directory, ".git");
31303
+ const dotGit = path18.join(directory, ".git");
29994
31304
  try {
29995
- const stat2 = await lstat7(dotGit);
31305
+ const stat2 = await lstat8(dotGit);
29996
31306
  if (stat2.isSymbolicLink()) fail3("GIT_METADATA_CHANGED");
29997
31307
  let gitDir;
29998
31308
  if (stat2.isDirectory()) gitDir = await realpath7(dotGit);
29999
31309
  else {
30000
31310
  const content = utf8(await this.readFile(dotGit, 4096)).trim();
30001
31311
  if (!content.startsWith("gitdir: ")) fail3("GIT_METADATA_CHANGED");
30002
- gitDir = await realpath7(path17.resolve(directory, content.slice(8)));
31312
+ gitDir = await realpath7(path18.resolve(directory, content.slice(8)));
30003
31313
  }
30004
31314
  if (guard.isWithin(gitDir, this.options.stateDirectory) || !guard.isWithin(gitDir, workspace2.root) && (!workspace2.gitCommonDir || !guard.isWithin(gitDir, workspace2.gitCommonDir))) fail3("GIT_COMMON_DIRECTORY_NOT_APPROVED");
30005
31315
  let common = gitDir;
30006
31316
  try {
30007
- const content = utf8(await this.readFile(path17.join(gitDir, "commondir"), 4096)).trim();
31317
+ const content = utf8(await this.readFile(path18.join(gitDir, "commondir"), 4096)).trim();
30008
31318
  if (!content) fail3("GIT_METADATA_CHANGED");
30009
- common = await realpath7(path17.resolve(gitDir, content));
31319
+ common = await realpath7(path18.resolve(gitDir, content));
30010
31320
  } catch (e) {
30011
31321
  if (e.code !== "ENOENT") throw e;
30012
31322
  }
30013
- if (!(await lstat7(common)).isDirectory() || guard.isWithin(common, this.options.stateDirectory)) fail3("GIT_METADATA_CHANGED");
31323
+ if (!(await lstat8(common)).isDirectory() || guard.isWithin(common, this.options.stateDirectory)) fail3("GIT_METADATA_CHANGED");
30014
31324
  if (!guard.isWithin(common, workspace2.root) && (!workspace2.gitCommonDir || !equalPath3(common, workspace2.gitCommonDir))) fail3("GIT_COMMON_DIRECTORY_NOT_APPROVED");
30015
31325
  return common;
30016
31326
  } catch (e) {
30017
31327
  if (e.code !== "ENOENT") throw e;
30018
31328
  }
30019
31329
  if (equalPath3(directory, workspace2.root)) break;
30020
- directory = path17.dirname(directory);
31330
+ directory = path18.dirname(directory);
30021
31331
  }
30022
31332
  return null;
30023
31333
  }
30024
31334
  };
30025
31335
 
30026
31336
  // agent/src/scheduler.ts
30027
- import path18 from "node:path";
30028
- import os4 from "node:os";
31337
+ import path19 from "node:path";
31338
+ import os5 from "node:os";
30029
31339
  function canonical(value) {
30030
- const p = path18.resolve(value);
31340
+ const p = path19.resolve(value);
30031
31341
  return process.platform === "win32" ? p.toLowerCase() : p;
30032
31342
  }
30033
31343
  function ancestor(a, b) {
30034
- const relative = path18.relative(a, b);
30035
- return relative === "" || !path18.isAbsolute(relative) && relative !== ".." && !relative.startsWith(".." + path18.sep);
31344
+ const relative = path19.relative(a, b);
31345
+ return relative === "" || !path19.isAbsolute(relative) && relative !== ".." && !relative.startsWith(".." + path19.sep);
30036
31346
  }
30037
31347
  function claimsConflict(a, b) {
30038
31348
  return a.some((x) => b.some((y) => (x.namespace ?? "filesystem") === (y.namespace ?? "filesystem") && (x.mode === "write" || y.mode === "write") && (ancestor(x.path, y.path) || ancestor(y.path, x.path))));
@@ -30040,7 +31350,7 @@ function claimsConflict(a, b) {
30040
31350
  var NativeScheduler = class {
30041
31351
  constructor(options = {}) {
30042
31352
  this.options = options;
30043
- const capacity = Math.max(1, Math.min(16, Math.floor(Math.max(2, os4.availableParallelism?.() ?? os4.cpus().length) / 2)));
31353
+ const capacity = Math.max(1, Math.min(16, Math.floor(Math.max(2, os5.availableParallelism?.() ?? os5.cpus().length) / 2)));
30044
31354
  this.safeSlots = options.safeSlots ?? capacity;
30045
31355
  this.maxQueued = options.maxQueued ?? 32;
30046
31356
  if (!Number.isInteger(this.safeSlots) || this.safeSlots < 1 || this.safeSlots > 32 || !Number.isInteger(this.maxQueued) || this.maxQueued < 1 || this.maxQueued > 256) throw Error("INVALID_SCHEDULER_LIMIT");
@@ -30058,16 +31368,16 @@ var NativeScheduler = class {
30058
31368
  } catch {
30059
31369
  }
30060
31370
  }
30061
- schedule(id2, claims, deadlineAt, run, signal) {
31371
+ schedule(id2, claims, deadlineAt, run2, signal) {
30062
31372
  if (!this.accepting) return Promise.reject(Error("AGENT_PAUSED"));
30063
31373
  if (!id2 || id2.length > 100 || this.active.has(id2) || this.waiting.some((j) => j.id === id2)) return Promise.reject(Error("DUPLICATE_SCHEDULED_EXECUTION"));
30064
- if (!Array.isArray(claims) || !claims.length || claims.length > 32 || claims.some((c) => !c || !path18.isAbsolute(c.path) || !["read", "write"].includes(c.mode))) return Promise.reject(Error("INVALID_RESOURCE_CLAIM"));
31374
+ if (!Array.isArray(claims) || !claims.length || claims.length > 32 || claims.some((c) => !c || !path19.isAbsolute(c.path) || !["read", "write"].includes(c.mode))) return Promise.reject(Error("INVALID_RESOURCE_CLAIM"));
30065
31375
  const deadline = deadlineAt.getTime();
30066
31376
  if (!Number.isFinite(deadline) || deadline <= Date.now()) return Promise.reject(Error("ADMISSION_DEADLINE_EXPIRED"));
30067
31377
  if (signal?.aborted) return Promise.reject(Error("CANCELLED_BEFORE_ACCEPTANCE"));
30068
31378
  if (this.waiting.length >= this.maxQueued) return Promise.reject(Error("RESOURCE_BUSY"));
30069
31379
  return new Promise((resolve, reject) => {
30070
- const job = { id: id2, claims: claims.map((c) => ({ ...c, path: canonical(c.path) })), deadline, run, signal, resolve, reject };
31380
+ const job = { id: id2, claims: claims.map((c) => ({ ...c, path: canonical(c.path) })), deadline, run: run2, signal, resolve, reject };
30071
31381
  const remove = (reason) => {
30072
31382
  const index = this.waiting.indexOf(job);
30073
31383
  if (index < 0) return;
@@ -30766,7 +32076,45 @@ function journalBinding(entry, binding2) {
30766
32076
  function journalResult(value, code) {
30767
32077
  return { ...value, resultCode: code ?? (value.treeTerminated ? value.cancelled ? "CANCELLED" : value.timedOut ? "TIMEOUT" : value.exitCode === 0 ? "SUCCESS" : "USER_PROGRAM_FAILED" : "EXECUTION_UNKNOWN") };
30768
32078
  }
30769
- var knownCodes = /* @__PURE__ */ new Set(["PROJECT_IDENTITY_UNKNOWN", "PROJECT_IDENTITY_MISMATCH", "INVALID_TOOL_ARGUMENTS", "LOCAL_PERMISSION_REQUIRED", "PATH_NOT_ALLOWED", "FILE_CHANGED", "FILE_NOT_FOUND", "FILE_ALREADY_EXISTS", "REPLACEMENT_NOT_UNIQUE", "OUTPUT_LIMIT_EXCEEDED", "BINARY_FILE_NOT_SUPPORTED", "FILE_UNSUPPORTED_OR_TOO_LARGE", "INVALID_LINE_RANGE", "FILE_IN_USE", "FILE_READ_ONLY", "FILE_WRITE_LIMIT", "GIT_METADATA_CHANGED", "GIT_COMMON_DIRECTORY_NOT_APPROVED", "GIT_NOT_INSTALLED", "LOCALHOST_NOT_ALLOWED", "COMMAND_NOT_ALLOWED", "WORKSPACE_CHANGED", "WORKSPACE_UNAVAILABLE", "RESOURCE_BUSY", "AGENT_PAUSED", "CANCELLED_BEFORE_ACCEPTANCE", "ADMISSION_DEADLINE_EXPIRED"]);
32079
+ var knownCodes = /* @__PURE__ */ new Set([
32080
+ "PROJECT_IDENTITY_UNKNOWN",
32081
+ "PROJECT_IDENTITY_MISMATCH",
32082
+ "INVALID_TOOL_ARGUMENTS",
32083
+ "LOCAL_PERMISSION_REQUIRED",
32084
+ "PATH_NOT_ALLOWED",
32085
+ "FILE_CHANGED",
32086
+ "FILE_NOT_FOUND",
32087
+ "FILE_ALREADY_EXISTS",
32088
+ "REPLACEMENT_NOT_UNIQUE",
32089
+ "OUTPUT_LIMIT_EXCEEDED",
32090
+ "BINARY_FILE_NOT_SUPPORTED",
32091
+ "FILE_UNSUPPORTED_OR_TOO_LARGE",
32092
+ "INVALID_LINE_RANGE",
32093
+ "FILE_IN_USE",
32094
+ "FILE_READ_ONLY",
32095
+ "FILE_WRITE_LIMIT",
32096
+ "GIT_METADATA_CHANGED",
32097
+ "GIT_COMMON_DIRECTORY_NOT_APPROVED",
32098
+ "GIT_NOT_INSTALLED",
32099
+ "LOCALHOST_NOT_ALLOWED",
32100
+ "COMMAND_NOT_ALLOWED",
32101
+ "WORKSPACE_CHANGED",
32102
+ "WORKSPACE_UNAVAILABLE",
32103
+ "RESOURCE_BUSY",
32104
+ "AGENT_PAUSED",
32105
+ "CANCELLED_BEFORE_ACCEPTANCE",
32106
+ "ADMISSION_DEADLINE_EXPIRED",
32107
+ // take_screenshot refusals (#434, #486): without these the client sees TOOL_FAILED.
32108
+ "FULL_ACCESS_REQUIRED",
32109
+ "SCREENSHOT_DISABLED",
32110
+ "SCREENSHOT_DISABLED_BY_OWNER",
32111
+ "SCREENSHOT_UNSUPPORTED",
32112
+ "SCREENSHOT_TOO_LARGE",
32113
+ "SCREEN_UNAVAILABLE",
32114
+ "SCREEN_LOCKED",
32115
+ "SCREEN_ENCODER_UNAVAILABLE",
32116
+ "SCREEN_RECORDING_PERMISSION_REQUIRED"
32117
+ ]);
30770
32118
  function safeCode(error62) {
30771
32119
  const code = error62 instanceof NativeToolError ? error62.code : error62 instanceof Error ? error62.message : "";
30772
32120
  return knownCodes.has(code) || /^GUARD_[A-Z_]{1,30}$/.test(code) ? code : "TOOL_FAILED";
@@ -30777,6 +32125,14 @@ function resultOutcome(result2) {
30777
32125
  if (!result2.treeTerminated || result2.exitCode === null) return "unknown";
30778
32126
  return result2.exitCode === 0 ? "success" : "failed";
30779
32127
  }
32128
+ function screenshotMetadata(stdout) {
32129
+ try {
32130
+ const { data: _data, ...metadata } = JSON.parse(stdout);
32131
+ return JSON.stringify(metadata);
32132
+ } catch {
32133
+ return "";
32134
+ }
32135
+ }
30780
32136
  async function outboundResult(call, result2, binding2, optional2, ledger) {
30781
32137
  const shaped = call.name === "command_run" ? shapeCommandResultForAgentDetailed({ command: call.args.command, args: call.args.args, cwd: call.args.cwd ?? "." }, result2) : { result: result2, telemetry: unshapedResultTelemetry(result2) };
30782
32138
  if (ledger) {
@@ -30829,7 +32185,7 @@ var NativeRuntime = class {
30829
32185
  }
30830
32186
  if (frame.type === "result" && this.options.contentAudit) {
30831
32187
  const call = this.contexts.get(frame.binding.executionId)?.tool.call;
30832
- if (call) try {
32188
+ if (call && call.name !== "take_screenshot") try {
30833
32189
  this.options.contentAudit.record(frame.binding, call, frame.result);
30834
32190
  } catch {
30835
32191
  }
@@ -30966,8 +32322,10 @@ var NativeRuntime = class {
30966
32322
  const checked = ResultSchema.parse(output2);
30967
32323
  const { resultCode, ...journalOutput } = checked;
30968
32324
  if (context.guardPermit) await this.options.guard.result(context.guardPermit, checked);
30969
- const final = await this.options.journal.finish(binding2.executionId, journalOutput, resultCode);
30970
- this.send({ type: "result", version: 1, binding: binding2, result: await outboundResult(runnable.call, journalResult(final.result, resultCode), binding2, this.optionalTelemetry, this.options.efficiencyLedger) });
32325
+ const image = runnable.call.name === "take_screenshot" ? journalOutput.stdout : void 0;
32326
+ const final = await this.options.journal.finish(binding2.executionId, image === void 0 ? journalOutput : { ...journalOutput, stdout: screenshotMetadata(image) }, resultCode);
32327
+ const outbound = await outboundResult(runnable.call, journalResult(final.result, resultCode), binding2, this.optionalTelemetry, this.options.efficiencyLedger);
32328
+ this.send({ type: "result", version: 1, binding: binding2, result: image === void 0 ? outbound : { ...outbound, stdout: image } });
30971
32329
  }, abort.signal);
30972
32330
  context.task = work.catch(async (error62) => {
30973
32331
  if (!context.accepted) {
@@ -31189,10 +32547,10 @@ var NativeRelayBridge = class {
31189
32547
  };
31190
32548
 
31191
32549
  // agent/src/local-direct.ts
31192
- import net from "node:net";
31193
- import path19 from "node:path";
31194
- import { createHmac as createHmac2, hkdfSync, randomBytes as randomBytes6, randomUUID as randomUUID8, timingSafeEqual as timingSafeEqual3 } from "node:crypto";
31195
- import { mkdir as mkdir7, readFile as readFile7, rename as rename5, rm as rm6, writeFile as writeFile3 } from "node:fs/promises";
32550
+ import net2 from "node:net";
32551
+ import path20 from "node:path";
32552
+ import { createHmac as createHmac2, hkdfSync, randomBytes as randomBytes7, randomUUID as randomUUID8, timingSafeEqual as timingSafeEqual3 } from "node:crypto";
32553
+ import { mkdir as mkdir7, readFile as readFile8, rename as rename5, rm as rm7, writeFile as writeFile3 } from "node:fs/promises";
31196
32554
  var LocalDirectError = class extends Error {
31197
32555
  constructor(code) {
31198
32556
  super(code);
@@ -31210,11 +32568,11 @@ var ADMISSION_MS = 6e4;
31210
32568
  var MAX_IN_FLIGHT = 16;
31211
32569
  var MAX_CONNECTIONS = 32;
31212
32570
  function localDirectDirectory(appData) {
31213
- return path19.join(appData, "LocalCommander", "LocalMcp");
32571
+ return path20.join(appData, "LocalCommander", "LocalMcp");
31214
32572
  }
31215
32573
  async function localDirectEnabled(directory) {
31216
32574
  try {
31217
- return JSON.parse(await readFile7(path19.join(directory, "settings.json"), "utf8"))?.enabled === true;
32575
+ return JSON.parse(await readFile8(path20.join(directory, "settings.json"), "utf8"))?.enabled === true;
31218
32576
  } catch {
31219
32577
  return false;
31220
32578
  }
@@ -31228,7 +32586,7 @@ function sameProof(candidate, expected) {
31228
32586
  const a = Buffer.from(candidate), b = Buffer.from(expected);
31229
32587
  return a.length === b.length && timingSafeEqual3(a, b);
31230
32588
  }
31231
- var nonce = () => randomBytes6(32).toString("base64url");
32589
+ var nonce = () => randomBytes7(32).toString("base64url");
31232
32590
  var NONCE = /^[A-Za-z0-9_-]{43}$/;
31233
32591
  function codeOf(error62) {
31234
32592
  const code = error62 instanceof NativeToolError || error62 instanceof LocalDirectError ? error62.code : error62 instanceof Error ? error62.message : "";
@@ -31287,7 +32645,7 @@ var Lines = class {
31287
32645
  async function readEndpoint(directory) {
31288
32646
  let value;
31289
32647
  try {
31290
- value = JSON.parse(await readFile7(path19.join(directory, "endpoint.json"), "utf8"));
32648
+ value = JSON.parse(await readFile8(path20.join(directory, "endpoint.json"), "utf8"));
31291
32649
  } catch {
31292
32650
  fail4("LOCAL_AGENT_NOT_RUNNING");
31293
32651
  }
@@ -31304,13 +32662,13 @@ var LocalDirectServer = class _LocalDirectServer {
31304
32662
  sockets = /* @__PURE__ */ new Set();
31305
32663
  /** Listens only while the owner has enabled direct local access; null otherwise. */
31306
32664
  static async start(options) {
31307
- const endpointFile = path19.join(options.directory, "endpoint.json");
32665
+ const endpointFile = path20.join(options.directory, "endpoint.json");
31308
32666
  if (!await localDirectEnabled(options.directory)) {
31309
- await rm6(endpointFile, { force: true }).catch(() => {
32667
+ await rm7(endpointFile, { force: true }).catch(() => {
31310
32668
  });
31311
32669
  return null;
31312
32670
  }
31313
- const server = net.createServer(), self = new _LocalDirectServer(server, options);
32671
+ const server = net2.createServer(), self = new _LocalDirectServer(server, options);
31314
32672
  server.on("connection", (socket) => self.accept(socket));
31315
32673
  await new Promise((resolve, reject) => {
31316
32674
  server.once("error", reject);
@@ -31332,7 +32690,7 @@ var LocalDirectServer = class _LocalDirectServer {
31332
32690
  for (const socket of this.sockets) socket.destroy();
31333
32691
  await new Promise((resolve) => this.server.close(() => resolve()));
31334
32692
  try {
31335
- if ((await readEndpoint(this.options.directory)).pid === process.pid) await rm6(path19.join(this.options.directory, "endpoint.json"), { force: true });
32693
+ if ((await readEndpoint(this.options.directory)).pid === process.pid) await rm7(path20.join(this.options.directory, "endpoint.json"), { force: true });
31336
32694
  } catch {
31337
32695
  }
31338
32696
  }
@@ -31467,7 +32825,7 @@ var LocalDirectClient = class _LocalDirectClient {
31467
32825
  static async connect(options) {
31468
32826
  if (!await localDirectEnabled(options.directory)) fail4("LOCAL_ACCESS_DISABLED");
31469
32827
  const endpoint2 = await readEndpoint(options.directory);
31470
- const socket = net.createConnection({ host: "127.0.0.1", port: endpoint2.port });
32828
+ const socket = net2.createConnection({ host: "127.0.0.1", port: endpoint2.port });
31471
32829
  let handler = () => {
31472
32830
  };
31473
32831
  const lines = new Lines(socket, (frame) => handler(frame));
@@ -35187,9 +36545,9 @@ var rev2026Codec = {
35187
36545
  });
35188
36546
  const parsed = buildSchemas2026().RequestMetaEnvelopeSchema.safeParse(meta3);
35189
36547
  if (!parsed.success) for (const issue2 of parsed.error.issues) {
35190
- const path29 = issue2.path.map(String);
35191
- const key = path29.length > 0 ? path29.join(".") : "_meta";
35192
- if (path29.length === 1 && issues.some((existing) => existing.key === key && existing.problem === "missing")) continue;
36548
+ const path30 = issue2.path.map(String);
36549
+ const key = path30.length > 0 ? path30.join(".") : "_meta";
36550
+ if (path30.length === 1 && issues.some((existing) => existing.key === key && existing.problem === "missing")) continue;
35193
36551
  issues.push({
35194
36552
  key,
35195
36553
  problem: issue2.message
@@ -35491,29 +36849,29 @@ var PERMITTED_X_MCP_HEADER_TYPES = /* @__PURE__ */ new Set([
35491
36849
  function scanXMcpHeaderDeclarations(inputSchema) {
35492
36850
  const declarations = [];
35493
36851
  const seenLower = /* @__PURE__ */ new Map();
35494
- const visit2 = (node2, path29, reachable) => {
36852
+ const visit2 = (node2, path30, reachable) => {
35495
36853
  if (node2 === null || typeof node2 !== "object") return void 0;
35496
36854
  const schema = node2;
35497
36855
  if (X_MCP_HEADER_KEY in schema) {
35498
- if (!reachable || path29.length === 0) return `${pathName(path29)}: x-mcp-header is only permitted on properties statically reachable via a chain of 'properties' keys (not under items, additionalProperties, oneOf/anyOf/allOf/not, if/then/else, or $ref)`;
36856
+ if (!reachable || path30.length === 0) return `${pathName(path30)}: x-mcp-header is only permitted on properties statically reachable via a chain of 'properties' keys (not under items, additionalProperties, oneOf/anyOf/allOf/not, if/then/else, or $ref)`;
35499
36857
  const raw = schema[X_MCP_HEADER_KEY];
35500
- if (typeof raw !== "string" || raw.length === 0) return `${pathName(path29)}: x-mcp-header MUST be a non-empty string`;
35501
- if (!RFC9110_TOKEN.test(raw)) return `${pathName(path29)}: x-mcp-header '${raw}' is not a valid RFC 9110 token (no spaces, control characters or HTTP delimiters)`;
36858
+ if (typeof raw !== "string" || raw.length === 0) return `${pathName(path30)}: x-mcp-header MUST be a non-empty string`;
36859
+ if (!RFC9110_TOKEN.test(raw)) return `${pathName(path30)}: x-mcp-header '${raw}' is not a valid RFC 9110 token (no spaces, control characters or HTTP delimiters)`;
35502
36860
  const type = typeof schema.type === "string" ? schema.type : void 0;
35503
- if (type === void 0 || !PERMITTED_X_MCP_HEADER_TYPES.has(type)) return `${pathName(path29)}: x-mcp-header is only permitted on primitive-typed properties (string, integer, boolean); got ${type ?? "<none>"}`;
36861
+ if (type === void 0 || !PERMITTED_X_MCP_HEADER_TYPES.has(type)) return `${pathName(path30)}: x-mcp-header is only permitted on primitive-typed properties (string, integer, boolean); got ${type ?? "<none>"}`;
35504
36862
  const lower = raw.toLowerCase();
35505
36863
  const prior = seenLower.get(lower);
35506
36864
  if (prior !== void 0) return `x-mcp-header '${raw}' is not case-insensitively unique (also declared as '${prior}')`;
35507
36865
  seenLower.set(lower, raw);
35508
36866
  declarations.push({
35509
- path: path29,
36867
+ path: path30,
35510
36868
  headerName: raw,
35511
36869
  type
35512
36870
  });
35513
36871
  }
35514
36872
  const properties = schema.properties;
35515
36873
  if (properties !== null && typeof properties === "object") for (const [key, child] of Object.entries(properties)) {
35516
- const fault$1 = visit2(child, [...path29, key], reachable);
36874
+ const fault$1 = visit2(child, [...path30, key], reachable);
35517
36875
  if (fault$1 !== void 0) return fault$1;
35518
36876
  }
35519
36877
  for (const k of NON_REACHABLE_SUBSCHEMA_KEYWORDS) {
@@ -35521,7 +36879,7 @@ function scanXMcpHeaderDeclarations(inputSchema) {
35521
36879
  if (sub === void 0) continue;
35522
36880
  const branches = Array.isArray(sub) ? sub : sub !== null && typeof sub === "object" && OBJECT_VALUED_SUBSCHEMA_KEYWORDS.has(k) ? Object.values(sub) : [sub];
35523
36881
  for (const branch of branches) {
35524
- const fault$1 = visit2(branch, [...path29, `<${k}>`], false);
36882
+ const fault$1 = visit2(branch, [...path30, `<${k}>`], false);
35525
36883
  if (fault$1 !== void 0) return fault$1;
35526
36884
  }
35527
36885
  }
@@ -35561,8 +36919,8 @@ var OBJECT_VALUED_SUBSCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
35561
36919
  "$defs",
35562
36920
  "definitions"
35563
36921
  ]);
35564
- function pathName(path29) {
35565
- return path29.length === 0 ? "<root>" : path29.join(".");
36922
+ function pathName(path30) {
36923
+ return path30.length === 0 ? "<root>" : path30.join(".");
35566
36924
  }
35567
36925
  var HEADER_MISMATCH_ERROR_CODE = -32020;
35568
36926
  var INBOUND_VALIDATION_LADDER = [
@@ -35812,7 +37170,7 @@ var PROPERTY_KEYS_BY_TYPE = {
35812
37170
  array: shapeKeys([UntitledMultiSelectEnumSchemaSchema, TitledMultiSelectEnumSchemaSchema])
35813
37171
  };
35814
37172
  var SUPPORTED_STRING_FORMATS = new Set(StringSchemaSchema.shape.format.unwrap().options);
35815
- function walkProperty(node2, path29, vendor, unsupported) {
37173
+ function walkProperty(node2, path30, vendor, unsupported) {
35816
37174
  if (!isJsonObject(node2)) return node2;
35817
37175
  const allowedKeys = typeof node2.type === "string" && Object.hasOwn(PROPERTY_KEYS_BY_TYPE, node2.type) ? PROPERTY_KEYS_BY_TYPE[node2.type] : void 0;
35818
37176
  if (allowedKeys === void 0) return node2;
@@ -35820,8 +37178,8 @@ function walkProperty(node2, path29, vendor, unsupported) {
35820
37178
  for (const [key, value] of Object.entries(node2)) if (allowedKeys.has(key) || isAnnotationOnlyJsonSchemaKeyword(key)) pruned[key] = value;
35821
37179
  else if (key === "pattern" && node2.type === "string" && typeof node2.format === "string") {
35822
37180
  if (!SUPPORTED_STRING_FORMATS.has(node2.format)) pruned[key] = value;
35823
- else if (typeof value !== "string" || !isLibraryFormatPattern(node2.format, value, vendor)) unsupported.push(`${path29}.${key}`);
35824
- } else unsupported.push(`${path29}.${key}`);
37181
+ else if (typeof value !== "string" || !isLibraryFormatPattern(node2.format, value, vendor)) unsupported.push(`${path30}.${key}`);
37182
+ } else unsupported.push(`${path30}.${key}`);
35825
37183
  return pruned;
35826
37184
  }
35827
37185
  function walkRequestedSchema(converted, vendor) {
@@ -35838,11 +37196,11 @@ function describeUnsupportedProperties(pruned, fallback) {
35838
37196
  const offenders = Object.entries(pruned.properties).filter(([, node2]) => !parseSchema(PrimitiveSchemaDefinitionSchema, node2).success).map(([name2]) => `properties.${name2}`);
35839
37197
  return offenders.length > 0 ? offenders.join(", ") : fallback;
35840
37198
  }
35841
- function findDroppedConstraintPaths(original, parsed, path29 = "") {
35842
- if (Array.isArray(original) && Array.isArray(parsed)) return original.flatMap((item, index) => findDroppedConstraintPaths(item, parsed[index], `${path29}[${index}]`));
37199
+ function findDroppedConstraintPaths(original, parsed, path30 = "") {
37200
+ if (Array.isArray(original) && Array.isArray(parsed)) return original.flatMap((item, index) => findDroppedConstraintPaths(item, parsed[index], `${path30}[${index}]`));
35843
37201
  if (!isJsonObject(original) || !isJsonObject(parsed)) return [];
35844
37202
  return Object.entries(original).flatMap(([key, value]) => {
35845
- const childPath = path29 ? `${path29}.${key}` : key;
37203
+ const childPath = path30 ? `${path30}.${key}` : key;
35846
37204
  if (!Object.prototype.hasOwnProperty.call(parsed, key)) return isAnnotationOnlyJsonSchemaKeyword(key) ? [] : [childPath];
35847
37205
  return findDroppedConstraintPaths(value, parsed[key], childPath);
35848
37206
  });
@@ -36990,8 +38348,8 @@ var require_content_type = /* @__PURE__ */ __commonJSMin(((exports) => {
36990
38348
  var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g;
36991
38349
  var QESC_REGEXP = /\\([\u000b\u0020-\u00ff])/g;
36992
38350
  var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
36993
- exports.parse = parse3;
36994
- function parse3(string4) {
38351
+ exports.parse = parse4;
38352
+ function parse4(string4) {
36995
38353
  if (!string4) throw new TypeError("argument string is required");
36996
38354
  var header = typeof string4 === "object" ? getcontenttype(string4) : string4;
36997
38355
  if (typeof header !== "string") throw new TypeError("argument string is required to be a string");
@@ -37515,9 +38873,9 @@ var require_codegen = /* @__PURE__ */ __commonJSMin(((exports) => {
37515
38873
  const rhs = this.rhs === void 0 ? "" : ` = ${this.rhs}`;
37516
38874
  return `${varKind} ${this.name}${rhs};` + _n;
37517
38875
  }
37518
- optimizeNames(names, constants10) {
38876
+ optimizeNames(names, constants11) {
37519
38877
  if (!names[this.name.str]) return;
37520
- if (this.rhs) this.rhs = optimizeExpr(this.rhs, names, constants10);
38878
+ if (this.rhs) this.rhs = optimizeExpr(this.rhs, names, constants11);
37521
38879
  return this;
37522
38880
  }
37523
38881
  get names() {
@@ -37534,9 +38892,9 @@ var require_codegen = /* @__PURE__ */ __commonJSMin(((exports) => {
37534
38892
  render({ _n }) {
37535
38893
  return `${this.lhs} = ${this.rhs};` + _n;
37536
38894
  }
37537
- optimizeNames(names, constants10) {
38895
+ optimizeNames(names, constants11) {
37538
38896
  if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects) return;
37539
- this.rhs = optimizeExpr(this.rhs, names, constants10);
38897
+ this.rhs = optimizeExpr(this.rhs, names, constants11);
37540
38898
  return this;
37541
38899
  }
37542
38900
  get names() {
@@ -37595,8 +38953,8 @@ var require_codegen = /* @__PURE__ */ __commonJSMin(((exports) => {
37595
38953
  optimizeNodes() {
37596
38954
  return `${this.code}` ? this : void 0;
37597
38955
  }
37598
- optimizeNames(names, constants10) {
37599
- this.code = optimizeExpr(this.code, names, constants10);
38956
+ optimizeNames(names, constants11) {
38957
+ this.code = optimizeExpr(this.code, names, constants11);
37600
38958
  return this;
37601
38959
  }
37602
38960
  get names() {
@@ -37622,12 +38980,12 @@ var require_codegen = /* @__PURE__ */ __commonJSMin(((exports) => {
37622
38980
  }
37623
38981
  return nodes.length > 0 ? this : void 0;
37624
38982
  }
37625
- optimizeNames(names, constants10) {
38983
+ optimizeNames(names, constants11) {
37626
38984
  const { nodes } = this;
37627
38985
  let i = nodes.length;
37628
38986
  while (i--) {
37629
38987
  const n = nodes[i];
37630
- if (n.optimizeNames(names, constants10)) continue;
38988
+ if (n.optimizeNames(names, constants11)) continue;
37631
38989
  subtractNames(names, n.names);
37632
38990
  nodes.splice(i, 1);
37633
38991
  }
@@ -37674,11 +39032,11 @@ var require_codegen = /* @__PURE__ */ __commonJSMin(((exports) => {
37674
39032
  if (cond === false || !this.nodes.length) return void 0;
37675
39033
  return this;
37676
39034
  }
37677
- optimizeNames(names, constants10) {
39035
+ optimizeNames(names, constants11) {
37678
39036
  var _a3;
37679
- this.else = (_a3 = this.else) === null || _a3 === void 0 ? void 0 : _a3.optimizeNames(names, constants10);
37680
- if (!(super.optimizeNames(names, constants10) || this.else)) return;
37681
- this.condition = optimizeExpr(this.condition, names, constants10);
39037
+ this.else = (_a3 = this.else) === null || _a3 === void 0 ? void 0 : _a3.optimizeNames(names, constants11);
39038
+ if (!(super.optimizeNames(names, constants11) || this.else)) return;
39039
+ this.condition = optimizeExpr(this.condition, names, constants11);
37682
39040
  return this;
37683
39041
  }
37684
39042
  get names() {
@@ -37700,9 +39058,9 @@ var require_codegen = /* @__PURE__ */ __commonJSMin(((exports) => {
37700
39058
  render(opts) {
37701
39059
  return `for(${this.iteration})` + super.render(opts);
37702
39060
  }
37703
- optimizeNames(names, constants10) {
37704
- if (!super.optimizeNames(names, constants10)) return;
37705
- this.iteration = optimizeExpr(this.iteration, names, constants10);
39061
+ optimizeNames(names, constants11) {
39062
+ if (!super.optimizeNames(names, constants11)) return;
39063
+ this.iteration = optimizeExpr(this.iteration, names, constants11);
37706
39064
  return this;
37707
39065
  }
37708
39066
  get names() {
@@ -37737,9 +39095,9 @@ var require_codegen = /* @__PURE__ */ __commonJSMin(((exports) => {
37737
39095
  render(opts) {
37738
39096
  return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
37739
39097
  }
37740
- optimizeNames(names, constants10) {
37741
- if (!super.optimizeNames(names, constants10)) return;
37742
- this.iterable = optimizeExpr(this.iterable, names, constants10);
39098
+ optimizeNames(names, constants11) {
39099
+ if (!super.optimizeNames(names, constants11)) return;
39100
+ this.iterable = optimizeExpr(this.iterable, names, constants11);
37743
39101
  return this;
37744
39102
  }
37745
39103
  get names() {
@@ -37778,11 +39136,11 @@ var require_codegen = /* @__PURE__ */ __commonJSMin(((exports) => {
37778
39136
  (_b = this.finally) === null || _b === void 0 || _b.optimizeNodes();
37779
39137
  return this;
37780
39138
  }
37781
- optimizeNames(names, constants10) {
39139
+ optimizeNames(names, constants11) {
37782
39140
  var _a3, _b;
37783
- super.optimizeNames(names, constants10);
37784
- (_a3 = this.catch) === null || _a3 === void 0 || _a3.optimizeNames(names, constants10);
37785
- (_b = this.finally) === null || _b === void 0 || _b.optimizeNames(names, constants10);
39141
+ super.optimizeNames(names, constants11);
39142
+ (_a3 = this.catch) === null || _a3 === void 0 || _a3.optimizeNames(names, constants11);
39143
+ (_b = this.finally) === null || _b === void 0 || _b.optimizeNames(names, constants11);
37786
39144
  return this;
37787
39145
  }
37788
39146
  get names() {
@@ -38031,7 +39389,7 @@ var require_codegen = /* @__PURE__ */ __commonJSMin(((exports) => {
38031
39389
  function addExprNames(names, from) {
38032
39390
  return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
38033
39391
  }
38034
- function optimizeExpr(expr, names, constants10) {
39392
+ function optimizeExpr(expr, names, constants11) {
38035
39393
  if (expr instanceof code_1.Name) return replaceName(expr);
38036
39394
  if (!canOptimize(expr)) return expr;
38037
39395
  return new code_1._Code(expr._items.reduce((items, c) => {
@@ -38041,13 +39399,13 @@ var require_codegen = /* @__PURE__ */ __commonJSMin(((exports) => {
38041
39399
  return items;
38042
39400
  }, []));
38043
39401
  function replaceName(n) {
38044
- const c = constants10[n.str];
39402
+ const c = constants11[n.str];
38045
39403
  if (c === void 0 || names[n.str] !== 1) return n;
38046
39404
  delete names[n.str];
38047
39405
  return c;
38048
39406
  }
38049
39407
  function canOptimize(e) {
38050
- return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants10[c.str] !== void 0);
39408
+ return e instanceof code_1._Code && e._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants11[c.str] !== void 0);
38051
39409
  }
38052
39410
  }
38053
39411
  function subtractNames(names, from) {
@@ -39918,8 +41276,8 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
39918
41276
  for (let i = 0; i < str.length; i++) if (str[i] === token) ind++;
39919
41277
  return ind;
39920
41278
  }
39921
- function removeDotSegments(path29) {
39922
- let input2 = path29;
41279
+ function removeDotSegments(path30) {
41280
+ let input2 = path30;
39923
41281
  const output2 = [];
39924
41282
  let nextSlash = -1;
39925
41283
  let len = 0;
@@ -40072,8 +41430,8 @@ var require_schemes = /* @__PURE__ */ __commonJSMin(((exports, module) => {
40072
41430
  wsComponent.secure = void 0;
40073
41431
  }
40074
41432
  if (wsComponent.resourceName) {
40075
- const [path29, query] = wsComponent.resourceName.split("?");
40076
- wsComponent.path = path29 && path29 !== "/" ? path29 : void 0;
41433
+ const [path30, query] = wsComponent.resourceName.split("?");
41434
+ wsComponent.path = path30 && path30 !== "/" ? path30 : void 0;
40077
41435
  wsComponent.query = query;
40078
41436
  wsComponent.resourceName = void 0;
40079
41437
  }
@@ -40179,21 +41537,21 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
40179
41537
  const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = require_utils();
40180
41538
  const { SCHEMES, getSchemeHandler } = require_schemes();
40181
41539
  function normalize(uri, options) {
40182
- if (typeof uri === "string") uri = serialize(parse3(uri, options), options);
40183
- else if (typeof uri === "object") uri = parse3(serialize(uri, options), options);
41540
+ if (typeof uri === "string") uri = serialize(parse4(uri, options), options);
41541
+ else if (typeof uri === "object") uri = parse4(serialize(uri, options), options);
40184
41542
  return uri;
40185
41543
  }
40186
41544
  function resolve(baseURI, relativeURI, options) {
40187
41545
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
40188
- const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
41546
+ const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
40189
41547
  schemelessOptions.skipEscape = true;
40190
41548
  return serialize(resolved, schemelessOptions);
40191
41549
  }
40192
41550
  function resolveComponent(base, relative, options, skipNormalization) {
40193
41551
  const target = {};
40194
41552
  if (!skipNormalization) {
40195
- base = parse3(serialize(base, options), options);
40196
- relative = parse3(serialize(relative, options), options);
41553
+ base = parse4(serialize(base, options), options);
41554
+ relative = parse4(serialize(relative, options), options);
40197
41555
  }
40198
41556
  options = options || {};
40199
41557
  if (!options.tolerant && relative.scheme) {
@@ -40237,7 +41595,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
40237
41595
  function equal(uriA, uriB, options) {
40238
41596
  if (typeof uriA === "string") {
40239
41597
  uriA = unescape(uriA);
40240
- uriA = serialize(normalizeComponentEncoding(parse3(uriA, options), true), {
41598
+ uriA = serialize(normalizeComponentEncoding(parse4(uriA, options), true), {
40241
41599
  ...options,
40242
41600
  skipEscape: true
40243
41601
  });
@@ -40247,7 +41605,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
40247
41605
  });
40248
41606
  if (typeof uriB === "string") {
40249
41607
  uriB = unescape(uriB);
40250
- uriB = serialize(normalizeComponentEncoding(parse3(uriB, options), true), {
41608
+ uriB = serialize(normalizeComponentEncoding(parse4(uriB, options), true), {
40251
41609
  ...options,
40252
41610
  skipEscape: true
40253
41611
  });
@@ -40300,7 +41658,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
40300
41658
  return uriTokens.join("");
40301
41659
  }
40302
41660
  const URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
40303
- function parse3(uri, opts) {
41661
+ function parse4(uri, opts) {
40304
41662
  const options = Object.assign({}, opts);
40305
41663
  const parsed = {
40306
41664
  scheme: void 0,
@@ -40361,7 +41719,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
40361
41719
  resolveComponent,
40362
41720
  equal,
40363
41721
  serialize,
40364
- parse: parse3
41722
+ parse: parse4
40365
41723
  };
40366
41724
  module.exports = fastUri;
40367
41725
  module.exports.default = fastUri;
@@ -45640,7 +46998,8 @@ var DESCRIPTIONS = {
45640
46998
  git_diff: ["Git diff of the repository at a workspace-relative path.", { readOnlyHint: true, openWorldHint: false }],
45641
46999
  git_log: ["Recent Git commits of the repository at a workspace-relative path.", { readOnlyHint: true, openWorldHint: false }],
45642
47000
  project_snapshot: ["Compact project overview: Git state and, with startup, AGENTS.md policy and task continuation.", { readOnlyHint: true, openWorldHint: false }],
45643
- command_run: ["Run one executable with an argument array (no shell parsing), hidden, with captured output. Uses this Windows account's rights within the owner's grant.", { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true }],
47001
+ command_run: ["Run one executable with an argument array (no shell parsing), hidden, with captured output. Uses this user account's rights within the owner's grant.", { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true }],
47002
+ take_screenshot: ["Take a still image of this computer's primary screen, returned as a JPEG image. It contains everything visible on the screen, including any open passwords, keys or private messages. Needs a Full Access workspace; the lock screen is never captured.", { readOnlyHint: true, openWorldHint: false }],
45644
47003
  localhost_request: ["HTTP request to a service on this computer (localhost only).", { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false }]
45645
47004
  };
45646
47005
  var workspace = external_exports.string().min(1).max(4096).optional().describe("Workspace grant id, root path (for example D:\\) or display name from workspace_list. Optional when only one workspace is approved.");
@@ -45653,6 +47012,14 @@ function failure4(error62) {
45653
47012
  return text2(code + hint, true);
45654
47013
  }
45655
47014
  function render(name2, result2) {
47015
+ if (name2 === "take_screenshot" && result2.resultCode === "SUCCESS") {
47016
+ try {
47017
+ const { data, mimeType, ...metadata } = JSON.parse(result2.stdout);
47018
+ if (typeof data === "string" && data && mimeType === "image/jpeg") return { content: [{ type: "image", data, mimeType }, { type: "text", text: JSON.stringify(metadata) }] };
47019
+ } catch {
47020
+ }
47021
+ return text2(JSON.stringify({ resultCode: "SCREEN_UNAVAILABLE" }), true);
47022
+ }
45656
47023
  if (name2 !== "command_run" && result2.resultCode === "SUCCESS") return text2(result2.stdout);
45657
47024
  const { exitCode, resultCode, timedOut, cancelled, stdout, stderr, stdoutTruncated, stderrTruncated } = result2;
45658
47025
  return text2(
@@ -45673,7 +47040,7 @@ async function serveLocalMcp(options) {
45673
47040
  return connecting;
45674
47041
  };
45675
47042
  const server = new McpServer({ name: "local-commander-local", version: options.agentVersion }, {
45676
- instructions: "Local Commander direct access to this computer, through the owner's approved workspaces. Paths are relative to the selected workspace root; call workspace_list to see roots. Commands run hidden with this Windows account's rights; owner denials still apply."
47043
+ instructions: "Local Commander direct access to this computer, through the owner's approved workspaces. Paths are relative to the selected workspace root; call workspace_list to see roots. Commands run hidden with this user account's rights; owner denials still apply."
45677
47044
  });
45678
47045
  server.registerTool(
45679
47046
  "workspace_list",
@@ -45688,7 +47055,7 @@ async function serveLocalMcp(options) {
45688
47055
  );
45689
47056
  for (const option of ToolCallSchema.options) {
45690
47057
  const name2 = option.shape.name.value, entry = DESCRIPTIONS[name2];
45691
- if (!entry) continue;
47058
+ if (!entry || name2 === "take_screenshot" && !screenshotEnabled()) continue;
45692
47059
  const inputSchema = option.shape.args.extend({ workspace });
45693
47060
  const callback = async (input2, ctx) => {
45694
47061
  const { workspace: selected, ...args } = input2;
@@ -46154,6 +47521,7 @@ async function connectOnce(options) {
46154
47521
  const incidents = Array.isArray(readyFrame.capabilities) && readyFrame.capabilities.includes("incidentBatchV1");
46155
47522
  const monitorHeartbeat = Array.isArray(readyFrame.capabilities) && readyFrame.capabilities.includes("monitorHeartbeatV1") && typeof readyFrame.heartbeatMs === "number" && Number.isInteger(readyFrame.heartbeatMs) && readyFrame.heartbeatMs >= 1e3 && readyFrame.heartbeatMs <= 6e4 ? readyFrame.heartbeatMs : void 0;
46156
47523
  const nativeStatus = Array.isArray(readyFrame.capabilities) && readyFrame.capabilities.includes(NATIVE_STATUS_CAPABILITY) && options.status;
47524
+ const accessModes = Array.isArray(readyFrame.capabilities) && readyFrame.capabilities.includes(WORKSPACE_ACCESS_MODE_CAPABILITY);
46157
47525
  const reportStatus = () => {
46158
47526
  if (!nativeStatus) return;
46159
47527
  const { safeSlots, active, queued, paused } = nativeStatus();
@@ -46380,7 +47748,16 @@ async function connectOnce(options) {
46380
47748
  registerWorkspace: (workspace2) => {
46381
47749
  if (pendingWorkspace.size >= 32) return Promise.reject(new RelayClientError("RELAY_PENDING_LIMIT"));
46382
47750
  const requestId = randomUUID10();
46383
- const event = { type: "workspace_grant", version: 1, requestId, workspaceGrantId: workspace2.workspaceGrantId, rootHash: workspace2.rootHash, displayName: workspace2.displayName, policyVersion: workspace2.policyVersion };
47751
+ const event = {
47752
+ type: "workspace_grant",
47753
+ version: 1,
47754
+ requestId,
47755
+ workspaceGrantId: workspace2.workspaceGrantId,
47756
+ rootHash: workspace2.rootHash,
47757
+ displayName: workspace2.displayName,
47758
+ policyVersion: workspace2.policyVersion,
47759
+ ...accessModes ? { accessMode: workspace2.fullAccess === true ? "full" : "scoped" } : {}
47760
+ };
46384
47761
  return new Promise((resolve, reject) => {
46385
47762
  const timer = setTimeout(() => {
46386
47763
  pendingWorkspace.delete(requestId);
@@ -46427,16 +47804,16 @@ async function connectOnce(options) {
46427
47804
  // agent/src/machine-identity.ts
46428
47805
  import { spawn as spawn5 } from "node:child_process";
46429
47806
  import { createHash as createHash16 } from "node:crypto";
46430
- import os5 from "node:os";
47807
+ import os6 from "node:os";
46431
47808
  import { open as open7 } from "node:fs/promises";
46432
- import { constants as constants8 } from "node:fs";
46433
- import path20 from "node:path";
47809
+ import { constants as constants9 } from "node:fs";
47810
+ import path21 from "node:path";
46434
47811
  var MACHINE_GUID = /^\s*MachineGuid\s+REG_SZ\s+([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})\s*$/m;
46435
47812
  async function readMachineGuid(timeoutMs2 = 5e3) {
46436
47813
  if (process.platform === "linux") {
46437
47814
  let handle;
46438
47815
  try {
46439
- handle = await open7("/etc/machine-id", constants8.O_RDONLY | constants8.O_NOFOLLOW);
47816
+ handle = await open7("/etc/machine-id", constants9.O_RDONLY | constants9.O_NOFOLLOW);
46440
47817
  const stat2 = await handle.stat();
46441
47818
  if (!stat2.isFile() || stat2.size > 128) return null;
46442
47819
  const data = Buffer.alloc(129);
@@ -46451,7 +47828,7 @@ async function readMachineGuid(timeoutMs2 = 5e3) {
46451
47828
  }
46452
47829
  }
46453
47830
  if (!["win32", "darwin"].includes(process.platform)) return null;
46454
- const reg = process.platform === "darwin" ? "/usr/sbin/ioreg" : path20.join(process.env.SystemRoot || "C:\\Windows", "System32", "reg.exe");
47831
+ const reg = process.platform === "darwin" ? "/usr/sbin/ioreg" : path21.join(process.env.SystemRoot || "C:\\Windows", "System32", "reg.exe");
46455
47832
  const args = process.platform === "darwin" ? ["-rd1", "-c", "IOPlatformExpertDevice"] : ["query", "HKLM\\SOFTWARE\\Microsoft\\Cryptography", "/v", "MachineGuid", "/reg:64"];
46456
47833
  const pattern = process.platform === "darwin" ? /"IOPlatformUUID"\s*=\s*"([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})"/ : MACHINE_GUID;
46457
47834
  return new Promise((resolve) => {
@@ -46485,7 +47862,7 @@ async function readComputerName(timeoutMs2 = 5e3) {
46485
47862
  if (process.platform === "linux") {
46486
47863
  let handle;
46487
47864
  try {
46488
- handle = await open7("/etc/hostname", constants8.O_RDONLY | constants8.O_NOFOLLOW);
47865
+ handle = await open7("/etc/hostname", constants9.O_RDONLY | constants9.O_NOFOLLOW);
46489
47866
  const data = Buffer.alloc(257), { bytesRead } = await handle.read(data, 0, data.length, 0);
46490
47867
  const name2 = data.subarray(0, bytesRead).toString("utf8").trim();
46491
47868
  if (bytesRead <= 256 && valid(name2)) return name2;
@@ -46523,9 +47900,9 @@ async function readComputerName(timeoutMs2 = 5e3) {
46523
47900
  });
46524
47901
  if (valid(name2)) return name2;
46525
47902
  }
46526
- return os5.hostname();
47903
+ return os6.hostname();
46527
47904
  }
46528
- function machineProof(deviceId, machineGuid, computerName = os5.hostname()) {
47905
+ function machineProof(deviceId, machineGuid, computerName = os6.hostname()) {
46529
47906
  const name2 = computerName.slice(0, 120);
46530
47907
  if (!name2 || name2.trim() !== name2 || /[\u0000-\u001f\u007f]/.test(name2)) return null;
46531
47908
  const fingerprint3 = createHash16("sha256").update("lcmcp-machine-v1\0" + deviceId.toLowerCase() + "\0" + machineGuid.toLowerCase() + "\0" + name2.toUpperCase(), "utf8").digest("hex");
@@ -46566,8 +47943,8 @@ function canonicalOrigin2(value) {
46566
47943
  fail6("ORIGIN_INVALID");
46567
47944
  }
46568
47945
  }
46569
- function endpoint(origin, path29) {
46570
- return origin + path29;
47946
+ function endpoint(origin, path30) {
47947
+ return origin + path30;
46571
47948
  }
46572
47949
  function uuid21(value, code) {
46573
47950
  if (typeof value !== "string" || !UUID3.test(value)) fail6(code);
@@ -47068,29 +48445,29 @@ async function deliverGuardEvidence(target, packet, options = {}) {
47068
48445
  }
47069
48446
 
47070
48447
  // agent/src/optimization-ledger.ts
47071
- import { constants as constants9 } from "node:fs";
47072
- import { lstat as lstat8, mkdir as mkdir8, open as open8, readFile as readFile8, realpath as realpath8 } from "node:fs/promises";
47073
- import path21 from "node:path";
48448
+ import { constants as constants10 } from "node:fs";
48449
+ import { lstat as lstat9, mkdir as mkdir8, open as open8, readFile as readFile9, realpath as realpath8 } from "node:fs/promises";
48450
+ import path22 from "node:path";
47074
48451
  var MAX_LEDGER_BYTES = 64 * 1024 * 1024;
47075
48452
  var MAX_NOTICE_LEDGER_BYTES = 8 * 1024 * 1024;
47076
48453
  function failure5(code) {
47077
48454
  return Object.assign(new Error(code), { code });
47078
48455
  }
47079
48456
  async function safeDirectory2(directory) {
47080
- const absolute2 = path21.resolve(directory);
48457
+ const absolute2 = path22.resolve(directory);
47081
48458
  let current2 = absolute2;
47082
48459
  for (; ; ) {
47083
48460
  try {
47084
- if ((await lstat8(current2)).isSymbolicLink()) throw failure5("OPTIMIZATION_LEDGER_DIRECTORY_INVALID");
48461
+ if ((await lstat9(current2)).isSymbolicLink()) throw failure5("OPTIMIZATION_LEDGER_DIRECTORY_INVALID");
47085
48462
  } catch (error62) {
47086
48463
  if (error62.code !== "ENOENT") throw error62;
47087
48464
  }
47088
- const parent = path21.dirname(current2);
48465
+ const parent = path22.dirname(current2);
47089
48466
  if (parent === current2) break;
47090
48467
  current2 = parent;
47091
48468
  }
47092
48469
  await mkdir8(absolute2, { recursive: true, mode: 448 });
47093
- const stat2 = await lstat8(absolute2);
48470
+ const stat2 = await lstat9(absolute2);
47094
48471
  if (!stat2.isDirectory() || stat2.isSymbolicLink()) throw failure5("OPTIMIZATION_LEDGER_DIRECTORY_INVALID");
47095
48472
  return realpath8(absolute2);
47096
48473
  }
@@ -47120,29 +48497,29 @@ var OptimizationLedger = class _OptimizationLedger {
47120
48497
  closed = false;
47121
48498
  static async open(directory) {
47122
48499
  const dir = await safeDirectory2(directory);
47123
- const filename = path21.join(dir, "live-efficiency.v1.jsonl");
47124
- const noticesFilename = path21.join(dir, "live-efficiency-notices.v1.jsonl");
48500
+ const filename = path22.join(dir, "live-efficiency.v1.jsonl");
48501
+ const noticesFilename = path22.join(dir, "live-efficiency-notices.v1.jsonl");
47125
48502
  let existing = "";
47126
48503
  try {
47127
- const stat2 = await lstat8(filename);
48504
+ const stat2 = await lstat9(filename);
47128
48505
  if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.size > MAX_LEDGER_BYTES) {
47129
48506
  throw failure5("OPTIMIZATION_LEDGER_INVALID");
47130
48507
  }
47131
- existing = await readFile8(filename, "utf8");
48508
+ existing = await readFile9(filename, "utf8");
47132
48509
  } catch (error62) {
47133
48510
  if (error62.code !== "ENOENT") throw error62;
47134
48511
  }
47135
48512
  const handle = await open8(
47136
48513
  filename,
47137
- constants9.O_CREAT | constants9.O_APPEND | constants9.O_WRONLY | (constants9.O_NOFOLLOW ?? 0),
48514
+ constants10.O_CREAT | constants10.O_APPEND | constants10.O_WRONLY | (constants10.O_NOFOLLOW ?? 0),
47138
48515
  384
47139
48516
  );
47140
48517
  const ledger = new _OptimizationLedger(filename, handle, noticesFilename);
47141
48518
  try {
47142
48519
  try {
47143
- const noticeStat = await lstat8(noticesFilename);
48520
+ const noticeStat = await lstat9(noticesFilename);
47144
48521
  if (!noticeStat.isFile() || noticeStat.isSymbolicLink() || noticeStat.size > MAX_NOTICE_LEDGER_BYTES) throw failure5("OPTIMIZATION_NOTICE_LEDGER_INVALID");
47145
- const notices = await readFile8(noticesFilename, "utf8");
48522
+ const notices = await readFile9(noticesFilename, "utf8");
47146
48523
  for (const line of notices.split("\n")) {
47147
48524
  if (!line) continue;
47148
48525
  const parsed = JSON.parse(line);
@@ -47222,7 +48599,7 @@ var OptimizationLedger = class _OptimizationLedger {
47222
48599
  const marker = JSON.stringify({ sessionId: event.sessionId, checkpointCalls, deliveredAt: (/* @__PURE__ */ new Date()).toISOString() }) + "\n";
47223
48600
  let currentBytes = 0;
47224
48601
  try {
47225
- const stat2 = await lstat8(this.noticesFilename);
48602
+ const stat2 = await lstat9(this.noticesFilename);
47226
48603
  if (!stat2.isFile() || stat2.isSymbolicLink()) throw failure5("OPTIMIZATION_NOTICE_LEDGER_INVALID");
47227
48604
  currentBytes = stat2.size;
47228
48605
  } catch (error62) {
@@ -47231,7 +48608,7 @@ var OptimizationLedger = class _OptimizationLedger {
47231
48608
  if (currentBytes + Buffer.byteLength(marker, "utf8") > MAX_NOTICE_LEDGER_BYTES) throw failure5("OPTIMIZATION_NOTICE_LEDGER_CAPACITY_EXCEEDED");
47232
48609
  const markerHandle = await open8(
47233
48610
  this.noticesFilename,
47234
- constants9.O_CREAT | constants9.O_APPEND | constants9.O_WRONLY | (constants9.O_NOFOLLOW ?? 0),
48611
+ constants10.O_CREAT | constants10.O_APPEND | constants10.O_WRONLY | (constants10.O_NOFOLLOW ?? 0),
47235
48612
  384
47236
48613
  );
47237
48614
  try {
@@ -47270,9 +48647,9 @@ var OptimizationLedger = class _OptimizationLedger {
47270
48647
 
47271
48648
  // agent/src/monitor.ts
47272
48649
  import { createHash as createHash17, randomUUID as randomUUID12 } from "node:crypto";
47273
- import { lstat as lstat9, mkdir as mkdir9, open as open9, rename as rename6, rm as rm7 } from "node:fs/promises";
47274
- import path22 from "node:path";
47275
- import os6 from "node:os";
48650
+ import { lstat as lstat10, mkdir as mkdir9, open as open9, rename as rename6, rm as rm8 } from "node:fs/promises";
48651
+ import path23 from "node:path";
48652
+ import os7 from "node:os";
47276
48653
 
47277
48654
  // packages/agent-cli/bin/monitor-savings.mjs
47278
48655
  var count = (value) => Number.isSafeInteger(value) && value >= 0 && value <= 1e15;
@@ -47294,7 +48671,7 @@ function lifetimeSavingsView(raw) {
47294
48671
  // agent/src/monitor.ts
47295
48672
  function commandSummary2(tool) {
47296
48673
  if (tool.name !== "command_run") return { name: tool.name, command: tool.name };
47297
- const candidate = path22.win32.basename(tool.args.command).replace(/\.(exe|cmd|bat|com)$/i, "").toLowerCase();
48674
+ const candidate = path23.win32.basename(tool.args.command).replace(/\.(exe|cmd|bat|com)$/i, "").toLowerCase();
47298
48675
  const name2 = ["node", "npm", "npx", "git", "rg", "powershell", "pwsh", "cmd", "tsc", "python", "dotnet"].includes(candidate) ? candidate : "command";
47299
48676
  let command = name2;
47300
48677
  if (name2 === "node" && tool.args.args.includes("--test") && !tool.args.args.some((arg) => ["-e", "--eval", "-p", "--print"].includes(arg))) command += " --test";
@@ -47307,9 +48684,9 @@ function commandSummary2(tool) {
47307
48684
  var ProductionMonitor = class {
47308
48685
  constructor(directory, stateDirectory, agentVersion3) {
47309
48686
  this.agentVersion = agentVersion3;
47310
- const key = createHash17("sha256").update(path22.resolve(stateDirectory).toLowerCase()).digest("hex");
47311
- this.file = path22.join(directory, key + ".json");
47312
- this.transportFile = path22.join(directory, key + ".transport");
48687
+ const key = createHash17("sha256").update(path23.resolve(stateDirectory).toLowerCase()).digest("hex");
48688
+ this.file = path23.join(directory, key + ".json");
48689
+ this.transportFile = path23.join(directory, key + ".transport");
47313
48690
  }
47314
48691
  agentVersion;
47315
48692
  instanceId = randomUUID12();
@@ -47320,7 +48697,7 @@ var ProductionMonitor = class {
47320
48697
  measured = /* @__PURE__ */ new Set();
47321
48698
  polls = { status: 0, output: 0 };
47322
48699
  efficiencyCalls = 0;
47323
- computer = os6.hostname().replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 64) || "PC";
48700
+ computer = os7.hostname().replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 64) || "PC";
47324
48701
  sequence = 0;
47325
48702
  connection = {
47326
48703
  state: "starting",
@@ -47501,7 +48878,7 @@ var ProductionMonitor = class {
47501
48878
  schemaVersion: 1,
47502
48879
  instanceId: this.instanceId,
47503
48880
  pid: process.pid,
47504
- savingsSourceId: path22.basename(this.file, ".json"),
48881
+ savingsSourceId: path23.basename(this.file, ".json"),
47505
48882
  lifetimeSavings: this.lifetimeSavings && { ...this.lifetimeSavings },
47506
48883
  computer: this.computer,
47507
48884
  processName: "lc-agent",
@@ -47535,9 +48912,9 @@ var ProductionMonitor = class {
47535
48912
  return this.writing;
47536
48913
  }
47537
48914
  async write(file2, contents) {
47538
- const directory = path22.dirname(file2);
48915
+ const directory = path23.dirname(file2);
47539
48916
  await mkdir9(directory, { recursive: true, mode: 448 });
47540
- const stat2 = await lstat9(directory);
48917
+ const stat2 = await lstat10(directory);
47541
48918
  if (!stat2.isDirectory() || stat2.isSymbolicLink()) throw Error("MONITOR_DIRECTORY_INVALID");
47542
48919
  const temporary = file2 + "." + this.instanceId + ".tmp";
47543
48920
  const handle = await open9(temporary, "wx", 384);
@@ -47549,7 +48926,7 @@ var ProductionMonitor = class {
47549
48926
  }
47550
48927
  await rename6(temporary, file2);
47551
48928
  } finally {
47552
- await rm7(temporary, { force: true });
48929
+ await rm8(temporary, { force: true });
47553
48930
  }
47554
48931
  }
47555
48932
  async close() {
@@ -47960,27 +49337,27 @@ var NativeFabricObserver = class {
47960
49337
  };
47961
49338
 
47962
49339
  // agent/src/native-fabric-startup.ts
47963
- import { lstat as lstat11, mkdir as mkdir12, open as open11, readFile as readFile9 } from "node:fs/promises";
47964
- import path25 from "node:path";
49340
+ import { lstat as lstat12, mkdir as mkdir12, open as open11, readFile as readFile10 } from "node:fs/promises";
49341
+ import path26 from "node:path";
47965
49342
 
47966
49343
  // src/agent-fabric-service.ts
47967
- import { lstat as lstat10, mkdir as mkdir11, realpath as realpath9 } from "node:fs/promises";
49344
+ import { lstat as lstat11, mkdir as mkdir11, realpath as realpath9 } from "node:fs/promises";
47968
49345
  import { watch } from "node:fs";
47969
- import path24 from "node:path";
49346
+ import path25 from "node:path";
47970
49347
 
47971
49348
  // src/agent-runtime-identity.ts
47972
- import { createHash as createHash19, randomBytes as randomBytes7, randomUUID as randomUUID14, timingSafeEqual as timingSafeEqual4 } from "node:crypto";
49349
+ import { createHash as createHash19, randomBytes as randomBytes8, randomUUID as randomUUID14, timingSafeEqual as timingSafeEqual4 } from "node:crypto";
47973
49350
 
47974
49351
  // src/agent-fabric-state.ts
47975
49352
  import { randomUUID as randomUUID13 } from "node:crypto";
47976
- import { mkdir as mkdir10, open as open10, rename as rename7, unlink as unlink2 } from "node:fs/promises";
47977
- import path23 from "node:path";
49353
+ import { mkdir as mkdir10, open as open10, rename as rename7, unlink as unlink3 } from "node:fs/promises";
49354
+ import path24 from "node:path";
47978
49355
  var queues = /* @__PURE__ */ new Map();
47979
49356
  var FabricStateFile = class {
47980
- constructor(file2, maxBytes, parse3) {
49357
+ constructor(file2, maxBytes, parse4) {
47981
49358
  this.maxBytes = maxBytes;
47982
- this.parse = parse3;
47983
- this.file = path23.resolve(file2);
49359
+ this.parse = parse4;
49360
+ this.file = path24.resolve(file2);
47984
49361
  }
47985
49362
  maxBytes;
47986
49363
  parse;
@@ -48024,7 +49401,7 @@ var FabricStateFile = class {
48024
49401
  }
48025
49402
  update(fn, create) {
48026
49403
  return this.serial(async () => {
48027
- if (create) await mkdir10(path23.dirname(this.file), { recursive: true });
49404
+ if (create) await mkdir10(path24.dirname(this.file), { recursive: true });
48028
49405
  const lockPath = this.file + ".lock";
48029
49406
  const token = randomUUID13();
48030
49407
  const lock = await open10(lockPath, "wx", 384).catch((error62) => {
@@ -48055,7 +49432,7 @@ var FabricStateFile = class {
48055
49432
  }
48056
49433
  await rename7(temporary, this.file);
48057
49434
  } finally {
48058
- await unlink2(temporary).catch((error62) => {
49435
+ await unlink3(temporary).catch((error62) => {
48059
49436
  if (error62.code !== "ENOENT") throw error62;
48060
49437
  });
48061
49438
  }
@@ -48069,7 +49446,7 @@ var FabricStateFile = class {
48069
49446
  } finally {
48070
49447
  await current2.close();
48071
49448
  }
48072
- await unlink2(lockPath);
49449
+ await unlink3(lockPath);
48073
49450
  }
48074
49451
  });
48075
49452
  }
@@ -48123,7 +49500,7 @@ var AgentRuntimeIdentityStore = class {
48123
49500
  return this.serial((state) => {
48124
49501
  if (state.bindings.length >= MAX_BINDINGS) throw Error("RUNTIME_IDENTITY_LIMIT");
48125
49502
  const runtimeId = "rt-" + randomUUID14();
48126
- const runtimeKey = randomBytes7(32).toString("base64url");
49503
+ const runtimeKey = randomBytes8(32).toString("base64url");
48127
49504
  const now = this.now();
48128
49505
  state.bindings.push({ runtimeId, keyHash: encodedDigest(runtimeKey), createdAt: now, lastUsedAt: now, revoked: false });
48129
49506
  return { runtimeId, runtimeKey };
@@ -48668,9 +50045,9 @@ var WorkerRequest = external_exports.discriminatedUnion("operation", [
48668
50045
  var AgentFabricService = class _AgentFabricService {
48669
50046
  constructor(directory, controllerId) {
48670
50047
  this.directory = directory;
48671
- this.identities = new AgentRuntimeIdentityStore(path24.join(directory, "identities.json"));
50048
+ this.identities = new AgentRuntimeIdentityStore(path25.join(directory, "identities.json"));
48672
50049
  this.mailbox = new AgentWorkerMailbox(
48673
- path24.join(directory, "mailbox.json"),
50050
+ path25.join(directory, "mailbox.json"),
48674
50051
  controllerId,
48675
50052
  this.identities,
48676
50053
  void 0,
@@ -48685,21 +50062,21 @@ var AgentFabricService = class _AgentFabricService {
48685
50062
  closed = false;
48686
50063
  static async open(directory, controllerId, device = null, initialize = true) {
48687
50064
  const expected = Binding.parse({ version: 1, controllerId, device, initialized: false });
48688
- const absolute2 = path24.resolve(directory);
48689
- for (let current2 = absolute2; ; current2 = path24.dirname(current2)) {
50065
+ const absolute2 = path25.resolve(directory);
50066
+ for (let current2 = absolute2; ; current2 = path25.dirname(current2)) {
48690
50067
  try {
48691
- if ((await lstat10(current2)).isSymbolicLink()) throw Error("FABRIC_DIRECTORY_INVALID");
50068
+ if ((await lstat11(current2)).isSymbolicLink()) throw Error("FABRIC_DIRECTORY_INVALID");
48692
50069
  } catch (error62) {
48693
50070
  if (error62.code !== "ENOENT") throw error62;
48694
50071
  }
48695
- if (path24.dirname(current2) === current2) break;
50072
+ if (path25.dirname(current2) === current2) break;
48696
50073
  }
48697
50074
  if (initialize) await mkdir11(absolute2, { recursive: true, mode: 448 });
48698
- if (!(await lstat10(absolute2)).isDirectory() || (await realpath9(absolute2)).toLowerCase() !== absolute2.toLowerCase())
50075
+ if (!(await lstat11(absolute2)).isDirectory() || (await realpath9(absolute2)).toLowerCase() !== absolute2.toLowerCase())
48699
50076
  throw Error("FABRIC_DIRECTORY_INVALID");
48700
50077
  const present = /* @__PURE__ */ new Set();
48701
50078
  for (const name2 of ["binding.json", "mailbox.json", "identities.json"]) {
48702
- const file2 = await lstat10(path24.join(absolute2, name2)).catch((error62) => {
50079
+ const file2 = await lstat11(path25.join(absolute2, name2)).catch((error62) => {
48703
50080
  if (error62.code === "ENOENT") return null;
48704
50081
  throw error62;
48705
50082
  });
@@ -48707,7 +50084,7 @@ var AgentFabricService = class _AgentFabricService {
48707
50084
  if (file2) present.add(name2);
48708
50085
  }
48709
50086
  if (!present.has("binding.json") && present.size) throw Error("FABRIC_BINDING_MISSING");
48710
- const binding2 = new FabricStateFile(path24.join(absolute2, "binding.json"), 2048, (value) => Binding.parse(value));
50087
+ const binding2 = new FabricStateFile(path25.join(absolute2, "binding.json"), 2048, (value) => Binding.parse(value));
48711
50088
  const service2 = new _AgentFabricService(absolute2, controllerId);
48712
50089
  await binding2.update(async (state) => {
48713
50090
  if (state.controllerId !== expected.controllerId || JSON.stringify(state.device) !== JSON.stringify(expected.device))
@@ -48722,7 +50099,7 @@ var AgentFabricService = class _AgentFabricService {
48722
50099
  state.initialized = true;
48723
50100
  }
48724
50101
  const snapshot2 = await service2.mailbox.snapshot();
48725
- if (snapshot2.workers.some((worker) => worker.runtimeId !== null)) await lstat10(path24.join(absolute2, "identities.json"));
50102
+ if (snapshot2.workers.some((worker) => worker.runtimeId !== null)) await lstat11(path25.join(absolute2, "identities.json"));
48726
50103
  }, initialize ? () => expected : void 0);
48727
50104
  return service2;
48728
50105
  }
@@ -48809,19 +50186,19 @@ var Delivery = external_exports.strictObject({ capability: external_exports.stri
48809
50186
  async function openNativeFabric(stateDirectory, enrollment, box, initialize = true) {
48810
50187
  const controllerId = "device-" + external_exports.string().uuid().parse(enrollment.deviceId).toLowerCase();
48811
50188
  const tenantId = external_exports.string().uuid().parse(enrollment.tenantId).toLowerCase();
48812
- const parent = path25.join(stateDirectory, ".local-commander"), marker = path25.join(parent, "fabric-established.json");
50189
+ const parent = path26.join(stateDirectory, ".local-commander"), marker = path26.join(parent, "fabric-established.json");
48813
50190
  try {
48814
50191
  await mkdir12(parent, { mode: 448 });
48815
50192
  } catch (error62) {
48816
50193
  if (error62.code !== "EEXIST") throw error62;
48817
50194
  }
48818
- const parentInfo = await lstat11(parent);
50195
+ const parentInfo = await lstat12(parent);
48819
50196
  if (!parentInfo.isDirectory() || parentInfo.isSymbolicLink()) throw Error("FABRIC_DIRECTORY_INVALID");
48820
50197
  const expected = JSON.stringify({ version: 1, controllerId, tenantId });
48821
50198
  let fresh = false;
48822
50199
  try {
48823
- const info = await lstat11(marker);
48824
- if (!info.isFile() || info.isSymbolicLink() || info.size > 2048 || await readFile9(marker, "utf8") !== expected)
50200
+ const info = await lstat12(marker);
50201
+ if (!info.isFile() || info.isSymbolicLink() || info.size > 2048 || await readFile10(marker, "utf8") !== expected)
48825
50202
  throw Error("FABRIC_BINDING_CHANGED");
48826
50203
  } catch (error62) {
48827
50204
  if (error62.code !== "ENOENT" || !initialize) throw error62;
@@ -48835,22 +50212,22 @@ async function openNativeFabric(stateDirectory, enrollment, box, initialize = tr
48835
50212
  fresh = true;
48836
50213
  }
48837
50214
  const service2 = await AgentFabricService.open(
48838
- path25.join(stateDirectory, ".local-commander", "fabric"),
50215
+ path26.join(stateDirectory, ".local-commander", "fabric"),
48839
50216
  controllerId,
48840
50217
  { deviceId: enrollment.deviceId.toLowerCase(), enrollmentEvidenceRef: "enrollment-" + tenantId },
48841
50218
  fresh
48842
50219
  );
48843
50220
  const purpose = "native-fabric:" + tenantId + ":" + controllerId;
48844
- const credentialFile = (workerId) => path25.join(service2.directory, external_exports.string().uuid().parse(workerId) + ".capability");
50221
+ const credentialFile = (workerId) => path26.join(service2.directory, external_exports.string().uuid().parse(workerId) + ".capability");
48845
50222
  const decode4 = (value) => {
48846
50223
  const credential = Credential.parse(JSON.parse(box.open(Buffer.from(value, "base64"), purpose).toString("utf8")));
48847
50224
  if (credential.controllerId !== controllerId) throw Error("FABRIC_WORKER_DENIED");
48848
50225
  return credential;
48849
50226
  };
48850
50227
  async function capability(workerId) {
48851
- const file2 = credentialFile(workerId), info = await lstat11(file2);
50228
+ const file2 = credentialFile(workerId), info = await lstat12(file2);
48852
50229
  if (!info.isFile() || info.isSymbolicLink() || info.size > 4096) throw Error("FABRIC_CREDENTIAL_UNKNOWN");
48853
- const encoded = await readFile9(file2, "utf8");
50230
+ const encoded = await readFile10(file2, "utf8");
48854
50231
  if (decode4(encoded).workerId !== workerId) throw Error("FABRIC_WORKER_DENIED");
48855
50232
  return encoded;
48856
50233
  }
@@ -48942,7 +50319,7 @@ async function readFabricRequest(input2 = process.stdin) {
48942
50319
 
48943
50320
  // agent/src/supervisor-liveness.ts
48944
50321
  import { spawn as spawn6 } from "node:child_process";
48945
- import path26 from "node:path";
50322
+ import path27 from "node:path";
48946
50323
  import { setTimeout as delay3 } from "node:timers/promises";
48947
50324
  var ROW = /^"([^"]+)","(\d{1,10})"/;
48948
50325
  function parseTasklist(output2, image) {
@@ -48957,7 +50334,7 @@ function parseTasklist(output2, image) {
48957
50334
  }
48958
50335
  function listProcesses(image, timeoutMs2 = 5e3) {
48959
50336
  if (process.platform !== "win32" || !/^[A-Za-z0-9._-]{1,64}\.exe$/i.test(image)) return Promise.resolve(null);
48960
- const tasklist = path26.join(process.env.SystemRoot || "C:\\Windows", "System32", "tasklist.exe");
50337
+ const tasklist = path27.join(process.env.SystemRoot || "C:\\Windows", "System32", "tasklist.exe");
48961
50338
  return new Promise((resolve) => {
48962
50339
  let output2 = "", settled = false;
48963
50340
  const finish = (value) => {
@@ -48986,8 +50363,8 @@ function listProcesses(image, timeoutMs2 = 5e3) {
48986
50363
  }
48987
50364
  function supervisorLiveness(helperPath, options = {}) {
48988
50365
  if (process.platform === "linux" && !options.list) return linuxSupervisorLiveness;
48989
- if (process.platform === "darwin" && !options.list) return (pids, _linux, darwin) => darwinSupervisorLiveness(path26.join(path26.dirname(helperPath), "posix-host"), pids, darwin);
48990
- const image = path26.basename(helperPath), waitMs = options.waitMs ?? 1e4, pollMs = options.pollMs ?? 500, list = options.list ?? listProcesses;
50366
+ if (process.platform === "darwin" && !options.list) return (pids, _linux, darwin) => darwinSupervisorLiveness(path27.join(path27.dirname(helperPath), "posix-host"), pids, darwin);
50367
+ const image = path27.basename(helperPath), waitMs = options.waitMs ?? 1e4, pollMs = options.pollMs ?? 500, list = options.list ?? listProcesses;
48991
50368
  return async (pids) => {
48992
50369
  const deadline = Date.now() + waitMs;
48993
50370
  for (; ; ) {
@@ -49002,14 +50379,14 @@ function supervisorLiveness(helperPath, options = {}) {
49002
50379
 
49003
50380
  // agent/src/content-audit.ts
49004
50381
  import { createReadStream } from "node:fs";
49005
- import { appendFile, lstat as lstat12, mkdir as mkdir13, open as open12, readdir as readdir5, readFile as readFile10, rename as rename8, rm as rm8, writeFile as writeFile4 } from "node:fs/promises";
49006
- import path27 from "node:path";
50382
+ import { appendFile, lstat as lstat13, mkdir as mkdir13, open as open12, readdir as readdir6, readFile as readFile11, rename as rename8, rm as rm9, writeFile as writeFile4 } from "node:fs/promises";
50383
+ import path28 from "node:path";
49007
50384
  import { performance as performance3 } from "node:perf_hooks";
49008
50385
  import { createInterface as createInterface2 } from "node:readline";
49009
- import { randomBytes as randomBytes9 } from "node:crypto";
50386
+ import { randomBytes as randomBytes10 } from "node:crypto";
49010
50387
 
49011
50388
  // src/audit-crypto.ts
49012
- import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, createHash as createHash20, randomBytes as randomBytes8 } from "node:crypto";
50389
+ import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, createHash as createHash20, randomBytes as randomBytes9 } from "node:crypto";
49013
50390
  import { promisify as promisify3 } from "node:util";
49014
50391
  import { gunzipSync, gzip, gzipSync } from "node:zlib";
49015
50392
  var gzipAsync = promisify3(gzip);
@@ -49061,7 +50438,7 @@ async function encryptAuditRecordAsync(record2, keyInput, keyId2) {
49061
50438
  function sealCompressed(compressed, keyInput, keyId2) {
49062
50439
  const key = parseAuditRecoveryKey(keyInput);
49063
50440
  const kid = keyId2?.trim() || auditRecoveryKeyId(key);
49064
- const iv = randomBytes8(IV_BYTES);
50441
+ const iv = randomBytes9(IV_BYTES);
49065
50442
  try {
49066
50443
  const cipher = createCipheriv3("aes-256-gcm", key, iv, { authTagLength: TAG_BYTES });
49067
50444
  cipher.setAAD(additionalData(kid));
@@ -49172,17 +50549,17 @@ var FILE = /^(full|metrics)-(\d{4}-\d{2}-\d{2})\.jsonl$/;
49172
50549
  var PAUSED_FILE = "paused.json";
49173
50550
  var DAY_MS = 864e5;
49174
50551
  function contentAuditDirectory(stateDir) {
49175
- return path27.join(path27.dirname(path27.resolve(stateDir)), "Audit");
50552
+ return path28.join(path28.dirname(path28.resolve(stateDir)), "Audit");
49176
50553
  }
49177
50554
  async function plainDirectory(dir) {
49178
50555
  await mkdir13(dir, { recursive: true, mode: 448 });
49179
- const info = await lstat12(dir);
50556
+ const info = await lstat13(dir);
49180
50557
  if (info.isSymbolicLink() || !info.isDirectory()) throw Error("AUDIT_DIRECTORY_INVALID");
49181
50558
  }
49182
50559
  async function auditFiles(dir) {
49183
50560
  let names;
49184
50561
  try {
49185
- names = await readdir5(dir);
50562
+ names = await readdir6(dir);
49186
50563
  } catch (error62) {
49187
50564
  if (error62.code === "ENOENT") return [];
49188
50565
  throw error62;
@@ -49191,18 +50568,18 @@ async function auditFiles(dir) {
49191
50568
  for (const name2 of names) {
49192
50569
  const match = FILE.exec(name2);
49193
50570
  if (!match) continue;
49194
- const info = await lstat12(path27.join(dir, name2));
50571
+ const info = await lstat13(path28.join(dir, name2));
49195
50572
  if (info.isFile()) files.push({ name: name2, kind: match[1], day: match[2], bytes: info.size });
49196
50573
  }
49197
50574
  return files.sort((a, b) => a.name.localeCompare(b.name));
49198
50575
  }
49199
50576
  async function writeJsonAtomic(file2, value) {
49200
- const temp = `${file2}.${randomBytes9(6).toString("hex")}.tmp`;
50577
+ const temp = `${file2}.${randomBytes10(6).toString("hex")}.tmp`;
49201
50578
  try {
49202
50579
  await writeFile4(temp, JSON.stringify(value) + "\n", { flag: "wx", mode: 384 });
49203
50580
  await rename8(temp, file2);
49204
50581
  } finally {
49205
- await rm8(temp, { force: true }).catch(() => {
50582
+ await rm9(temp, { force: true }).catch(() => {
49206
50583
  });
49207
50584
  }
49208
50585
  }
@@ -49229,7 +50606,7 @@ var ContentAudit = class _ContentAudit {
49229
50606
  skipped = 0;
49230
50607
  closed = false;
49231
50608
  static async open(options) {
49232
- const dir = path27.resolve(options.directory);
50609
+ const dir = path28.resolve(options.directory);
49233
50610
  await plainDirectory(dir);
49234
50611
  const audit = new _ContentAudit(
49235
50612
  dir,
@@ -49238,7 +50615,7 @@ var ContentAudit = class _ContentAudit {
49238
50615
  { retentionDays: options.retentionDays ?? AUDIT_RETENTION_DAYS, maxBytes: options.maxBytes ?? AUDIT_MAX_BYTES },
49239
50616
  options.now ?? (() => /* @__PURE__ */ new Date())
49240
50617
  );
49241
- await rm8(path27.join(dir, PAUSED_FILE), { force: true });
50618
+ await rm9(path28.join(dir, PAUSED_FILE), { force: true });
49242
50619
  await audit.rollover(audit.now());
49243
50620
  if (audit.usedBytes >= audit.limits.maxBytes) await audit.pause("QUOTA_EXCEEDED");
49244
50621
  return audit;
@@ -49308,8 +50685,8 @@ var ContentAudit = class _ContentAudit {
49308
50685
  await this.pause("QUOTA_EXCEEDED");
49309
50686
  return;
49310
50687
  }
49311
- await appendFile(path27.join(this.dir, `full-${day}.jsonl`), line, { mode: 384 });
49312
- await appendFile(path27.join(this.dir, `metrics-${day}.jsonl`), metrics, { mode: 384 });
50688
+ await appendFile(path28.join(this.dir, `full-${day}.jsonl`), line, { mode: 384 });
50689
+ await appendFile(path28.join(this.dir, `metrics-${day}.jsonl`), metrics, { mode: 384 });
49313
50690
  this.usedBytes += bytes3;
49314
50691
  }
49315
50692
  /** Daily retention runs on the first write of a new day; no timer or background scan. */
@@ -49318,7 +50695,7 @@ var ContentAudit = class _ContentAudit {
49318
50695
  const cutoff = new Date(at.getTime() - this.limits.retentionDays * DAY_MS).toISOString().slice(0, 10);
49319
50696
  let used = 0;
49320
50697
  for (const file2 of await auditFiles(this.dir)) {
49321
- if (file2.day <= cutoff) await rm8(path27.join(this.dir, file2.name), { force: true });
50698
+ if (file2.day <= cutoff) await rm9(path28.join(this.dir, file2.name), { force: true });
49322
50699
  else used += file2.bytes;
49323
50700
  }
49324
50701
  this.usedBytes = used;
@@ -49326,7 +50703,7 @@ var ContentAudit = class _ContentAudit {
49326
50703
  async pause(reason) {
49327
50704
  if (this.paused) return;
49328
50705
  this.paused = reason;
49329
- await writeJsonAtomic(path27.join(this.dir, PAUSED_FILE), { reason, at: this.now().toISOString() });
50706
+ await writeJsonAtomic(path28.join(this.dir, PAUSED_FILE), { reason, at: this.now().toISOString() });
49330
50707
  }
49331
50708
  };
49332
50709
  function percentiles(values) {
@@ -49348,13 +50725,13 @@ async function* jsonLines(file2) {
49348
50725
  }
49349
50726
  var count2 = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : 0;
49350
50727
  async function summarizeContentAudit(directory, key) {
49351
- const dir = path27.resolve(directory);
50728
+ const dir = path28.resolve(directory);
49352
50729
  const files = await auditFiles(dir);
49353
50730
  const days = /* @__PURE__ */ new Map();
49354
50731
  const sizes = [];
49355
50732
  const timings = [];
49356
50733
  for (const file2 of files.filter((f) => f.kind === "metrics")) {
49357
- for await (const line of jsonLines(path27.join(dir, file2.name))) {
50734
+ for await (const line of jsonLines(path28.join(dir, file2.name))) {
49358
50735
  let day = days.get(file2.day);
49359
50736
  if (!day) {
49360
50737
  day = { day: file2.day, records: 0, failed: 0, rawBytes: 0, sanitizedBytes: 0, compressedBytes: 0, envelopeBytes: 0 };
@@ -49374,7 +50751,7 @@ async function summarizeContentAudit(directory, key) {
49374
50751
  }
49375
50752
  let paused = null;
49376
50753
  try {
49377
- const value = JSON.parse(await readFile10(path27.join(dir, PAUSED_FILE), "utf8"));
50754
+ const value = JSON.parse(await readFile11(path28.join(dir, PAUSED_FILE), "utf8"));
49378
50755
  if (typeof value.reason === "string" && typeof value.at === "string") paused = { reason: value.reason.slice(0, 40), at: value.at.slice(0, 40) };
49379
50756
  } catch {
49380
50757
  }
@@ -49382,7 +50759,7 @@ async function summarizeContentAudit(directory, key) {
49382
50759
  const newest = files.filter((f) => f.kind === "full").at(-1);
49383
50760
  if (key && newest) {
49384
50761
  const tail = [];
49385
- for await (const line of jsonLines(path27.join(dir, newest.name))) {
50762
+ for await (const line of jsonLines(path28.join(dir, newest.name))) {
49386
50763
  tail.push(line);
49387
50764
  if (tail.length > 5) tail.shift();
49388
50765
  }
@@ -49416,10 +50793,10 @@ async function summarizeContentAudit(directory, key) {
49416
50793
  };
49417
50794
  }
49418
50795
  async function restoreContentAudit(input2, output2, key) {
49419
- const handle = await open12(path27.resolve(output2), "wx", 384);
50796
+ const handle = await open12(path28.resolve(output2), "wx", 384);
49420
50797
  let records = 0, failed = 0;
49421
50798
  try {
49422
- for await (const line of jsonLines(path27.resolve(input2))) {
50799
+ for await (const line of jsonLines(path28.resolve(input2))) {
49423
50800
  try {
49424
50801
  await handle.appendFile(JSON.stringify(decryptAuditRecord(line, key)) + "\n");
49425
50802
  records += 1;
@@ -49434,7 +50811,7 @@ async function restoreContentAudit(input2, output2, key) {
49434
50811
  }
49435
50812
 
49436
50813
  // agent/src/main.ts
49437
- var AGENT_VERSION2 = true ? "0.3.45" : "0.3.2";
50814
+ var AGENT_VERSION2 = true ? "0.3.47" : "0.3.2";
49438
50815
  var NETWORK_PUBLIC_KEY = true ? "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAvmu+81vWtJBQDZNHcAIW\nzCSxpG+R9RBsum2df5mP2cOW+wyUDTpnYquFge1qgI5YYTF96j0xCyXL8B9FeNWs\n939opWNmv53j+CQlS4cEIQhBbZSCu0eC4icsVEzBhvf68MB+E668SOtZBcVTEnyh\n96PTcupxS10rQJBWDinbKBXRC2gvGYeu01rWa/nsrndy4vAYP5t3yQtdOC8e8mr0\n+2Mg2Qhiq+KiTCtDd+L9oXvoLqqJYbzUIveNGha25AWxF1Weblp0gOM87hell5gV\nK7q4ZLUq/wBRGYNmQRdLyV7/WRE1FFPSW21/SBZQ/5aU4UqJU/MjMcrJUrnRKngz\nYKmo0czkxS3N7Q2KVxomgR1AQSuQFKMrboZYKjShADp9RIYUxzs7cYg51Of5PnHh\n6Ax+VevDGfzjMD+yHuyxYZqCtX4OwgolJxz63UQbzKlris+8xb5lLYTbIuz90Pss\nn6HK/F5May25c6oMmS3nh/NsiZopL1OvdtWKTt1L4WlRAgMBAAE=\n-----END PUBLIC KEY-----\n" : "";
49439
50816
  var AI_CONNECTION_SHIPPED = false;
49440
50817
  function processAlive(pid) {
@@ -49448,7 +50825,7 @@ function processAlive(pid) {
49448
50825
  }
49449
50826
  async function claimAgentProcess(stateDir, runtimeDir, version2) {
49450
50827
  await mkdir14(stateDir, { recursive: true });
49451
- const file2 = path28.join(stateDir, "agent-process.json");
50828
+ const file2 = path29.join(stateDir, "agent-process.json");
49452
50829
  for (let attempt = 0; attempt < 2; attempt += 1) {
49453
50830
  try {
49454
50831
  const handle = await open13(file2, "wx", 384);
@@ -49459,8 +50836,8 @@ async function claimAgentProcess(stateDir, runtimeDir, version2) {
49459
50836
  }
49460
50837
  return async () => {
49461
50838
  try {
49462
- const current2 = JSON.parse(await readFile11(file2, "utf8"));
49463
- if (current2.pid === process.pid) await rm9(file2, { force: true });
50839
+ const current2 = JSON.parse(await readFile12(file2, "utf8"));
50840
+ if (current2.pid === process.pid) await rm10(file2, { force: true });
49464
50841
  } catch {
49465
50842
  }
49466
50843
  };
@@ -49468,12 +50845,12 @@ async function claimAgentProcess(stateDir, runtimeDir, version2) {
49468
50845
  if (!error62 || typeof error62 !== "object" || !("code" in error62) || error62.code !== "EEXIST") throw error62;
49469
50846
  let stale = true;
49470
50847
  try {
49471
- const current2 = JSON.parse(await readFile11(file2, "utf8"));
50848
+ const current2 = JSON.parse(await readFile12(file2, "utf8"));
49472
50849
  stale = typeof current2.pid !== "number" || !processAlive(current2.pid);
49473
50850
  } catch {
49474
50851
  }
49475
50852
  if (!stale) throw Error("AGENT_ALREADY_RUNNING");
49476
- await rm9(file2, { force: true });
50853
+ await rm10(file2, { force: true });
49477
50854
  }
49478
50855
  }
49479
50856
  throw Error("AGENT_ALREADY_RUNNING");
@@ -49724,10 +51101,10 @@ async function openContentAudit(store, stateDir) {
49724
51101
  async function main() {
49725
51102
  if (!["win32", "linux", "darwin"].includes(process.platform)) throw Error("PLATFORM_UNSUPPORTED");
49726
51103
  const appData = process.env.LC_AGENT_DATA_DIR ?? (process.platform === "win32" ? process.env.LOCALAPPDATA : posixDataHome());
49727
- if (!appData || !path28.isAbsolute(appData)) throw Error("APP_DATA_MISSING");
49728
- const stateDir = process.env.LC_AGENT_STATE_DIR ?? path28.join(appData, "LocalCommander", "Agent");
49729
- const binaryDir = path28.dirname(process.platform === "win32" ? process.execPath : await realpath10(process.execPath));
49730
- const ownerBridgePath = process.env.LC_OWNER_BRIDGE ?? path28.join(binaryDir, process.platform === "win32" ? "OwnerBridge.exe" : "owner-store");
51104
+ if (!appData || !path29.isAbsolute(appData)) throw Error("APP_DATA_MISSING");
51105
+ const stateDir = process.env.LC_AGENT_STATE_DIR ?? path29.join(appData, "LocalCommander", "Agent");
51106
+ const binaryDir = path29.dirname(process.platform === "win32" ? process.execPath : await realpath10(process.execPath));
51107
+ const ownerBridgePath = process.env.LC_OWNER_BRIDGE ?? path29.join(binaryDir, process.platform === "win32" ? "OwnerBridge.exe" : "owner-store");
49731
51108
  const store = await WindowsPrivateStore.open(stateDir, ownerBridgePath);
49732
51109
  const command = process.argv[2] ?? "run";
49733
51110
  if (process.platform !== "win32" && (command.startsWith("guard-") || command.startsWith("network-"))) throw Error("FEATURE_PLATFORM_UNSUPPORTED");
@@ -49737,7 +51114,7 @@ async function main() {
49737
51114
  const pairing = new PairingClient(store, { controlPlaneOrigin: origin, agentVersion: AGENT_VERSION2 });
49738
51115
  const begun = await pairing.begin();
49739
51116
  process.stdout.write(JSON.stringify({ approvalUrl: begun.approvalUrl, confirmationCode: begun.confirmationCode, expiresAt: begun.expiresAt.toISOString() }) + "\n");
49740
- await pairing.waitAndComplete(begun, os7.hostname().slice(0, 120));
51117
+ await pairing.waitAndComplete(begun, os8.hostname().slice(0, 120));
49741
51118
  process.stdout.write("DEVICE_PAIRED\n");
49742
51119
  return;
49743
51120
  }
@@ -49822,7 +51199,7 @@ async function main() {
49822
51199
  }
49823
51200
  if (command === "efficiency-report") {
49824
51201
  if (args.length) throw Error("AGENT_COMMAND_INVALID");
49825
- const ledger = await OptimizationLedger.open(path28.join(stateDir, "optimization"));
51202
+ const ledger = await OptimizationLedger.open(path29.join(stateDir, "optimization"));
49826
51203
  try {
49827
51204
  process.stdout.write(JSON.stringify(await ledger.report(), null, 2) + "\n");
49828
51205
  } finally {
@@ -49832,7 +51209,7 @@ async function main() {
49832
51209
  }
49833
51210
  if (command === "guard-configure") {
49834
51211
  if (args.length !== 1) throw Error("AGENT_COMMAND_INVALID");
49835
- const filename = await (await import("node:fs/promises")).realpath(path28.resolve(args[0]));
51212
+ const filename = await (await import("node:fs/promises")).realpath(path29.resolve(args[0]));
49836
51213
  const input2 = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readWindowsFile(ownerBridgePath, filename, 2e5)));
49837
51214
  if (!input2 || typeof input2 !== "object" || Object.keys(input2).sort().join(",") !== "compact,settings") throw Error("GUARD_CONFIGURATION_INVALID");
49838
51215
  await store.configureGuard(input2.settings, input2.compact);
@@ -49851,7 +51228,7 @@ async function main() {
49851
51228
  }
49852
51229
  if (command === "guard-evidence") {
49853
51230
  if (args.length) throw Error("AGENT_COMMAND_INVALID");
49854
- const journal = await NativeJournal.open(path28.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
51231
+ const journal = await NativeJournal.open(path29.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
49855
51232
  try {
49856
51233
  process.stdout.write(JSON.stringify(await journal.guardEvidence()) + "\n");
49857
51234
  } finally {
@@ -49863,7 +51240,7 @@ async function main() {
49863
51240
  if (args.length !== (command === "guard-export" ? 0 : 1)) throw Error("AGENT_COMMAND_INVALID");
49864
51241
  const identity = await store.load();
49865
51242
  if (!identity?.enrollment) throw Error("ENROLLMENT_MISSING");
49866
- const journal = await NativeJournal.open(path28.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
51243
+ const journal = await NativeJournal.open(path29.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
49867
51244
  try {
49868
51245
  const { tenantId, deviceId } = identity.enrollment;
49869
51246
  const records = (await journal.guardEvidence()).filter((record2) => record2.tenantId === tenantId && record2.deviceId === deviceId);
@@ -49941,27 +51318,27 @@ async function main() {
49941
51318
  if (args.length) throw Error("AGENT_COMMAND_INVALID");
49942
51319
  if (!(await store.load())?.enrollment) throw Error("ENROLLMENT_MISSING");
49943
51320
  const releaseProcess = await claimAgentProcess(stateDir, binaryDir, AGENT_VERSION2);
49944
- const monitor = new ProductionMonitor(path28.join(appData, "LocalCommander", "Monitor"), stateDir, AGENT_VERSION2);
51321
+ const monitor = new ProductionMonitor(path29.join(appData, "LocalCommander", "Monitor"), stateDir, AGENT_VERSION2);
49945
51322
  const publishMonitor = () => monitor.flush().catch(() => {
49946
51323
  process.stderr.write("MONITOR_WRITE_FAILED\n");
49947
51324
  });
49948
51325
  await publishMonitor();
49949
51326
  try {
49950
51327
  const journal = await NativeJournal.open(
49951
- path28.join(stateDir, "journal"),
51328
+ path29.join(stateDir, "journal"),
49952
51329
  new SecretBox({ "1": await store.loadDataKey() }),
49953
- process.platform === "win32" ? {} : { lockHelper: path28.join(binaryDir, "posix-host") }
51330
+ process.platform === "win32" ? {} : { lockHelper: path29.join(binaryDir, "posix-host") }
49954
51331
  );
49955
51332
  const ledgerLoss = () => {
49956
51333
  process.stderr.write("OPTIMIZATION_TELEMETRY_INCOMPLETE\n");
49957
51334
  };
49958
51335
  const efficiencyLedger = await new OptionalWork(ledgerLoss, 1e3, 1).run(
49959
- () => OptimizationLedger.open(path28.join(stateDir, "optimization")),
51336
+ () => OptimizationLedger.open(path29.join(stateDir, "optimization")),
49960
51337
  void 0,
49961
51338
  (ledger) => ledger.close()
49962
51339
  );
49963
51340
  try {
49964
- const helperPath = process.env.LC_JOB_HOST ?? path28.join(binaryDir, process.platform === "win32" ? "JobHost.exe" : "job-host.mjs");
51341
+ const helperPath = process.env.LC_JOB_HOST ?? path29.join(binaryDir, process.platform === "win32" ? "JobHost.exe" : "job-host.mjs");
49965
51342
  const tools = new NativeTools({ stateDirectory: stateDir, helperPath, ownerBridgePath, programs: await store.loadPrograms() });
49966
51343
  const stop = new AbortController();
49967
51344
  process.once("SIGINT", () => stop.abort());
@@ -50032,7 +51409,7 @@ async function main() {
50032
51409
  await releaseProcess();
50033
51410
  }
50034
51411
  }
50035
- var entrypoint = process.argv[1] && (process.platform === "win32" ? path28.resolve(process.argv[1]) : await realpath10(process.argv[1]).catch(() => null));
51412
+ var entrypoint = process.argv[1] && (process.platform === "win32" ? path29.resolve(process.argv[1]) : await realpath10(process.argv[1]).catch(() => null));
50036
51413
  if (entrypoint === fileURLToPath(import.meta.url)) {
50037
51414
  void main().catch((error62) => {
50038
51415
  const code = error62 instanceof Error && /^[A-Z0-9_]{1,64}$/.test(error62.message) ? error62.message : "AGENT_START_FAILED";