local-commander-agent 0.3.3 → 0.3.5

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
@@ -19,8 +19,8 @@ var __commonJS = (cb, mod) => function __require2() {
19
19
  }
20
20
  };
21
21
  var __export = (target, all) => {
22
- for (var name in all)
23
- __defProp(target, name, { get: all[name], enumerable: true });
22
+ for (var name2 in all)
23
+ __defProp(target, name2, { get: all[name2], enumerable: true });
24
24
  };
25
25
  var __copyProps = (to, from, except, desc) => {
26
26
  if (from && typeof from === "object" || typeof from === "function") {
@@ -2121,9 +2121,9 @@ var require_extension = __commonJS({
2121
2121
  "node_modules/ws/lib/extension.js"(exports, module) {
2122
2122
  "use strict";
2123
2123
  var { tokenChars } = require_validation();
2124
- function push(dest, name, elem) {
2125
- if (dest[name] === void 0) dest[name] = [elem];
2126
- else dest[name].push(elem);
2124
+ function push(dest, name2, elem) {
2125
+ if (dest[name2] === void 0) dest[name2] = [elem];
2126
+ else dest[name2].push(elem);
2127
2127
  }
2128
2128
  function parse3(header) {
2129
2129
  const offers = /* @__PURE__ */ Object.create(null);
@@ -2149,12 +2149,12 @@ var require_extension = __commonJS({
2149
2149
  throw new SyntaxError(`Unexpected character at index ${i}`);
2150
2150
  }
2151
2151
  if (end === -1) end = i;
2152
- const name = header.slice(start, end);
2152
+ const name2 = header.slice(start, end);
2153
2153
  if (code === 44) {
2154
- push(offers, name, params);
2154
+ push(offers, name2, params);
2155
2155
  params = /* @__PURE__ */ Object.create(null);
2156
2156
  } else {
2157
- extensionName = name;
2157
+ extensionName = name2;
2158
2158
  }
2159
2159
  start = end = -1;
2160
2160
  } else {
@@ -2278,7 +2278,7 @@ var require_websocket = __commonJS({
2278
2278
  var http = __require("http");
2279
2279
  var net = __require("net");
2280
2280
  var tls = __require("tls");
2281
- var { randomBytes: randomBytes4, createHash: createHash9 } = __require("crypto");
2281
+ var { randomBytes: randomBytes4, createHash: createHash10 } = __require("crypto");
2282
2282
  var { Duplex, Readable } = __require("stream");
2283
2283
  var { URL: URL2 } = __require("url");
2284
2284
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -2959,7 +2959,7 @@ var require_websocket = __commonJS({
2959
2959
  abortHandshake(websocket, socket, "Invalid Upgrade header");
2960
2960
  return;
2961
2961
  }
2962
- const digest4 = createHash9("sha1").update(key + GUID).digest("base64");
2962
+ const digest4 = createHash10("sha1").update(key + GUID).digest("base64");
2963
2963
  if (res.headers["sec-websocket-accept"] !== digest4) {
2964
2964
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
2965
2965
  return;
@@ -3328,7 +3328,7 @@ var require_websocket_server = __commonJS({
3328
3328
  var EventEmitter = __require("events");
3329
3329
  var http = __require("http");
3330
3330
  var { Duplex } = __require("stream");
3331
- var { createHash: createHash9 } = __require("crypto");
3331
+ var { createHash: createHash10 } = __require("crypto");
3332
3332
  var extension2 = require_extension();
3333
3333
  var PerMessageDeflate2 = require_permessage_deflate();
3334
3334
  var subprotocol2 = require_subprotocol();
@@ -3635,7 +3635,7 @@ var require_websocket_server = __commonJS({
3635
3635
  );
3636
3636
  }
3637
3637
  if (this._state > RUNNING) return abortHandshake(socket, 503);
3638
- const digest4 = createHash9("sha1").update(key + GUID).digest("base64");
3638
+ const digest4 = createHash10("sha1").update(key + GUID).digest("base64");
3639
3639
  const headers = [
3640
3640
  "HTTP/1.1 101 Switching Protocols",
3641
3641
  "Upgrade: websocket",
@@ -3723,7 +3723,7 @@ var require_websocket_server = __commonJS({
3723
3723
  });
3724
3724
 
3725
3725
  // agent/src/main.ts
3726
- import path10 from "node:path";
3726
+ import path12 from "node:path";
3727
3727
  import os3 from "node:os";
3728
3728
  import { mkdir as mkdir5, open as open6, readFile as readFile5, rm as rm4 } from "node:fs/promises";
3729
3729
  import { fileURLToPath } from "node:url";
@@ -4674,10 +4674,10 @@ function mergeDefs(...defs) {
4674
4674
  function cloneDef(schema) {
4675
4675
  return mergeDefs(schema._zod.def);
4676
4676
  }
4677
- function getElementAtPath(obj, path11) {
4678
- if (!path11)
4677
+ function getElementAtPath(obj, path13) {
4678
+ if (!path13)
4679
4679
  return obj;
4680
- return path11.reduce((acc, key) => acc?.[key], obj);
4680
+ return path13.reduce((acc, key) => acc?.[key], obj);
4681
4681
  }
4682
4682
  function promiseAllObject(promisesObj) {
4683
4683
  const keys = Object.keys(promisesObj);
@@ -4976,12 +4976,12 @@ function merge(a, b) {
4976
4976
  });
4977
4977
  return clone(a, def);
4978
4978
  }
4979
- function partial(Class2, schema, mask, name = "partial") {
4979
+ function partial(Class2, schema, mask, name2 = "partial") {
4980
4980
  const currDef = schema._zod.def;
4981
4981
  const checks = currDef.checks;
4982
4982
  const hasChecks = checks && checks.length > 0;
4983
4983
  if (hasChecks) {
4984
- throw new Error(`.${name}() cannot be used on object schemas containing refinements`);
4984
+ throw new Error(`.${name2}() cannot be used on object schemas containing refinements`);
4985
4985
  }
4986
4986
  const selected = mask ? new Set(maskedKeys(schema, mask)) : void 0;
4987
4987
  const newShape = {};
@@ -5017,11 +5017,11 @@ function explicitlyAborted(x, startIndex = 0) {
5017
5017
  }
5018
5018
  return false;
5019
5019
  }
5020
- function prefixIssues(path11, issues) {
5020
+ function prefixIssues(path13, issues) {
5021
5021
  return issues.map((iss) => {
5022
5022
  var _a3;
5023
5023
  (_a3 = iss).path ?? (_a3.path = []);
5024
- iss.path.unshift(path11);
5024
+ iss.path.unshift(path13);
5025
5025
  return iss;
5026
5026
  });
5027
5027
  }
@@ -5309,7 +5309,7 @@ function newError(Definition) {
5309
5309
  return new Definition();
5310
5310
  }
5311
5311
  // @__NO_SIDE_EFFECTS__
5312
- function $constructor(name, initializer3, proto, params) {
5312
+ function $constructor(name2, initializer3, proto, params) {
5313
5313
  const zodProto = {};
5314
5314
  function Internals(def) {
5315
5315
  this.def = def;
@@ -5327,10 +5327,10 @@ function $constructor(name, initializer3, proto, params) {
5327
5327
  } finally {
5328
5328
  _zodDesc.value = void 0;
5329
5329
  }
5330
- } else if (inst._zod.traits.has(name)) {
5330
+ } else if (inst._zod.traits.has(name2)) {
5331
5331
  return;
5332
5332
  }
5333
- inst._zod.traits.add(name);
5333
+ inst._zod.traits.add(name2);
5334
5334
  initializer3(inst, def);
5335
5335
  if (initialized) {
5336
5336
  const own2 = Object.getPrototypeOf(inst);
@@ -5356,7 +5356,7 @@ function $constructor(name, initializer3, proto, params) {
5356
5356
  const Parent = params?.Parent ?? Object;
5357
5357
  class Definition extends Parent {
5358
5358
  }
5359
- Object.defineProperty(Definition, "name", { value: name });
5359
+ Object.defineProperty(Definition, "name", { value: name2 });
5360
5360
  function _(def) {
5361
5361
  const inst = params?.Parent ? newError(Definition) : this;
5362
5362
  init(inst, def);
@@ -5377,10 +5377,10 @@ function $constructor(name, initializer3, proto, params) {
5377
5377
  value: (inst) => {
5378
5378
  if (params?.Parent && inst instanceof params.Parent)
5379
5379
  return true;
5380
- return inst?._zod?.traits?.has(name);
5380
+ return inst?._zod?.traits?.has(name2);
5381
5381
  }
5382
5382
  });
5383
- Object.defineProperty(_, "name", { value: name });
5383
+ Object.defineProperty(_, "name", { value: name2 });
5384
5384
  return _;
5385
5385
  }
5386
5386
  var $brand = /* @__PURE__ */ Symbol("zod_brand");
@@ -5390,8 +5390,8 @@ var $ZodAsyncError = class extends Error {
5390
5390
  }
5391
5391
  };
5392
5392
  var $ZodEncodeError = class extends Error {
5393
- constructor(name) {
5394
- super(`Encountered unidirectional transform during encode: ${name}`);
5393
+ constructor(name2) {
5394
+ super(`Encountered unidirectional transform during encode: ${name2}`);
5395
5395
  this.name = "ZodEncodeError";
5396
5396
  }
5397
5397
  };
@@ -5471,16 +5471,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) {
5471
5471
  }
5472
5472
  function formatError(error62, mapper = (issue2) => issue2.message) {
5473
5473
  const fieldErrors = { _errors: [] };
5474
- const processError = (error63, path11 = []) => {
5474
+ const processError = (error63, path13 = []) => {
5475
5475
  for (const issue2 of error63.issues) {
5476
5476
  if (issue2.code === "invalid_union" && issue2.errors.length) {
5477
- issue2.errors.map((issues) => processError({ issues }, [...path11, ...issue2.path]));
5477
+ issue2.errors.map((issues) => processError({ issues }, [...path13, ...issue2.path]));
5478
5478
  } else if (issue2.code === "invalid_key") {
5479
- processError({ issues: issue2.issues }, [...path11, ...issue2.path]);
5479
+ processError({ issues: issue2.issues }, [...path13, ...issue2.path]);
5480
5480
  } else if (issue2.code === "invalid_element") {
5481
- processError({ issues: issue2.issues }, [...path11, ...issue2.path]);
5481
+ processError({ issues: issue2.issues }, [...path13, ...issue2.path]);
5482
5482
  } else {
5483
- const fullpath = [...path11, ...issue2.path];
5483
+ const fullpath = [...path13, ...issue2.path];
5484
5484
  if (fullpath.length === 0) {
5485
5485
  fieldErrors._errors.push(mapper(issue2));
5486
5486
  } else {
@@ -5519,17 +5519,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) {
5519
5519
  }
5520
5520
  function treeifyError(error62, mapper = (issue2) => issue2.message) {
5521
5521
  const result2 = { errors: [] };
5522
- const processError = (error63, path11 = []) => {
5522
+ const processError = (error63, path13 = []) => {
5523
5523
  var _a3;
5524
5524
  for (const issue2 of error63.issues) {
5525
5525
  if (issue2.code === "invalid_union" && issue2.errors.length) {
5526
- issue2.errors.map((issues) => processError({ issues }, [...path11, ...issue2.path]));
5526
+ issue2.errors.map((issues) => processError({ issues }, [...path13, ...issue2.path]));
5527
5527
  } else if (issue2.code === "invalid_key") {
5528
- processError({ issues: issue2.issues }, [...path11, ...issue2.path]);
5528
+ processError({ issues: issue2.issues }, [...path13, ...issue2.path]);
5529
5529
  } else if (issue2.code === "invalid_element") {
5530
- processError({ issues: issue2.issues }, [...path11, ...issue2.path]);
5530
+ processError({ issues: issue2.issues }, [...path13, ...issue2.path]);
5531
5531
  } else {
5532
- const fullpath = [...path11, ...issue2.path];
5532
+ const fullpath = [...path13, ...issue2.path];
5533
5533
  if (fullpath.length === 0) {
5534
5534
  result2.errors.push(mapper(issue2));
5535
5535
  continue;
@@ -5568,8 +5568,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) {
5568
5568
  }
5569
5569
  function toDotPath(_path) {
5570
5570
  const segs = [];
5571
- const path11 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
5572
- for (const seg of path11) {
5571
+ const path13 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
5572
+ for (const seg of path13) {
5573
5573
  if (typeof seg === "number")
5574
5574
  segs.push(`[${seg}]`);
5575
5575
  else if (typeof seg === "symbol")
@@ -16890,13 +16890,13 @@ ${code}
16890
16890
  return fn;
16891
16891
  }
16892
16892
  function addConstant(ctx, value) {
16893
- for (const [name2, v] of ctx.constants) {
16893
+ for (const [name3, v] of ctx.constants) {
16894
16894
  if (v === value)
16895
- return name2;
16895
+ return name3;
16896
16896
  }
16897
- const name = `c${ctx.constantCounter++}`;
16898
- ctx.constants.set(name, value);
16899
- return name;
16897
+ const name2 = `c${ctx.constantCounter++}`;
16898
+ ctx.constants.set(name2, value);
16899
+ return name2;
16900
16900
  }
16901
16901
  function addUserConstant(ctx, fn) {
16902
16902
  ctx.definite = false;
@@ -22671,13 +22671,13 @@ function resolveRef(ref, ctx) {
22671
22671
  if (!ref.startsWith("#")) {
22672
22672
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
22673
22673
  }
22674
- const path11 = ref.slice(1).split("/").filter(Boolean);
22675
- if (path11.length === 0) {
22674
+ const path13 = ref.slice(1).split("/").filter(Boolean);
22675
+ if (path13.length === 0) {
22676
22676
  return ctx.rootSchema;
22677
22677
  }
22678
22678
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
22679
- if (path11[0] === defsKey) {
22680
- const key = path11[1] === void 0 ? void 0 : decodeJSONPointerSegment(path11[1]);
22679
+ if (path13[0] === defsKey) {
22680
+ const key = path13[1] === void 0 ? void 0 : decodeJSONPointerSegment(path13[1]);
22681
22681
  if (!key || !ctx.defs[key]) {
22682
22682
  throw new Error(`Reference not found: ${ref}`);
22683
22683
  }
@@ -23643,9 +23643,9 @@ function isDisjoint(...headers) {
23643
23643
  }
23644
23644
  return true;
23645
23645
  }
23646
- function assertNotSet(value, name) {
23646
+ function assertNotSet(value, name2) {
23647
23647
  if (value !== void 0)
23648
- throw new TypeError(`${name} can only be called once`);
23648
+ throw new TypeError(`${name2} can only be called once`);
23649
23649
  }
23650
23650
  function decodeBase64url(value, label, ErrorClass) {
23651
23651
  try {
@@ -23806,7 +23806,7 @@ function invalidKeyType(alg, actual, secret) {
23806
23806
  const types = ["CryptoKey", "KeyObject", "JSON Web Key"];
23807
23807
  return secret && types.push("Uint8Array"), new TypeError(message(`Key for the ${alg} algorithm must be `, actual, ...types));
23808
23808
  }
23809
- var unusable = (name, prop = "algorithm.name") => new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
23809
+ var unusable = (name2, prop = "algorithm.name") => new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name2}`);
23810
23810
  function checkUsage(key, usage) {
23811
23811
  if (usage && !key.usages.includes(usage))
23812
23812
  throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);
@@ -24481,7 +24481,9 @@ var ClientFrameSchema = external_exports.discriminatedUnion("type", [
24481
24481
  external_exports.object({ type: external_exports.literal("not_accepted"), version: external_exports.literal(1), binding: ExecutionBindingSchema, code: external_exports.string().regex(/^[A-Z0-9_]{1,40}$/), provedNotStarted: external_exports.boolean() }).strict(),
24482
24482
  external_exports.object({ type: external_exports.literal("control_result"), version: external_exports.literal(1), requestId: uuid8, binding: ExecutionBindingSchema, state: external_exports.enum(["prepared", "accepted", "running", "finished", "failed", "cancelled", "rejected", "unknown", "missing"]), result: ResultSchema.optional() }).strict()
24483
24483
  ]);
24484
- var TerminalEventSchema = external_exports.object({ type: external_exports.literal("executionResult"), protocolVersion: external_exports.literal(1), requestId: uuid8, tenantId: uuid8, deviceId: uuid8, connectionEpoch: epoch, binding: ExecutionBindingSchema, state: external_exports.enum(["finished", "failed", "cancelled", "unknown"]), resultCode: external_exports.string().regex(/^[A-Z0-9_]{1,40}$/) }).strict();
24484
+ var TerminalMetricsSchema = external_exports.object({ stdoutBytes: external_exports.number().int().min(0).max(4194304), stderrBytes: external_exports.number().int().min(0).max(4194304), outputTruncated: external_exports.boolean() }).strict();
24485
+ var TERMINAL_METRICS_CAPABILITY = "terminalMetrics";
24486
+ var TerminalEventSchema = external_exports.object({ type: external_exports.literal("executionResult"), protocolVersion: external_exports.literal(1), requestId: uuid8, tenantId: uuid8, deviceId: uuid8, connectionEpoch: epoch, binding: ExecutionBindingSchema, state: external_exports.enum(["finished", "failed", "cancelled", "unknown"]), resultCode: external_exports.string().regex(/^[A-Z0-9_]{1,40}$/), metrics: TerminalMetricsSchema.optional() }).strict();
24485
24487
  var TerminalEventAckSchema = external_exports.object({ type: external_exports.literal("executionResultAck"), protocolVersion: external_exports.literal(1), requestId: uuid8, ok: external_exports.boolean() }).strict();
24486
24488
  function canonicalJson(value) {
24487
24489
  function canonical2(v) {
@@ -24547,9 +24549,9 @@ function guardAction(binding2, tool, config2, observedAt) {
24547
24549
  if (!binding2.accountId || binding2.tenantId !== config2.tenantId || binding2.deviceId !== config2.deviceId || !tool.effective) {
24548
24550
  throw Error("GUARD_IDENTITY_REQUIRED");
24549
24551
  }
24550
- const name = tool.call.name;
24551
- const kind = name === "command_run" ? "execute" : name === "localhost_request" ? "localhost-access" : name === "fs_write" || name === "fs_replace" ? "write" : name.startsWith("git_") ? "git-read" : "read";
24552
- const resourceKind = kind === "execute" ? "workspace" : kind === "localhost-access" ? "localhost-service" : kind === "git-read" ? "git-repository" : name === "fs_read" || kind === "write" ? "file" : "workspace";
24552
+ const name2 = tool.call.name;
24553
+ const kind = name2 === "command_run" ? "execute" : name2 === "localhost_request" ? "localhost-access" : name2 === "fs_write" || name2 === "fs_replace" ? "write" : name2.startsWith("git_") ? "git-read" : "read";
24554
+ const resourceKind = kind === "execute" ? "workspace" : kind === "localhost-access" ? "localhost-service" : kind === "git-read" ? "git-repository" : name2 === "fs_read" || kind === "write" ? "file" : "workspace";
24553
24555
  return { payloadHash: guardHash(tool.effective), request: BoundActionRequestSchema.parse({
24554
24556
  protocolVersion: 1,
24555
24557
  requestId: binding2.executionId,
@@ -24569,13 +24571,13 @@ function guardAction(binding2, tool, config2, observedAt) {
24569
24571
  adapter: guardAdapter,
24570
24572
  actor: { kind: "human", subjectRef: binding2.accountId, authenticationClass: "delegated" },
24571
24573
  agent: { agentRef: "grant:" + binding2.grantId },
24572
- tool: { namespace: "local-commander", name },
24574
+ tool: { namespace: "local-commander", name: name2 },
24573
24575
  resource: { kind: resourceKind, locatorFingerprint: guardHash({
24574
24576
  workspace: binding2.workspaceGrantId,
24575
24577
  resources: tool.claims,
24576
- ...name === "localhost_request" ? { url: tool.call.args.url } : {}
24578
+ ...name2 === "localhost_request" ? { url: tool.call.args.url } : {}
24577
24579
  }) },
24578
- action: { kind, verb: name, effect: kind === "execute" ? "external-mutation" : kind === "write" ? "local-mutation" : kind === "localhost-access" ? "external-mutation" : "read-only" },
24580
+ action: { kind, verb: name2, effect: kind === "execute" ? "external-mutation" : kind === "write" ? "local-mutation" : kind === "localhost-access" ? "external-mutation" : "read-only" },
24579
24581
  dataClassifications: ["unknown"],
24580
24582
  environment: config2.environment
24581
24583
  }
@@ -24585,7 +24587,7 @@ function guardSummary(tool) {
24585
24587
  if (!tool.effective) throw Error("GUARD_ACTION_INVALID");
24586
24588
  const call = tool.call;
24587
24589
  const args = { ...call.args };
24588
- if (args.headers) args.headers = Object.keys(args.headers).map((name) => name + " (value hidden)");
24590
+ if (args.headers) args.headers = Object.keys(args.headers).map((name2) => name2 + " (value hidden)");
24589
24591
  return JSON.stringify({
24590
24592
  tool: call.name,
24591
24593
  resources: tool.claims,
@@ -24695,7 +24697,7 @@ function canonicalTime(value) {
24695
24697
  }
24696
24698
  function validateInput(value) {
24697
24699
  if (!value || typeof value !== "object" || Object.keys(value).some((k) => !bindingKeys.includes(k))) throw failure2("JOURNAL_INPUT_INVALID");
24698
- for (const name of bindingKeys.slice(0, 6)) if (typeof value[name] !== "string" || !uuid11.test(value[name])) throw failure2("JOURNAL_INPUT_INVALID");
24700
+ for (const name2 of bindingKeys.slice(0, 6)) if (typeof value[name2] !== "string" || !uuid11.test(value[name2])) throw failure2("JOURNAL_INPUT_INVALID");
24699
24701
  if (value.accountId !== void 0 && !uuid11.test(value.accountId)) throw failure2("JOURNAL_INPUT_INVALID");
24700
24702
  if (typeof value.connectionEpoch !== "string" || !/^[1-9]\d{0,18}$/.test(value.connectionEpoch) || BigInt(value.connectionEpoch) > 9223372036854775807n || typeof value.payloadHash !== "string" || !hash4.test(value.payloadHash) || !canonicalTime(value.deadlineAt)) throw failure2("JOURNAL_INPUT_INVALID");
24701
24703
  if (value.workspaceGrantId === void 0 !== (value.policyVersion === void 0) || value.workspaceGrantId !== void 0 && (!uuid11.test(value.workspaceGrantId) || !Number.isInteger(value.policyVersion) || value.policyVersion < 1 || value.policyVersion > 2147483647)) throw failure2("JOURNAL_INPUT_INVALID");
@@ -24817,9 +24819,9 @@ var NativeJournal = class _NativeJournal {
24817
24819
  async load() {
24818
24820
  const names = await readdir(this.dir);
24819
24821
  if (names.length > this.options.maxEntries + 256) throw failure2("JOURNAL_CAPACITY_EXCEEDED");
24820
- for (const name of names) {
24821
- if (!name.endsWith(".entry")) continue;
24822
- const id = name.slice(0, -6);
24822
+ for (const name2 of names) {
24823
+ if (!name2.endsWith(".entry")) continue;
24824
+ const id = name2.slice(0, -6);
24823
24825
  if (!uuid11.test(id)) throw failure2("JOURNAL_CORRUPT");
24824
24826
  const envelope = await this.readOwned(id);
24825
24827
  this.totalBytes += envelope.length;
@@ -25083,10 +25085,10 @@ var NativeJournal = class _NativeJournal {
25083
25085
 
25084
25086
  // agent/src/private-store.ts
25085
25087
  import { constants as constants2 } from "node:fs";
25086
- import { lstat as lstat2, open as open3, readFile as readFile2, readdir as readdir2, realpath as realpath2, rename as rename2, rm as rm2, writeFile } from "node:fs/promises";
25087
- import path3 from "node:path";
25088
+ import { lstat as lstat3, open as open3, readFile as readFile2, readdir as readdir2, realpath as realpath3, rename as rename2, rm as rm2, writeFile } from "node:fs/promises";
25089
+ import path5 from "node:path";
25088
25090
  import os from "node:os";
25089
- import { createHash as createHash7, createPrivateKey, createPublicKey as createPublicKey3, generateKeyPairSync, randomBytes as randomBytes3, randomUUID as randomUUID3 } from "node:crypto";
25091
+ import { createHash as createHash8, createPrivateKey, createPublicKey as createPublicKey3, generateKeyPairSync, randomBytes as randomBytes3, randomUUID as randomUUID3 } from "node:crypto";
25090
25092
  import { spawn } from "node:child_process";
25091
25093
 
25092
25094
  // src/child-environment.ts
@@ -25203,13 +25205,123 @@ function buildChildEnvironment(source, platform = process.platform) {
25203
25205
  return result2;
25204
25206
  }
25205
25207
 
25208
+ // agent/src/access-selection.ts
25209
+ import path3 from "node:path";
25210
+ function parseAccessSelection(value) {
25211
+ const fail5 = () => {
25212
+ throw Error("ACCESS_SELECTION_INVALID");
25213
+ };
25214
+ if (!value || typeof value !== "object" || Array.isArray(value)) return fail5();
25215
+ const input2 = value;
25216
+ if (!Array.isArray(input2.paths)) return fail5();
25217
+ if (input2.mode === "cancelled") {
25218
+ if (input2.paths.length !== 0) return fail5();
25219
+ return null;
25220
+ }
25221
+ if (input2.mode !== "folders" && input2.mode !== "all-drives") return fail5();
25222
+ if (input2.paths.length < 1 || input2.paths.length > (input2.mode === "folders" ? 1 : 26)) return fail5();
25223
+ const roots = [];
25224
+ for (const candidate of input2.paths) {
25225
+ if (typeof candidate !== "string" || candidate.length > 4096 || /[\u0000-\u001f]/.test(candidate) || !path3.win32.isAbsolute(candidate)) return fail5();
25226
+ if (input2.mode === "all-drives" && !/^[a-z]:\\$/i.test(candidate)) return fail5();
25227
+ const normalized = path3.win32.normalize(candidate).toLowerCase();
25228
+ if (roots.some((root) => path3.win32.normalize(root).toLowerCase() === normalized)) return fail5();
25229
+ roots.push(candidate);
25230
+ }
25231
+ return { mode: input2.mode, paths: roots };
25232
+ }
25233
+
25234
+ // agent/src/owner-permissions.ts
25235
+ import { createHash as createHash4 } from "node:crypto";
25236
+ import { lstat as lstat2, realpath as realpath2 } from "node:fs/promises";
25237
+ import path4 from "node:path";
25238
+ var uuid12 = external_exports.string().uuid().toLowerCase();
25239
+ var name = external_exports.string().regex(/^[a-zA-Z0-9_.-]{1,64}$/).toLowerCase();
25240
+ var changeSchema = external_exports.discriminatedUnion("kind", [
25241
+ external_exports.object({ workspaceGrantId: uuid12, kind: external_exports.literal("write"), enabled: external_exports.boolean() }).strict(),
25242
+ external_exports.object({ workspaceGrantId: uuid12, kind: external_exports.literal("localhost"), enabled: external_exports.boolean(), port: external_exports.number().int().min(1).max(65535) }).strict(),
25243
+ external_exports.object({ workspaceGrantId: uuid12, kind: external_exports.literal("command"), enabled: external_exports.boolean(), name, executable: external_exports.string().min(1).max(4096).optional() }).strict()
25244
+ ]);
25245
+ var PERMISSION_HISTORY_LIMIT = 64;
25246
+ var PermissionHistorySchema = external_exports.array(external_exports.object({
25247
+ id: uuid12,
25248
+ changedAt: external_exports.string().datetime(),
25249
+ workspaceGrantId: uuid12,
25250
+ kind: external_exports.enum(["write", "command", "localhost"]),
25251
+ enabled: external_exports.boolean(),
25252
+ resourceHash: external_exports.string().regex(/^[a-f0-9]{64}$/),
25253
+ ownerSid: external_exports.string().max(184).regex(/^S-1-(?:[0-9]+-)+[0-9]+$/)
25254
+ }).strict()).max(PERMISSION_HISTORY_LIMIT);
25255
+ function permissionHash(value) {
25256
+ return createHash4("sha256").update(JSON.stringify(value)).digest("hex");
25257
+ }
25258
+ function invalid2(code = "PERMISSION_INVALID") {
25259
+ throw Object.assign(new Error(code), { code });
25260
+ }
25261
+ function parsePermissionChange(value) {
25262
+ const parsed = changeSchema.safeParse(value);
25263
+ if (!parsed.success) invalid2();
25264
+ const change = parsed.data;
25265
+ if (change.kind === "command" && (change.enabled ? !change.executable : change.executable !== void 0)) invalid2();
25266
+ return change;
25267
+ }
25268
+ function equalPath(a, b) {
25269
+ return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
25270
+ }
25271
+ function permissionLabel(value) {
25272
+ return JSON.stringify(value).replace(
25273
+ /[\u007f-\u009f\u061c\u200b-\u200f\u2028-\u202e\u2060-\u2069\ufeff]/gu,
25274
+ (ch) => "\\u" + ch.charCodeAt(0).toString(16).padStart(4, "0")
25275
+ );
25276
+ }
25277
+ function nonAsciiNotice(value) {
25278
+ if (!value || !/[^\x20-\x7e]/.test(value)) return "";
25279
+ return "\nWarning: this path contains non-ASCII characters: " + value.replace(/[^\x20-\x7e]/g, (ch) => "\\u" + ch.charCodeAt(0).toString(16).padStart(4, "0"));
25280
+ }
25281
+ async function planPermissionChange(current2, programs, input2) {
25282
+ const change = parsePermissionChange(input2);
25283
+ if (current2.workspaceGrantId !== change.workspaceGrantId) invalid2("WORKSPACE_UNKNOWN");
25284
+ const workspace = structuredClone(current2), nextPrograms = { ...programs };
25285
+ let resource = { rootHash: workspace.rootHash, kind: change.kind };
25286
+ let detail;
25287
+ if (change.kind === "write") {
25288
+ workspace.permissions.writeFiles = change.enabled;
25289
+ detail = "File writes: " + (change.enabled ? "ALLOW" : "DENY");
25290
+ } else if (change.kind === "localhost") {
25291
+ workspace.localhostPorts = change.enabled ? [.../* @__PURE__ */ new Set([...workspace.localhostPorts, change.port])].sort((a, b) => a - b) : workspace.localhostPorts.filter((port) => port !== change.port);
25292
+ if (workspace.localhostPorts.length > 32) invalid2("PERMISSION_LIMIT");
25293
+ workspace.permissions.localhost = workspace.localhostPorts.length > 0;
25294
+ resource = { rootHash: workspace.rootHash, kind: change.kind, port: change.port };
25295
+ detail = "Localhost port " + change.port + ": " + (change.enabled ? "ALLOW" : "DENY");
25296
+ } else {
25297
+ let executableIdentity = null;
25298
+ if (change.enabled) {
25299
+ const executable = change.executable;
25300
+ if (!path4.isAbsolute(executable) || path4.extname(executable).toLowerCase() !== ".exe" || /[\u0000-\u001f\u007f-\u009f\u061c\u200b-\u200f\u2028-\u202e\u2060-\u2069\ufeff]/u.test(executable)) invalid2();
25301
+ const stat = await lstat2(executable).catch(() => invalid2());
25302
+ const canonical2 = await realpath2(executable).catch(() => invalid2());
25303
+ if (!stat.isFile() || stat.isSymbolicLink() || !equalPath(path4.resolve(executable), canonical2)) invalid2();
25304
+ if (Object.hasOwn(nextPrograms, change.name) && !equalPath(nextPrograms[change.name], canonical2)) invalid2("COMMAND_CONFLICT");
25305
+ nextPrograms[change.name] = canonical2;
25306
+ workspace.allowedCommands = [.../* @__PURE__ */ new Set([...workspace.allowedCommands, change.name])].sort();
25307
+ if (workspace.allowedCommands.length > 32 || Object.keys(nextPrograms).length > 32) invalid2("PERMISSION_LIMIT");
25308
+ executableIdentity = { executable: canonical2, dev: stat.dev, ino: stat.ino, size: stat.size, mtimeMs: stat.mtimeMs, ctimeMs: stat.ctimeMs };
25309
+ } else workspace.allowedCommands = workspace.allowedCommands.filter((value) => value !== change.name);
25310
+ workspace.permissions.executeCommands = workspace.allowedCommands.length > 0;
25311
+ resource = { rootHash: workspace.rootHash, kind: change.kind, name: change.name, executable: nextPrograms[change.name] ?? null, executableIdentity };
25312
+ detail = "Command " + permissionLabel(change.name) + ": " + (change.enabled ? "ALLOW" : "DENY") + "\nExact executable: " + permissionLabel(nextPrograms[change.name] ?? "not registered") + nonAsciiNotice(nextPrograms[change.name]) + "\nA permitted program can access resources available to your Windows account, including outside this folder. This is not an OS sandbox.";
25313
+ }
25314
+ const summary = "Change Local Commander permissions\nWorkspace: " + permissionLabel(current2.displayName) + "\nWorkspace ID: " + current2.workspaceGrantId + "\nFolder: " + permissionLabel(current2.root) + "\n\n" + detail + "\n\nThis change persists until you revoke it. Other workspaces are not granted this permission.\nReview before approving. Closing this window, rejecting or timing out changes nothing.\nA running agent may restart after the change; running work can be interrupted. Revocation does not undo completed effects.";
25315
+ return { workspace, programs: nextPrograms, change, summary, resourceHash: permissionHash(resource) };
25316
+ }
25317
+
25206
25318
  // packages/policy/src/signed-bundle.ts
25207
- import { createHash as createHash5, KeyObject as KeyObject2 } from "node:crypto";
25319
+ import { createHash as createHash6, KeyObject as KeyObject2 } from "node:crypto";
25208
25320
 
25209
25321
  // packages/policy/src/evaluator.ts
25210
- import { createHash as createHash4 } from "node:crypto";
25322
+ import { createHash as createHash5 } from "node:crypto";
25211
25323
  import { isDeepStrictEqual } from "node:util";
25212
- var uuid12 = external_exports.string().uuid().toLowerCase();
25324
+ var uuid13 = external_exports.string().uuid().toLowerCase();
25213
25325
  var slug2 = external_exports.string().regex(/^[a-z][a-z0-9._-]{0,63}$/);
25214
25326
  var utc = external_exports.iso.datetime({ offset: false });
25215
25327
  var risk = external_exports.enum(["low", "moderate", "high", "critical"]);
@@ -25234,7 +25346,7 @@ var PolicyRuleSchema = external_exports.object({
25234
25346
  }
25235
25347
  });
25236
25348
  var PolicySnapshotSchema = external_exports.object({
25237
- tenantId: uuid12,
25349
+ tenantId: uuid13,
25238
25350
  policyId: slug2,
25239
25351
  policyVersion: external_exports.string().trim().min(1).max(64),
25240
25352
  issuedAt: utc,
@@ -25264,7 +25376,7 @@ function matches(rule, request, requestRisk) {
25264
25376
  return (!rule.actionKinds || rule.actionKinds.includes(action.kind)) && (!rule.toolNamespaces || rule.toolNamespaces.includes(tool.namespace)) && (!rule.environments || rule.environments.includes(environment.environment)) && (!rule.anyDataClassifications || rule.anyDataClassifications.some((value) => dataClassifications.includes(value))) && (!rule.resourceKinds || rule.resourceKinds.includes(resource.kind)) && (!rule.resourceFingerprints || rule.resourceFingerprints.includes(resource.locatorFingerprint)) && (!rule.riskClasses || rule.riskClasses.includes(requestRisk));
25265
25377
  }
25266
25378
  function decisionId(requestId, policyId, policyVersion, ruleId) {
25267
- const bytes3 = createHash4("sha256").update(JSON.stringify([requestId, policyId, policyVersion, ruleId])).digest().subarray(0, 16);
25379
+ const bytes3 = createHash5("sha256").update(JSON.stringify([requestId, policyId, policyVersion, ruleId])).digest().subarray(0, 16);
25268
25380
  bytes3[6] = bytes3[6] & 15 | 64;
25269
25381
  bytes3[8] = bytes3[8] & 63 | 128;
25270
25382
  const hex3 = bytes3.toString("hex");
@@ -25333,7 +25445,7 @@ async function verifySignedPolicyBundle(candidate, authority, checkpointInput, n
25333
25445
  if (payload.byteLength > 256 * 1024) throw new Error();
25334
25446
  const bundle = BundleSchema.parse(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(payload)));
25335
25447
  const { snapshot: snapshot2 } = bundle;
25336
- const payloadSha256 = createHash5("sha256").update(payload).digest("hex");
25448
+ const payloadSha256 = createHash6("sha256").update(payload).digest("hex");
25337
25449
  if (snapshot2.tenantId !== expected.tenantId || snapshot2.policyId !== expected.policyId || at < Date.parse(snapshot2.issuedAt) || at >= Date.parse(snapshot2.expiresAt) || bundle.sequence < checkpoint.sequence || bundle.sequence === checkpoint.sequence && payloadSha256 !== checkpoint.payloadSha256) throw new Error();
25338
25450
  return { snapshot: snapshot2, checkpoint: {
25339
25451
  ...expected,
@@ -25347,15 +25459,15 @@ async function verifySignedPolicyBundle(candidate, authority, checkpointInput, n
25347
25459
  }
25348
25460
 
25349
25461
  // packages/policy/src/approvals.ts
25350
- import { createHash as createHash6, randomUUID as randomUUID2 } from "node:crypto";
25351
- var uuid13 = TrustedActionBindingSchema.shape.tenantId;
25462
+ import { createHash as createHash7, randomUUID as randomUUID2 } from "node:crypto";
25463
+ var uuid14 = TrustedActionBindingSchema.shape.tenantId;
25352
25464
  var utc3 = TrustedActionBindingSchema.shape.expiresAt;
25353
25465
  var digest3 = ResourceRefSchema.shape.locatorFingerprint;
25354
25466
  var requirement = PolicyDecisionSchema.shape.approval.unwrap();
25355
25467
  var ApprovalActionSchema = external_exports.object({ request: BoundActionRequestSchema, payloadHash: digest3 }).strict();
25356
25468
  var ApprovalAuthoritySchema = external_exports.object({
25357
- tenantId: uuid13,
25358
- accountId: uuid13,
25469
+ tenantId: uuid14,
25470
+ accountId: uuid14,
25359
25471
  approvalClass: requirement.shape.approvalClass,
25360
25472
  authenticatedAt: utc3,
25361
25473
  expiresAt: utc3
@@ -25367,11 +25479,11 @@ var ContextSchema = external_exports.object({
25367
25479
  policyExpiresAt: utc3
25368
25480
  }).strict();
25369
25481
  var GrantSchema = external_exports.object({
25370
- approvalId: uuid13,
25371
- requestId: uuid13,
25372
- decisionId: uuid13,
25482
+ approvalId: uuid14,
25483
+ requestId: uuid14,
25484
+ decisionId: uuid14,
25373
25485
  bindingHash: digest3,
25374
- approverAccountId: uuid13,
25486
+ approverAccountId: uuid14,
25375
25487
  approvalClass: requirement.shape.approvalClass,
25376
25488
  scope: requirement.shape.scope,
25377
25489
  issuedAt: utc3,
@@ -25380,8 +25492,8 @@ var GrantSchema = external_exports.object({
25380
25492
  uses: external_exports.number().int().min(0).max(Number.MAX_SAFE_INTEGER)
25381
25493
  }).strict().refine((value) => Date.parse(value.issuedAt) < Date.parse(value.expiresAt) && (value.scope === "once" ? value.uses === (value.state === "consumed" ? 1 : 0) : value.state !== "consumed"));
25382
25494
  var ApprovalLedgerSchema = external_exports.object({
25383
- tenantId: uuid13,
25384
- deviceId: uuid13,
25495
+ tenantId: uuid14,
25496
+ deviceId: uuid14,
25385
25497
  lastChangedAt: utc3,
25386
25498
  grants: external_exports.array(GrantSchema).max(128)
25387
25499
  }).strict().refine((value) => new Set(value.grants.map((grant) => grant.approvalId)).size === value.grants.length && new Set(value.grants.map((grant) => grant.requestId)).size === value.grants.length && value.grants.every((grant) => Date.parse(grant.issuedAt) <= Date.parse(value.lastChangedAt)));
@@ -25402,7 +25514,7 @@ function binding(ledger, input2, now) {
25402
25514
  approval.expiresAt ? Date.parse(approval.expiresAt) : Infinity
25403
25515
  );
25404
25516
  if (at >= deadline) throw Error();
25405
- const bindingHash = createHash6("sha256").update(JSON.stringify([
25517
+ const bindingHash = createHash7("sha256").update(JSON.stringify([
25406
25518
  owner.bindingSource,
25407
25519
  owner.tenantId,
25408
25520
  owner.accountId,
@@ -25458,7 +25570,7 @@ function issueApproval(ledgerInput, context, authorityInput, now, expiresAt) {
25458
25570
  }
25459
25571
  function consumeApproval(ledgerInput, context, approvalId, now) {
25460
25572
  try {
25461
- const ledger = current(ledgerInput, now), bound = binding(ledger, context, now), id = uuid13.parse(approvalId);
25573
+ const ledger = current(ledgerInput, now), bound = binding(ledger, context, now), id = uuid14.parse(approvalId);
25462
25574
  const grant = ledger.grants.find((candidate) => candidate.approvalId === id);
25463
25575
  if (!grant || grant.state !== "active" || grant.bindingHash !== bound.bindingHash || grant.uses === Number.MAX_SAFE_INTEGER || Date.parse(now) < Date.parse(grant.issuedAt) || grant.scope === "once" && (grant.requestId !== bound.request.requestId || grant.decisionId !== bound.decision.decisionId)) throw Error();
25464
25576
  const consumed = { ...grant, uses: grant.uses + 1, state: grant.scope === "once" ? "consumed" : "active" };
@@ -25469,7 +25581,7 @@ function consumeApproval(ledgerInput, context, approvalId, now) {
25469
25581
  }
25470
25582
  function revokeApproval(ledgerInput, approvalId, now) {
25471
25583
  try {
25472
- const ledger = current(ledgerInput, now), id = uuid13.parse(approvalId);
25584
+ const ledger = current(ledgerInput, now), id = uuid14.parse(approvalId);
25473
25585
  return { ...ledger, grants: ledger.grants.map((grant) => grant.approvalId === id && grant.state === "active" ? { ...grant, state: "revoked" } : grant) };
25474
25586
  } catch {
25475
25587
  throw Error("APPROVAL_INVALID");
@@ -25484,12 +25596,12 @@ var MAX_STATE_BYTES = 256 * 1024;
25484
25596
  function fail(code) {
25485
25597
  return Object.assign(new Error(code), { code });
25486
25598
  }
25487
- function equalPath(a, b) {
25488
- return path3.resolve(a).toLowerCase() === path3.resolve(b).toLowerCase();
25599
+ function equalPath2(a, b) {
25600
+ return path5.resolve(a).toLowerCase() === path5.resolve(b).toLowerCase();
25489
25601
  }
25490
25602
  function under(child, parent) {
25491
- const rel = path3.relative(parent, child);
25492
- return rel !== "" && !rel.startsWith("..") && !path3.isAbsolute(rel);
25603
+ const rel = path5.relative(parent, child);
25604
+ return rel !== "" && !rel.startsWith("..") && !path5.isAbsolute(rel);
25493
25605
  }
25494
25606
  function canonicalPublicKey(value) {
25495
25607
  try {
@@ -25501,7 +25613,7 @@ function canonicalPublicKey(value) {
25501
25613
  }
25502
25614
  }
25503
25615
  function fingerprint(publicKeyPem) {
25504
- return createHash7("sha256").update(canonicalPublicKey(publicKeyPem).der).digest("hex");
25616
+ return createHash8("sha256").update(canonicalPublicKey(publicKeyPem).der).digest("hex");
25505
25617
  }
25506
25618
  function publicFromPrivate(privateKeyPem) {
25507
25619
  try {
@@ -25560,55 +25672,57 @@ function validateState(value) {
25560
25672
  }
25561
25673
  const approvals = value.approvals === void 0 ? void 0 : ApprovalLedgerSchema.safeParse(value.approvals);
25562
25674
  if (approvals && (!approvals.success || approvals.data.tenantId !== enrollment?.tenantId || approvals.data.deviceId !== enrollment.deviceId)) throw fail("STATE_CORRUPT");
25675
+ const permissionHistory = PermissionHistorySchema.safeParse(value.permissionHistory ?? []);
25676
+ if (!permissionHistory.success) throw fail("STATE_CORRUPT");
25563
25677
  const workspaces = value.workspaces ?? [];
25564
25678
  const programs = value.programs ?? {};
25565
25679
  const pendingWorkspaceRevokes = value.pendingWorkspaceRevokes ?? [];
25566
25680
  if (!Array.isArray(pendingWorkspaceRevokes) || pendingWorkspaceRevokes.length > 32 || pendingWorkspaceRevokes.some((id) => typeof id !== "string" || !UUID.test(id) || id !== id.toLowerCase()) || new Set(pendingWorkspaceRevokes).size !== pendingWorkspaceRevokes.length) throw fail("STATE_CORRUPT");
25567
- if (!programs || typeof programs !== "object" || Array.isArray(programs) || Object.keys(programs).length > 32 || Object.entries(programs).some(([name, executable]) => !/^[a-z0-9_.-]{1,64}$/.test(name) || typeof executable !== "string" || !path3.isAbsolute(executable) || executable.length > 4096 || /[\u0000-\u001f]/.test(executable))) throw fail("STATE_CORRUPT");
25568
- if (!Array.isArray(workspaces) || workspaces.length > 32 || workspaces.some((w) => !w || !UUID.test(w.workspaceGrantId) || typeof w.root !== "string" || !path3.isAbsolute(w.root) || w.root.length > 4096 || /[\u0000-\u001f]/.test(w.root) || !/^[a-f0-9]{64}$/.test(w.rootHash) || typeof w.displayName !== "string" || !w.displayName || w.displayName.length > 120 || w.policyVersion !== 1 || !w.permissions || w.permissions.readFiles !== true || typeof w.permissions.writeFiles !== "boolean" || typeof w.permissions.executeCommands !== "boolean" || typeof w.permissions.localhost !== "boolean" || !Array.isArray(w.allowedCommands) || w.allowedCommands.length > 32 || w.allowedCommands.some((name) => typeof name !== "string" || !Object.hasOwn(programs, name)) || new Set(w.allowedCommands).size !== w.allowedCommands.length || w.permissions.executeCommands !== w.allowedCommands.length > 0 || !Array.isArray(w.localhostPorts) || w.localhostPorts.length > 32 || w.localhostPorts.some((port) => !Number.isInteger(port) || port < 1 || port > 65535) || new Set(w.localhostPorts).size !== w.localhostPorts.length || w.permissions.localhost !== w.localhostPorts.length > 0)) throw fail("STATE_CORRUPT");
25681
+ if (!programs || typeof programs !== "object" || Array.isArray(programs) || Object.keys(programs).length > 32 || Object.entries(programs).some(([name2, executable]) => !/^[a-z0-9_.-]{1,64}$/.test(name2) || typeof executable !== "string" || !path5.isAbsolute(executable) || executable.length > 4096 || /[\u0000-\u001f]/.test(executable))) throw fail("STATE_CORRUPT");
25682
+ if (!Array.isArray(workspaces) || workspaces.length > 32 || workspaces.some((w) => !w || !UUID.test(w.workspaceGrantId) || typeof w.root !== "string" || !path5.isAbsolute(w.root) || w.root.length > 4096 || /[\u0000-\u001f]/.test(w.root) || !/^[a-f0-9]{64}$/.test(w.rootHash) || typeof w.displayName !== "string" || !w.displayName || w.displayName.length > 120 || w.policyVersion !== 1 || !w.permissions || w.permissions.readFiles !== true || typeof w.permissions.writeFiles !== "boolean" || typeof w.permissions.executeCommands !== "boolean" || typeof w.permissions.localhost !== "boolean" || !Array.isArray(w.allowedCommands) || w.allowedCommands.length > 32 || w.allowedCommands.some((name2) => typeof name2 !== "string" || !Object.hasOwn(programs, name2)) || new Set(w.allowedCommands).size !== w.allowedCommands.length || w.permissions.executeCommands !== w.allowedCommands.length > 0 || !Array.isArray(w.localhostPorts) || w.localhostPorts.length > 32 || w.localhostPorts.some((port) => !Number.isInteger(port) || port < 1 || port > 65535) || new Set(w.localhostPorts).size !== w.localhostPorts.length || w.permissions.localhost !== w.localhostPorts.length > 0)) throw fail("STATE_CORRUPT");
25569
25683
  if (new Set(workspaces.map((w) => w.workspaceGrantId)).size !== workspaces.length || new Set(workspaces.map((w) => w.rootHash)).size !== workspaces.length) throw fail("STATE_CORRUPT");
25570
25684
  if (workspaces.some((w) => pendingWorkspaceRevokes.includes(w.workspaceGrantId))) throw fail("STATE_CORRUPT");
25571
- return { version: 1, publicKeyPem: value.publicKeyPem, privateKeyPem: value.privateKeyPem, fingerprint: value.fingerprint, dataKey: value.dataKey, ...enrollment ? { enrollment } : {}, workspaces, programs, pendingWorkspaceRevokes, ...policyBundle ? { policyBundle } : {}, ...approvals?.success ? { approvals: approvals.data } : {}, ...value.guardRequired ? { guardRequired: true } : {}, ...guard ? { guard } : {} };
25685
+ return { version: 1, publicKeyPem: value.publicKeyPem, privateKeyPem: value.privateKeyPem, fingerprint: value.fingerprint, dataKey: value.dataKey, ...enrollment ? { enrollment } : {}, workspaces, programs, pendingWorkspaceRevokes, ...value.permissionHistory ? { permissionHistory: permissionHistory.data } : {}, ...policyBundle ? { policyBundle } : {}, ...approvals?.success ? { approvals: approvals.data } : {}, ...value.guardRequired ? { guardRequired: true } : {}, ...guard ? { guard } : {} };
25572
25686
  }
25573
25687
  async function noSymlinkChain(target) {
25574
- if (!path3.isAbsolute(target)) throw fail("STORE_DIRECTORY_INVALID");
25575
- const absolute2 = path3.resolve(target);
25576
- if (absolute2 === path3.parse(absolute2).root) throw fail("STORE_DIRECTORY_INVALID");
25688
+ if (!path5.isAbsolute(target)) throw fail("STORE_DIRECTORY_INVALID");
25689
+ const absolute2 = path5.resolve(target);
25690
+ if (absolute2 === path5.parse(absolute2).root) throw fail("STORE_DIRECTORY_INVALID");
25577
25691
  const missing = [];
25578
25692
  let cursor = absolute2;
25579
25693
  for (; ; ) {
25580
25694
  try {
25581
- const stat = await lstat2(cursor);
25695
+ const stat = await lstat3(cursor);
25582
25696
  if (stat.isSymbolicLink()) throw fail("STORE_DIRECTORY_INVALID");
25583
25697
  break;
25584
25698
  } catch (error62) {
25585
25699
  if (error62.code !== "ENOENT") throw error62;
25586
25700
  missing.push(cursor);
25587
- const parent = path3.dirname(cursor);
25701
+ const parent = path5.dirname(cursor);
25588
25702
  if (parent === cursor) throw fail("STORE_DIRECTORY_INVALID");
25589
25703
  cursor = parent;
25590
25704
  }
25591
25705
  }
25592
- const canonicalParent = await realpath2(cursor);
25593
- if (!equalPath(cursor, canonicalParent)) throw fail("STORE_DIRECTORY_INVALID");
25706
+ const canonicalParent = await realpath3(cursor);
25707
+ if (!equalPath2(cursor, canonicalParent)) throw fail("STORE_DIRECTORY_INVALID");
25594
25708
  return absolute2;
25595
25709
  }
25596
25710
  function allowedDirectory(absolute2) {
25597
- const localAppData = process.env.LOCALAPPDATA || path3.join(os.homedir(), "AppData", "Local");
25598
- const appRoot = path3.resolve(localAppData, "LocalCommander");
25599
- const tempRoot = path3.resolve(os.tmpdir());
25711
+ const localAppData = process.env.LOCALAPPDATA || path5.join(os.homedir(), "AppData", "Local");
25712
+ const appRoot = path5.resolve(localAppData, "LocalCommander");
25713
+ const tempRoot = path5.resolve(os.tmpdir());
25600
25714
  if (under(absolute2, appRoot)) return;
25601
- if (under(absolute2, tempRoot) && /^lc-private-[A-Za-z0-9_.-]+$/i.test(path3.basename(absolute2))) return;
25715
+ if (under(absolute2, tempRoot) && /^lc-private-[A-Za-z0-9_.-]+$/i.test(path5.basename(absolute2))) return;
25602
25716
  throw fail("STORE_DIRECTORY_POLICY");
25603
25717
  }
25604
25718
  async function canonicalBridge(value) {
25605
- if (typeof value !== "string" || !path3.isAbsolute(value) || path3.extname(value).toLowerCase() !== ".exe") throw fail("BRIDGE_INVALID");
25606
- const stat = await lstat2(value).catch(() => {
25719
+ if (typeof value !== "string" || !path5.isAbsolute(value) || path5.extname(value).toLowerCase() !== ".exe") throw fail("BRIDGE_INVALID");
25720
+ const stat = await lstat3(value).catch(() => {
25607
25721
  throw fail("BRIDGE_INVALID");
25608
25722
  });
25609
25723
  if (!stat.isFile() || stat.isSymbolicLink() || stat.size < 1 || stat.size > 4 * 1024 * 1024) throw fail("BRIDGE_INVALID");
25610
- const canonical2 = await realpath2(value);
25611
- if (!equalPath(value, canonical2)) throw fail("BRIDGE_INVALID");
25724
+ const canonical2 = await realpath3(value);
25725
+ if (!equalPath2(value, canonical2)) throw fail("BRIDGE_INVALID");
25612
25726
  return canonical2;
25613
25727
  }
25614
25728
  function parseBridgeData(value, max = MAX_STATE_BYTES * 4) {
@@ -25640,11 +25754,11 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
25640
25754
  }
25641
25755
  const approved = /* @__PURE__ */ new Set([MARKER, "owner-state.dat", "owner-state.lock", "journal"]);
25642
25756
  if (names.length && !names.includes(MARKER)) throw fail("STORE_DIRECTORY_UNKNOWN");
25643
- if (names.some((name) => !approved.has(name))) throw fail("STORE_DIRECTORY_UNKNOWN");
25757
+ if (names.some((name2) => !approved.has(name2))) throw fail("STORE_DIRECTORY_UNKNOWN");
25644
25758
  await _WindowsPrivateStore.invoke(bridge, "init-directory", { path: absolute2 }, 5e3, false);
25645
- const canonical2 = await realpath2(absolute2);
25646
- if (!equalPath(absolute2, canonical2) || (await lstat2(canonical2)).isSymbolicLink()) throw fail("STORE_DIRECTORY_INVALID");
25647
- const markerPath = path3.join(canonical2, MARKER);
25759
+ const canonical2 = await realpath3(absolute2);
25760
+ if (!equalPath2(absolute2, canonical2) || (await lstat3(canonical2)).isSymbolicLink()) throw fail("STORE_DIRECTORY_INVALID");
25761
+ const markerPath = path5.join(canonical2, MARKER);
25648
25762
  try {
25649
25763
  await writeFile(markerPath, "LocalCommander private state\n", { flag: "wx", mode: 384 });
25650
25764
  } catch (error62) {
@@ -25659,10 +25773,10 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
25659
25773
  return result2;
25660
25774
  }
25661
25775
  statePath() {
25662
- return path3.join(this.dir, "owner-state.dat");
25776
+ return path5.join(this.dir, "owner-state.dat");
25663
25777
  }
25664
25778
  lockPath() {
25665
- return path3.join(this.dir, "owner-state.lock");
25779
+ return path5.join(this.dir, "owner-state.lock");
25666
25780
  }
25667
25781
  static invoke(bridge, arg, body, timeoutMs2, interactive, signal) {
25668
25782
  return new Promise((resolve, reject) => {
@@ -25757,9 +25871,21 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
25757
25871
  }
25758
25872
  }
25759
25873
  }
25874
+ /** After an owner approval, a briefly busy lock (the running agent) must not discard the decision. */
25875
+ async withLockWait(fn, waitMs) {
25876
+ const deadline = Date.now() + waitMs;
25877
+ for (; ; ) {
25878
+ try {
25879
+ return await this.withLock(fn);
25880
+ } catch (error62) {
25881
+ if (error62.code !== "STORE_LOCKED" || Date.now() >= deadline) throw error62;
25882
+ await new Promise((resolve) => setTimeout(resolve, 100));
25883
+ }
25884
+ }
25885
+ }
25760
25886
  async readState() {
25761
25887
  try {
25762
- const stat = await lstat2(this.statePath());
25888
+ const stat = await lstat3(this.statePath());
25763
25889
  if (!stat.isFile() || stat.isSymbolicLink() || stat.size < 1 || stat.size > MAX_STATE_BYTES * 4) throw fail("STATE_CORRUPT");
25764
25890
  const encrypted = await readFile2(this.statePath());
25765
25891
  const plaintext = await this.unprotect(encrypted);
@@ -25773,9 +25899,9 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
25773
25899
  }
25774
25900
  async rawHash() {
25775
25901
  try {
25776
- const stat = await lstat2(this.statePath());
25902
+ const stat = await lstat3(this.statePath());
25777
25903
  if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_STATE_BYTES * 4) throw fail("STATE_CORRUPT");
25778
- return createHash7("sha256").update(await readFile2(this.statePath())).digest("hex");
25904
+ return createHash8("sha256").update(await readFile2(this.statePath())).digest("hex");
25779
25905
  } catch (error62) {
25780
25906
  if (error62.code === "ENOENT") return null;
25781
25907
  throw error62;
@@ -25786,7 +25912,7 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
25786
25912
  const plaintext = Buffer.from(JSON.stringify(validateState(state)), "utf8");
25787
25913
  if (plaintext.length > MAX_STATE_BYTES) throw fail("STATE_TOO_LARGE");
25788
25914
  const encrypted = await this.protect(plaintext);
25789
- const temp = path3.join(this.dir, "owner-state." + randomBytes3(8).toString("hex") + ".tmp");
25915
+ const temp = path5.join(this.dir, "owner-state." + randomBytes3(8).toString("hex") + ".tmp");
25790
25916
  const handle = await open3(temp, constants2.O_CREAT | constants2.O_EXCL | constants2.O_WRONLY, 384);
25791
25917
  let closed = false;
25792
25918
  try {
@@ -25838,6 +25964,7 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
25838
25964
  state.workspaces = [];
25839
25965
  state.programs = {};
25840
25966
  state.pendingWorkspaceRevokes = [];
25967
+ delete state.permissionHistory;
25841
25968
  }
25842
25969
  state.enrollment = next;
25843
25970
  await this.writeState(state, before);
@@ -25855,6 +25982,7 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
25855
25982
  state.workspaces = [];
25856
25983
  state.programs = {};
25857
25984
  state.pendingWorkspaceRevokes = [];
25985
+ delete state.permissionHistory;
25858
25986
  await this.writeState(state, before);
25859
25987
  }));
25860
25988
  }
@@ -25974,7 +26102,7 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
25974
26102
  "guard-review",
25975
26103
  { data: Buffer.from(summary).toString("base64") },
25976
26104
  timeoutMs2,
25977
- false,
26105
+ true,
25978
26106
  signal
25979
26107
  );
25980
26108
  if (typeof answer?.approved !== "boolean" || typeof answer.ownerSid !== "string" || !/^S-1-(?:[0-9]+-)+[0-9]+$/.test(answer.ownerSid)) throw fail("GUARD_REVIEW_INVALID");
@@ -26016,7 +26144,7 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
26016
26144
  });
26017
26145
  }
26018
26146
  loadPrograms() {
26019
- return this.run(async () => Object.fromEntries(Object.entries((await this.readState())?.programs ?? {}).map(([name, executable]) => [name, { executable }])));
26147
+ return this.run(async () => Object.fromEntries(Object.entries((await this.readState())?.programs ?? {}).map(([name2, executable]) => [name2, { executable }])));
26020
26148
  }
26021
26149
  loadPendingWorkspaceRevokes() {
26022
26150
  return this.run(async () => [...(await this.readState())?.pendingWorkspaceRevokes ?? []]);
@@ -26036,7 +26164,7 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
26036
26164
  const before = await this.rawHash();
26037
26165
  state.workspaces = state.workspaces.filter((w) => w.workspaceGrantId !== id);
26038
26166
  state.pendingWorkspaceRevokes = [...state.pendingWorkspaceRevokes ?? [], id];
26039
- for (const name of Object.keys(state.programs ?? {})) if (!state.workspaces.some((w) => w.allowedCommands.includes(name))) delete state.programs[name];
26167
+ for (const name2 of Object.keys(state.programs ?? {})) if (!state.workspaces.some((w) => w.allowedCommands.includes(name2))) delete state.programs[name2];
26040
26168
  await this.writeState(state, before);
26041
26169
  }));
26042
26170
  }
@@ -26049,51 +26177,112 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
26049
26177
  await this.writeState(state, before);
26050
26178
  }));
26051
26179
  }
26052
- setWorkspacePermissions(change) {
26053
- return this.run(() => this.withLock(async () => {
26054
- const state = await this.readState();
26180
+ async setWorkspacePermissions(change) {
26181
+ const request = parsePermissionChange(change);
26182
+ const context = (state) => {
26055
26183
  if (!state?.enrollment) throw fail("ENROLLMENT_REQUIRED");
26056
- if (typeof change.workspaceGrantId !== "string" || !UUID.test(change.workspaceGrantId) || typeof change.enabled !== "boolean") throw fail("PERMISSION_INVALID");
26057
- const current2 = state.workspaces?.find((w) => w.workspaceGrantId === change.workspaceGrantId.toLowerCase());
26058
- if (!current2) throw fail("WORKSPACE_UNKNOWN");
26059
- const workspace = structuredClone(current2), programs = { ...state.programs ?? {} };
26060
- if (change.kind === "write") workspace.permissions.writeFiles = change.enabled;
26061
- else if (change.kind === "localhost") {
26062
- if (!Number.isInteger(change.port) || change.port < 1 || change.port > 65535) throw fail("PERMISSION_INVALID");
26063
- workspace.localhostPorts = change.enabled ? [.../* @__PURE__ */ new Set([...workspace.localhostPorts, change.port])].sort((a, b) => a - b) : workspace.localhostPorts.filter((port) => port !== change.port);
26064
- workspace.permissions.localhost = workspace.localhostPorts.length > 0;
26065
- } else if (change.kind === "command") {
26066
- const name = change.name?.toLowerCase();
26067
- if (!name || !/^[a-z0-9_.-]{1,64}$/.test(name)) throw fail("PERMISSION_INVALID");
26068
- if (change.enabled) {
26069
- const executable = change.executable;
26070
- if (typeof executable !== "string" || !path3.isAbsolute(executable) || path3.extname(executable).toLowerCase() !== ".exe" || executable.length > 4096 || /[\u0000-\u001f]/.test(executable)) throw fail("PERMISSION_INVALID");
26071
- const stat = await lstat2(executable).catch(() => {
26072
- throw fail("PERMISSION_INVALID");
26073
- });
26074
- if (!stat.isFile() || stat.isSymbolicLink() || !equalPath(executable, await realpath2(executable))) throw fail("PERMISSION_INVALID");
26075
- if (Object.hasOwn(programs, name) && !equalPath(programs[name], executable)) throw fail("COMMAND_CONFLICT");
26076
- programs[name] = executable;
26077
- workspace.allowedCommands = [.../* @__PURE__ */ new Set([...workspace.allowedCommands, name])].sort();
26078
- } else workspace.allowedCommands = workspace.allowedCommands.filter((value) => value !== name);
26079
- workspace.permissions.executeCommands = workspace.allowedCommands.length > 0;
26080
- } else throw fail("PERMISSION_INVALID");
26081
- state.workspaces = state.workspaces.map((w) => w.workspaceGrantId === workspace.workspaceGrantId ? workspace : w);
26082
- for (const name of Object.keys(programs)) if (!state.workspaces.some((w) => w.allowedCommands.includes(name))) delete programs[name];
26083
- state.programs = programs;
26184
+ const workspace = state.workspaces?.find((w) => w.workspaceGrantId === request.workspaceGrantId);
26185
+ if (!workspace) throw fail("WORKSPACE_UNKNOWN");
26186
+ const programs = state.programs ?? {};
26187
+ return { workspace, programs, enrollment: state.enrollment, fingerprint: permissionHash({
26188
+ enrollment: state.enrollment,
26189
+ workspace,
26190
+ programs: Object.entries(programs).sort(([a], [b]) => a.localeCompare(b)),
26191
+ guard: state.guard ?? null,
26192
+ guardRequired: state.guardRequired ?? false
26193
+ }) };
26194
+ };
26195
+ const initial = await this.run(async () => context(await this.readState()));
26196
+ const proposal = await planPermissionChange(initial.workspace, initial.programs, request);
26197
+ const review = await this.reviewGuard("Account: " + permissionLabel(initial.enrollment.accountEmail) + "\n" + proposal.summary, void 0, 6e4);
26198
+ if (!review.approved) throw fail("PERMISSION_REJECTED");
26199
+ return this.run(() => this.withLockWait(async () => {
26200
+ const state = await this.readState();
26201
+ const current2 = context(state);
26202
+ if (current2.fingerprint !== initial.fingerprint) throw fail("PERMISSION_STATE_CHANGED");
26203
+ if (state.guard && state.guard.ownerSid !== review.ownerSid) throw fail("PERMISSION_OWNER_MISMATCH");
26204
+ const verified = await planPermissionChange(current2.workspace, current2.programs, request);
26205
+ if (verified.resourceHash !== proposal.resourceHash) throw fail("PERMISSION_STATE_CHANGED");
26084
26206
  const before = await this.rawHash();
26207
+ state.workspaces = state.workspaces.map((w) => w.workspaceGrantId === verified.workspace.workspaceGrantId ? verified.workspace : w);
26208
+ state.programs = verified.programs;
26209
+ for (const name2 of Object.keys(state.programs)) if (!state.workspaces.some((w) => w.allowedCommands.includes(name2))) delete state.programs[name2];
26210
+ const record2 = {
26211
+ id: randomUUID3(),
26212
+ changedAt: (/* @__PURE__ */ new Date()).toISOString(),
26213
+ workspaceGrantId: request.workspaceGrantId,
26214
+ kind: request.kind,
26215
+ enabled: request.enabled,
26216
+ resourceHash: verified.resourceHash,
26217
+ ownerSid: review.ownerSid
26218
+ };
26219
+ state.permissionHistory = PermissionHistorySchema.parse([...state.permissionHistory ?? [], record2].slice(-PERMISSION_HISTORY_LIMIT));
26085
26220
  await this.writeState(state, before);
26086
- return workspace;
26221
+ return structuredClone(verified.workspace);
26222
+ }, 5e3));
26223
+ }
26224
+ /** Replace scope only after an explicit local dialog; updates never call this implicitly. */
26225
+ async configureAccess() {
26226
+ const expected = await this.run(() => this.withLock(async () => {
26227
+ if (!(await this.readState())?.enrollment) throw fail("ENROLLMENT_REQUIRED");
26228
+ return this.rawHash();
26229
+ }));
26230
+ const decision = await this.chooseAccess();
26231
+ if (decision === null) return null;
26232
+ const selected = parseAccessSelection(decision);
26233
+ if (!selected) return null;
26234
+ const roots = [];
26235
+ for (const chosen of selected.paths) {
26236
+ const stat = await lstat3(chosen);
26237
+ if (!stat.isDirectory() || stat.isSymbolicLink()) throw fail("WORKSPACE_INVALID");
26238
+ const root = await realpath3(chosen);
26239
+ const isDrive = equalPath2(root, path5.parse(root).root);
26240
+ if (!equalPath2(root, chosen) || (selected.mode === "all-drives" ? !isDrive : isDrive) || equalPath2(root, this.dir) || under(root, this.dir) || selected.mode === "folders" && under(this.dir, root)) throw fail("WORKSPACE_INVALID");
26241
+ roots.push(root);
26242
+ }
26243
+ return this.run(() => this.withLock(async () => {
26244
+ if (await this.rawHash() !== expected) throw fail("STATE_CHANGED");
26245
+ const state = await this.readState();
26246
+ if (!state?.enrollment) throw fail("ENROLLMENT_REQUIRED");
26247
+ const workspaces = roots.map((root) => {
26248
+ const rootHash = createHash8("sha256").update(process.platform === "win32" ? root.toLowerCase() : root).digest("hex");
26249
+ const existing = state.workspaces?.find((w) => w.rootHash === rootHash);
26250
+ return {
26251
+ workspaceGrantId: existing?.workspaceGrantId ?? randomUUID3(),
26252
+ root,
26253
+ rootHash,
26254
+ displayName: (path5.basename(root) || root).slice(0, 120),
26255
+ policyVersion: 1,
26256
+ permissions: { readFiles: true, writeFiles: true, executeCommands: false, localhost: false },
26257
+ allowedCommands: [],
26258
+ localhostPorts: []
26259
+ };
26260
+ });
26261
+ const retained = new Set(workspaces.map((w) => w.workspaceGrantId));
26262
+ const removed = (state.workspaces ?? []).filter((w) => !retained.has(w.workspaceGrantId)).map((w) => w.workspaceGrantId);
26263
+ const pending = [.../* @__PURE__ */ new Set([...state.pendingWorkspaceRevokes ?? [], ...removed])];
26264
+ if (pending.length > 32) throw fail("WORKSPACE_REVOKE_LIMIT");
26265
+ state.workspaces = workspaces;
26266
+ state.programs = {};
26267
+ state.pendingWorkspaceRevokes = pending;
26268
+ await this.writeState(state, expected);
26269
+ return structuredClone(workspaces);
26087
26270
  }));
26088
26271
  }
26272
+ chooseAccess() {
26273
+ return this.run(async () => parseAccessSelection(await _WindowsPrivateStore.invoke(this.bridge, "choose-access", {}, 24e4, true)));
26274
+ }
26275
+ loadPermissionHistory() {
26276
+ return this.run(async () => structuredClone((await this.readState())?.permissionHistory ?? []));
26277
+ }
26089
26278
  async approveWorkspace() {
26090
26279
  const chosen = await this.chooseFolder();
26091
26280
  if (chosen === null) return null;
26092
- const stat = await lstat2(chosen);
26281
+ const stat = await lstat3(chosen);
26093
26282
  if (!stat.isDirectory() || stat.isSymbolicLink()) throw fail("WORKSPACE_INVALID");
26094
- const root = await realpath2(chosen);
26095
- if (!equalPath(root, chosen) || equalPath(root, path3.parse(root).root) || equalPath(root, this.dir) || under(this.dir, root)) throw fail("WORKSPACE_INVALID");
26096
- const rootHash = createHash7("sha256").update(process.platform === "win32" ? root.toLowerCase() : root).digest("hex");
26283
+ const root = await realpath3(chosen);
26284
+ if (!equalPath2(root, chosen) || equalPath2(root, path5.parse(root).root) || equalPath2(root, this.dir) || under(this.dir, root)) throw fail("WORKSPACE_INVALID");
26285
+ const rootHash = createHash8("sha256").update(process.platform === "win32" ? root.toLowerCase() : root).digest("hex");
26097
26286
  return this.run(() => this.withLock(async () => {
26098
26287
  const state = await this.readState();
26099
26288
  if (!state?.enrollment) throw fail("ENROLLMENT_REQUIRED");
@@ -26101,7 +26290,7 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
26101
26290
  if (existing) return existing;
26102
26291
  if ((state.workspaces?.length ?? 0) >= 32) throw fail("WORKSPACE_LIMIT");
26103
26292
  const before = await this.rawHash();
26104
- const workspace = { workspaceGrantId: randomUUID3(), root, rootHash, displayName: path3.basename(root).slice(0, 120), policyVersion: 1, permissions: { readFiles: true, writeFiles: false, executeCommands: false, localhost: false }, allowedCommands: [], localhostPorts: [] };
26293
+ const workspace = { workspaceGrantId: randomUUID3(), root, rootHash, displayName: path5.basename(root).slice(0, 120), policyVersion: 1, permissions: { readFiles: true, writeFiles: true, executeCommands: false, localhost: false }, allowedCommands: [], localhostPorts: [] };
26105
26294
  state.workspaces = [...state.workspaces ?? [], workspace];
26106
26295
  await this.writeState(state, before);
26107
26296
  return workspace;
@@ -26111,7 +26300,7 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
26111
26300
  return this.run(async () => {
26112
26301
  const result2 = await _WindowsPrivateStore.invoke(this.bridge, "choose-folder", {}, 12e4, true);
26113
26302
  if (result2.path === null) return null;
26114
- if (typeof result2.path !== "string" || !path3.isAbsolute(result2.path) || result2.path.length > 4096 || /[\u0000-\u001f]/.test(result2.path)) throw fail("BRIDGE_OUTPUT_INVALID");
26303
+ if (typeof result2.path !== "string" || !path5.isAbsolute(result2.path) || result2.path.length > 4096 || /[\u0000-\u001f]/.test(result2.path)) throw fail("BRIDGE_OUTPUT_INVALID");
26115
26304
  return result2.path;
26116
26305
  });
26117
26306
  }
@@ -26119,22 +26308,40 @@ var WindowsPrivateStore = class _WindowsPrivateStore {
26119
26308
 
26120
26309
  // agent/src/tools.ts
26121
26310
  import { constants as constants3 } from "node:fs";
26122
- import { lstat as lstat4, open as open4, readdir as readdir3, realpath as realpath4, rename as rename3, rm as rm3 } from "node:fs/promises";
26123
- import path7 from "node:path";
26124
- import { createHash as createHash8, randomUUID as randomUUID4 } from "node:crypto";
26311
+ import { lstat as lstat5, open as open4, readdir as readdir3, realpath as realpath5, rename as rename3, rm as rm3 } from "node:fs/promises";
26312
+ import path9 from "node:path";
26313
+ import { createHash as createHash9, randomUUID as randomUUID4 } from "node:crypto";
26125
26314
 
26126
26315
  // src/guard.ts
26127
- import { lstat as lstat3, realpath as realpath3 } from "node:fs/promises";
26128
- import path4 from "node:path";
26316
+ import { lstat as lstat4, realpath as realpath4 } from "node:fs/promises";
26317
+ import path6 from "node:path";
26129
26318
  var SENSITIVE_NAMES = /* @__PURE__ */ new Set([
26130
26319
  ".npmrc",
26131
26320
  ".pypirc",
26132
26321
  ".git-credentials",
26133
26322
  "id_rsa",
26134
26323
  "id_ed25519",
26135
- "credentials.json"
26324
+ "id_ecdsa",
26325
+ "id_dsa",
26326
+ ".netrc",
26327
+ "_netrc",
26328
+ ".pgpass",
26329
+ "credentials.json",
26330
+ "application_default_credentials.json"
26136
26331
  ]);
26137
- var SENSITIVE_EXTENSIONS = /* @__PURE__ */ new Set([".pem", ".key", ".p12", ".pfx"]);
26332
+ var SENSITIVE_EXTENSIONS = /* @__PURE__ */ new Set([".pem", ".key", ".p12", ".pfx", ".ppk", ".kdbx"]);
26333
+ var SENSITIVE_IN_DIRECTORY = [
26334
+ [".aws", "credentials"],
26335
+ [".kube", "config"],
26336
+ [".docker", "config.json"],
26337
+ [".claude", ".credentials.json"],
26338
+ [".codex", "auth.json"],
26339
+ [".azure", "msal_token_cache.json"],
26340
+ [".azure", "accesstokens.json"],
26341
+ ["gh", "hosts.yml"],
26342
+ ["github cli", "hosts.yml"]
26343
+ ];
26344
+ var SENSITIVE_DIRECTORIES = /* @__PURE__ */ new Set([".ssh", ".gnupg"]);
26138
26345
  var PROTECTED_FILE_NAMES = /* @__PURE__ */ new Set([
26139
26346
  ".local-commander-oauth.json",
26140
26347
  "local-commander.config.json"
@@ -26144,12 +26351,12 @@ function comparePath(value) {
26144
26351
  return process.platform === "win32" ? value.toLowerCase() : value;
26145
26352
  }
26146
26353
  function isInside(root, candidate) {
26147
- const relative = path4.relative(root, candidate);
26148
- return relative === "" || !path4.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path4.sep}`);
26354
+ const relative = path6.relative(root, candidate);
26355
+ return relative === "" || !path6.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path6.sep}`);
26149
26356
  }
26150
26357
  function splitPathSegments(filePath) {
26151
- const parsed = path4.parse(path4.resolve(filePath));
26152
- return path4.relative(parsed.root, path4.resolve(filePath)).split(path4.sep).filter((segment) => segment.length > 0);
26358
+ const parsed = path6.parse(path6.resolve(filePath));
26359
+ return path6.relative(parsed.root, path6.resolve(filePath)).split(path6.sep).filter((segment) => segment.length > 0);
26153
26360
  }
26154
26361
  function isProtectedAuditFile(base) {
26155
26362
  return base === ".local-commander-audit.jsonl" || base.startsWith(".local-commander-audit.jsonl.");
@@ -26164,37 +26371,40 @@ function looksProtected(filePath) {
26164
26371
  return false;
26165
26372
  }
26166
26373
  function looksSensitive(filePath) {
26167
- const base = path4.basename(filePath).toLowerCase();
26374
+ const base = path6.basename(filePath).toLowerCase();
26168
26375
  if (base === ".env" || base.startsWith(".env.") && base !== ".env.example") return true;
26169
26376
  if (SENSITIVE_NAMES.has(base)) return true;
26170
- if (SENSITIVE_EXTENSIONS.has(path4.extname(base))) return true;
26171
- return false;
26377
+ if (SENSITIVE_EXTENSIONS.has(path6.extname(base))) return true;
26378
+ const segments = splitPathSegments(filePath).map((segment) => segment.toLowerCase());
26379
+ if (segments.slice(0, -1).some((segment) => SENSITIVE_DIRECTORIES.has(segment))) return true;
26380
+ const parent = segments.at(-2);
26381
+ return SENSITIVE_IN_DIRECTORY.some(([directory, name2]) => directory === parent && name2 === base);
26172
26382
  }
26173
26383
  async function canonicalizePossiblyMissing(inputPath, base) {
26174
- const absolute2 = path4.isAbsolute(inputPath) ? path4.resolve(inputPath) : path4.resolve(base, inputPath);
26175
- const parsed = path4.parse(absolute2);
26384
+ const absolute2 = path6.isAbsolute(inputPath) ? path6.resolve(inputPath) : path6.resolve(base, inputPath);
26385
+ const parsed = path6.parse(absolute2);
26176
26386
  let current2 = absolute2;
26177
26387
  const missing = [];
26178
26388
  while (current2 !== parsed.root) {
26179
26389
  try {
26180
- const resolved = await realpath3(current2);
26181
- return path4.join(resolved, ...missing.reverse());
26390
+ const resolved = await realpath4(current2);
26391
+ return path6.join(resolved, ...missing.reverse());
26182
26392
  } catch (error62) {
26183
26393
  if (error62.code !== "ENOENT") throw error62;
26184
26394
  let exists = false;
26185
26395
  try {
26186
- await lstat3(current2);
26396
+ await lstat4(current2);
26187
26397
  exists = true;
26188
26398
  } catch (statError) {
26189
26399
  if (statError.code !== "ENOENT") throw statError;
26190
26400
  }
26191
26401
  if (exists) throw error62;
26192
- missing.push(path4.basename(current2));
26193
- current2 = path4.dirname(current2);
26402
+ missing.push(path6.basename(current2));
26403
+ current2 = path6.dirname(current2);
26194
26404
  }
26195
26405
  }
26196
- const root = await realpath3(parsed.root);
26197
- return path4.join(root, ...missing.reverse());
26406
+ const root = await realpath4(parsed.root);
26407
+ return path6.join(root, ...missing.reverse());
26198
26408
  }
26199
26409
  var PathGuard = class _PathGuard {
26200
26410
  constructor(roots, allowSensitiveFiles, protectedPaths) {
@@ -26210,11 +26420,11 @@ var PathGuard = class _PathGuard {
26210
26420
  for (const root of roots) {
26211
26421
  let resolved;
26212
26422
  try {
26213
- resolved = await realpath3(path4.resolve(root));
26423
+ resolved = await realpath4(path6.resolve(root));
26214
26424
  } catch {
26215
26425
  throw new Error(`Configured root does not exist: ${root}`);
26216
26426
  }
26217
- const stat = await lstat3(resolved);
26427
+ const stat = await lstat4(resolved);
26218
26428
  if (!stat.isDirectory()) throw new Error(`Configured root is not a directory: ${root}`);
26219
26429
  if (!canonical2.some((existing) => comparePath(existing) === comparePath(resolved))) {
26220
26430
  canonical2.push(resolved);
@@ -26223,8 +26433,8 @@ var PathGuard = class _PathGuard {
26223
26433
  if (canonical2.length === 0) throw new Error("At least one allowed root is required");
26224
26434
  const protectedPaths = [];
26225
26435
  for (const protectedPath of options.protectedPaths ?? []) {
26226
- const base = path4.isAbsolute(protectedPath) ? path4.parse(path4.resolve(protectedPath)).root : canonical2[0];
26227
- const absolute2 = path4.resolve(base, protectedPath);
26436
+ const base = path6.isAbsolute(protectedPath) ? path6.parse(path6.resolve(protectedPath)).root : canonical2[0];
26437
+ const absolute2 = path6.resolve(base, protectedPath);
26228
26438
  if (!protectedPaths.some((existing) => comparePath(existing) === comparePath(absolute2))) protectedPaths.push(absolute2);
26229
26439
  const resolved = await canonicalizePossiblyMissing(protectedPath, base);
26230
26440
  if (!protectedPaths.some((existing) => comparePath(existing) === comparePath(resolved))) {
@@ -26240,7 +26450,7 @@ var PathGuard = class _PathGuard {
26240
26450
  }
26241
26451
  assertNotProtected(candidate) {
26242
26452
  if (looksProtected(candidate)) {
26243
- throw new Error(`Local Commander protected state is blocked: ${path4.basename(candidate)}`);
26453
+ throw new Error(`Local Commander protected state is blocked: ${path6.basename(candidate)}`);
26244
26454
  }
26245
26455
  const normalizedCandidate = comparePath(candidate);
26246
26456
  for (const protectedPath of this.protectedPaths) {
@@ -26253,37 +26463,37 @@ var PathGuard = class _PathGuard {
26253
26463
  this.assertNotProtected(filePath);
26254
26464
  if (!this.allowSensitiveFiles && looksSensitive(filePath)) {
26255
26465
  throw new Error(
26256
- `Sensitive file access is blocked by default: ${path4.basename(filePath)}. Enable files.allowSensitiveFiles only if you really need it.`
26466
+ `Sensitive file access is blocked by default: ${path6.basename(filePath)}. Enable files.allowSensitiveFiles only if you really need it.`
26257
26467
  );
26258
26468
  }
26259
26469
  }
26260
26470
  async resolveExisting(inputPath, cwd) {
26261
26471
  const base = cwd ? await this.resolveExisting(cwd) : this.roots[0];
26262
- const candidate = path4.isAbsolute(inputPath) ? path4.resolve(inputPath) : path4.resolve(base, inputPath);
26472
+ const candidate = path6.isAbsolute(inputPath) ? path6.resolve(inputPath) : path6.resolve(base, inputPath);
26263
26473
  this.assertNotProtected(candidate);
26264
- const resolved = await realpath3(candidate);
26474
+ const resolved = await realpath4(candidate);
26265
26475
  this.assertWithinRoots(resolved);
26266
26476
  this.assertNotProtected(resolved);
26267
26477
  return resolved;
26268
26478
  }
26269
26479
  async resolveDirectory(inputPath, cwd) {
26270
26480
  const resolved = await this.resolveExisting(inputPath, cwd);
26271
- const stat = await lstat3(resolved);
26481
+ const stat = await lstat4(resolved);
26272
26482
  if (!stat.isDirectory()) throw new Error(`Not a directory: ${resolved}`);
26273
26483
  return resolved;
26274
26484
  }
26275
26485
  async resolveForWrite(inputPath, cwd) {
26276
26486
  const base = cwd ? await this.resolveDirectory(cwd) : this.roots[0];
26277
- const candidate = path4.isAbsolute(inputPath) ? path4.resolve(inputPath) : path4.resolve(base, inputPath);
26487
+ const candidate = path6.isAbsolute(inputPath) ? path6.resolve(inputPath) : path6.resolve(base, inputPath);
26278
26488
  this.assertNotProtected(candidate);
26279
26489
  let existing;
26280
26490
  try {
26281
- existing = await realpath3(candidate);
26491
+ existing = await realpath4(candidate);
26282
26492
  } catch (error62) {
26283
26493
  if (error62.code !== "ENOENT") throw error62;
26284
26494
  let exists = false;
26285
26495
  try {
26286
- await lstat3(candidate);
26496
+ await lstat4(candidate);
26287
26497
  exists = true;
26288
26498
  } catch (statError) {
26289
26499
  if (statError.code !== "ENOENT") throw statError;
@@ -26296,11 +26506,11 @@ var PathGuard = class _PathGuard {
26296
26506
  this.assertSafeFile(existing);
26297
26507
  return existing;
26298
26508
  }
26299
- const parent = await realpath3(path4.dirname(candidate));
26509
+ const parent = await realpath4(path6.dirname(candidate));
26300
26510
  this.assertWithinRoots(parent);
26301
26511
  this.assertNotProtected(parent);
26302
26512
  this.assertSafeFile(candidate);
26303
- const target = path4.join(parent, path4.basename(candidate));
26513
+ const target = path6.join(parent, path6.basename(candidate));
26304
26514
  this.assertSafeFile(target);
26305
26515
  return target;
26306
26516
  }
@@ -26311,12 +26521,12 @@ var PathGuard = class _PathGuard {
26311
26521
 
26312
26522
  // src/windows-file-read.ts
26313
26523
  import { execFile } from "node:child_process";
26314
- import path5 from "node:path";
26524
+ import path7 from "node:path";
26315
26525
  function readWindowsFile(bridge, file2, maxBytes, signal) {
26316
26526
  return invokeRead(bridge, file2, maxBytes, false, signal);
26317
26527
  }
26318
26528
  function invokeRead(bridge, file2, maxBytes, prefix, signal) {
26319
- if (process.platform !== "win32" || !path5.isAbsolute(bridge) || !path5.isAbsolute(file2) || !Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > (prefix ? 16777216 : 1048576)) {
26529
+ if (process.platform !== "win32" || !path7.isAbsolute(bridge) || !path7.isAbsolute(file2) || !Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > (prefix ? 16777216 : 1048576)) {
26320
26530
  return Promise.reject(new Error("FILE_READ_ARGUMENT_INVALID"));
26321
26531
  }
26322
26532
  if (signal?.aborted) return Promise.reject(new Error("CANCELLED"));
@@ -26345,9 +26555,9 @@ function invokeRead(bridge, file2, maxBytes, prefix, signal) {
26345
26555
 
26346
26556
  // agent/src/job-supervisor.ts
26347
26557
  import { spawn as spawn2 } from "node:child_process";
26348
- import path6 from "node:path";
26558
+ import path8 from "node:path";
26349
26559
  function absolute(value) {
26350
- return typeof value === "string" && value.length > 0 && value.length < 32767 && !value.includes("\0") && path6.isAbsolute(value) && path6.resolve(value) === value;
26560
+ return typeof value === "string" && value.length > 0 && value.length < 32767 && !value.includes("\0") && path8.isAbsolute(value) && path8.resolve(value) === value;
26351
26561
  }
26352
26562
  async function runSupervised(helper, request, options = {}) {
26353
26563
  if (process.platform !== "win32") throw Error("WINDOWS_SUPERVISOR_REQUIRED");
@@ -26363,7 +26573,7 @@ async function runSupervised(helper, request, options = {}) {
26363
26573
  let pid = null, outcome = null;
26364
26574
  let buffer = "", failure5 = null, closed = false, cancelSent = false;
26365
26575
  let killTimer, hardTimer;
26366
- const child = spawn2(helper, [], { cwd: path6.dirname(helper), stdio: ["pipe", "pipe", "pipe"], windowsHide: true, shell: false, env: buildChildEnvironment(process.env) });
26576
+ const child = spawn2(helper, [], { cwd: path8.dirname(helper), stdio: ["pipe", "pipe", "pipe"], windowsHide: true, shell: false, env: buildChildEnvironment(process.env) });
26367
26577
  const cancel = () => {
26368
26578
  if (closed || cancelSent) return;
26369
26579
  cancelSent = true;
@@ -26465,9 +26675,9 @@ function fail2(code) {
26465
26675
  throw new NativeToolError(code);
26466
26676
  }
26467
26677
  function hash5(value) {
26468
- return createHash8("sha256").update(value).digest("hex");
26678
+ return createHash9("sha256").update(value).digest("hex");
26469
26679
  }
26470
- function equalPath2(a, b) {
26680
+ function equalPath3(a, b) {
26471
26681
  return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
26472
26682
  }
26473
26683
  function result(body) {
@@ -26479,7 +26689,7 @@ function stopped(signal) {
26479
26689
  if (signal.aborted) fail2("CANCELLED");
26480
26690
  }
26481
26691
  async function readBoundedFile(file2, maxBytes, bridge, signal) {
26482
- const stat = await lstat4(file2);
26692
+ const stat = await lstat5(file2);
26483
26693
  if (!stat.isFile() || stat.isSymbolicLink() || stat.size > maxBytes) fail2("FILE_UNSUPPORTED_OR_TOO_LARGE");
26484
26694
  if (process.platform === "win32") return readWindowsFile(bridge, file2, maxBytes, signal);
26485
26695
  const handle = await open4(file2, constants3.O_RDONLY | (constants3.O_NOFOLLOW ?? 0));
@@ -26517,7 +26727,7 @@ var NativeTools = class {
26517
26727
  options;
26518
26728
  async readFile(file2, maxBytes, signal) {
26519
26729
  try {
26520
- return await readBoundedFile(file2, maxBytes, this.options.ownerBridgePath ?? path7.join(path7.dirname(this.options.helperPath), "OwnerBridge.exe"), signal);
26730
+ return await readBoundedFile(file2, maxBytes, this.options.ownerBridgePath ?? path9.join(path9.dirname(this.options.helperPath), "OwnerBridge.exe"), signal);
26521
26731
  } catch (error62) {
26522
26732
  if (error62.code === "ENOENT") throw error62;
26523
26733
  if (error62 instanceof Error && /^[A-Z_]{1,40}$/.test(error62.message)) fail2(error62.message);
@@ -26540,9 +26750,19 @@ var NativeTools = class {
26540
26750
  if (scope2 === "files:read" && !permission.readFiles || scope2 === "files:write" && !permission.writeFiles || scope2 === "commands:execute" && !permission.executeCommands || scope2 === "localhost:access" && !permission.localhost) fail2("LOCAL_PERMISSION_REQUIRED");
26541
26751
  let guard;
26542
26752
  try {
26543
- const canonical2 = await realpath4(workspace.root);
26544
- if (!equalPath2(canonical2, workspace.root) || hash5(process.platform === "win32" ? canonical2.toLowerCase() : canonical2) !== workspace.rootHash) fail2("WORKSPACE_CHANGED");
26545
- guard = await PathGuard.create([canonical2], false, { protectedPaths: [this.options.stateDirectory] });
26753
+ const canonical2 = await realpath5(workspace.root);
26754
+ if (!equalPath3(canonical2, workspace.root) || hash5(process.platform === "win32" ? canonical2.toLowerCase() : canonical2) !== workspace.rootHash) fail2("WORKSPACE_CHANGED");
26755
+ const runtimeDirectory = path9.dirname(this.options.helperPath);
26756
+ const protectedPaths = [
26757
+ this.options.stateDirectory,
26758
+ this.options.helperPath,
26759
+ ...["agent.mjs", "node.exe", "OwnerBridge.exe", "LocalCommanderAgent.exe"].map((name2) => path9.join(runtimeDirectory, name2))
26760
+ ];
26761
+ if (this.options.ownerBridgePath) protectedPaths.push(this.options.ownerBridgePath);
26762
+ if (process.platform === "win32" && process.env.LOCALAPPDATA && path9.isAbsolute(process.env.LOCALAPPDATA)) {
26763
+ protectedPaths.push(path9.join(process.env.LOCALAPPDATA, "LocalCommander"));
26764
+ }
26765
+ guard = await PathGuard.create([canonical2], false, { protectedPaths });
26546
26766
  } catch (e) {
26547
26767
  if (e instanceof NativeToolError) throw e;
26548
26768
  fail2("WORKSPACE_UNAVAILABLE");
@@ -26568,11 +26788,11 @@ var NativeTools = class {
26568
26788
  return { call, claims: readClaim(filename), run: async (signal) => {
26569
26789
  stopped(signal);
26570
26790
  const verified = await resolve(call.args.path);
26571
- if (!equalPath2(verified, filename)) fail2("FILE_CHANGED");
26791
+ if (!equalPath3(verified, filename)) fail2("FILE_CHANGED");
26572
26792
  const bytes3 = await this.readFile(filename, 1048576, signal), contents = utf8(bytes3), lines = contents.split(/\r?\n/);
26573
26793
  const selected = lines.slice(first - 1, Math.min(last, lines.length)).join("\n");
26574
26794
  if (Buffer.byteLength(selected) > 12e4) fail2("OUTPUT_LIMIT_EXCEEDED");
26575
- return result({ path: path7.relative(workspace.root, filename), sha256: hash5(bytes3), startLine: first, endLine: Math.min(last, lines.length), totalLines: lines.length, content: selected, truncated: last < lines.length });
26795
+ return result({ path: path9.relative(workspace.root, filename), sha256: hash5(bytes3), startLine: first, endLine: Math.min(last, lines.length), totalLines: lines.length, content: selected, truncated: last < lines.length });
26576
26796
  } };
26577
26797
  }
26578
26798
  if (call.name === "fs_write" || call.name === "fs_replace") {
@@ -26587,7 +26807,7 @@ var NativeTools = class {
26587
26807
  return { call, claims: writeClaim(filename), run: async (signal) => {
26588
26808
  stopped(signal);
26589
26809
  const target = await guard.resolveForWrite(args.path);
26590
- if (!equalPath2(filename, target)) fail2("FILE_CHANGED");
26810
+ if (!equalPath3(filename, target)) fail2("FILE_CHANGED");
26591
26811
  let old = null;
26592
26812
  try {
26593
26813
  old = await this.readFile(target, 1048576, signal);
@@ -26608,7 +26828,7 @@ var NativeTools = class {
26608
26828
  }
26609
26829
  const bytes3 = Buffer.from(contents, "utf8");
26610
26830
  if (bytes3.length > MAX_FILE_WRITE_BYTES) fail2("FILE_WRITE_LIMIT");
26611
- const temp = path7.join(path7.dirname(target), ".lc-write-" + randomUUID4() + ".tmp");
26831
+ const temp = path9.join(path9.dirname(target), ".lc-write-" + randomUUID4() + ".tmp");
26612
26832
  const handle = await open4(temp, constants3.O_CREAT | constants3.O_EXCL | constants3.O_WRONLY, 384);
26613
26833
  try {
26614
26834
  await handle.writeFile(bytes3);
@@ -26616,7 +26836,7 @@ var NativeTools = class {
26616
26836
  await handle.close();
26617
26837
  stopped(signal);
26618
26838
  const again = await guard.resolveForWrite(args.path);
26619
- if (!equalPath2(target, again)) fail2("FILE_CHANGED");
26839
+ if (!equalPath3(target, again)) fail2("FILE_CHANGED");
26620
26840
  if (old) {
26621
26841
  if (hash5(await this.readFile(target, 1048576, signal)) !== hash5(old)) fail2("FILE_CHANGED");
26622
26842
  await rename3(temp, target);
@@ -26625,7 +26845,7 @@ var NativeTools = class {
26625
26845
  await link(temp, target);
26626
26846
  await rm3(temp);
26627
26847
  }
26628
- return result({ path: path7.relative(workspace.root, target), bytes: bytes3.length, sha256: hash5(bytes3), ...call.name === "fs_replace" ? { replacements } : {} });
26848
+ return result({ path: path9.relative(workspace.root, target), bytes: bytes3.length, sha256: hash5(bytes3), ...call.name === "fs_replace" ? { replacements } : {} });
26629
26849
  } catch (e) {
26630
26850
  await handle.close().catch(() => {
26631
26851
  });
@@ -26646,12 +26866,12 @@ var NativeTools = class {
26646
26866
  stopped(signal);
26647
26867
  if (matches2.length >= call.args.maxResults || scanned >= 300) break;
26648
26868
  try {
26649
- const filename = await guard.resolveExisting(path7.join(base, entry.path));
26869
+ const filename = await guard.resolveExisting(path9.join(base, entry.path));
26650
26870
  guard.assertSafeFile(filename);
26651
26871
  const data = utf8(await this.readFile(filename, 256e3, signal));
26652
26872
  scanned++;
26653
26873
  const lines = data.split(/\r?\n/);
26654
- for (let i = 0; i < lines.length && matches2.length < call.args.maxResults; i++) if ((call.args.caseSensitive ? lines[i] : lines[i].toLowerCase()).includes(query)) matches2.push({ path: path7.relative(workspace.root, filename), line: i + 1, text: lines[i].slice(0, 500) });
26874
+ for (let i = 0; i < lines.length && matches2.length < call.args.maxResults; i++) if ((call.args.caseSensitive ? lines[i] : lines[i].toLowerCase()).includes(query)) matches2.push({ path: path9.relative(workspace.root, filename), line: i + 1, text: lines[i].slice(0, 500) });
26655
26875
  } catch (error62) {
26656
26876
  if (error62 instanceof NativeToolError && ["FILE_READ_FAILED", "CANCELLED"].includes(error62.code)) throw error62;
26657
26877
  }
@@ -26663,9 +26883,9 @@ var NativeTools = class {
26663
26883
  const url2 = new URL(call.args.url), port = Number(url2.port || (url2.protocol === "https:" ? 443 : 80));
26664
26884
  if (!["http:", "https:"].includes(url2.protocol) || !["localhost", "127.0.0.1", "[::1]"].includes(url2.hostname) || url2.username || url2.password || url2.hash || !workspace.localhostPorts.includes(port) || this.options.protectedPorts?.includes(port)) fail2("LOCALHOST_NOT_ALLOWED");
26665
26885
  const headers = {};
26666
- for (const [name, value] of Object.entries(call.args.headers ?? {})) {
26667
- if (!/^[A-Za-z0-9-]+$/.test(name) || /[\r\n]/.test(value) || ["host", "connection", "content-length", "transfer-encoding", "upgrade", "proxy-authorization", "proxy-connection"].includes(name.toLowerCase()) || Object.keys(headers).some((k) => k.toLowerCase() === name.toLowerCase())) fail2("INVALID_HTTP_HEADER");
26668
- headers[name] = value;
26886
+ for (const [name2, value] of Object.entries(call.args.headers ?? {})) {
26887
+ if (!/^[A-Za-z0-9-]+$/.test(name2) || /[\r\n]/.test(value) || ["host", "connection", "content-length", "transfer-encoding", "upgrade", "proxy-authorization", "proxy-connection"].includes(name2.toLowerCase()) || Object.keys(headers).some((k) => k.toLowerCase() === name2.toLowerCase())) fail2("INVALID_HTTP_HEADER");
26888
+ headers[name2] = value;
26669
26889
  }
26670
26890
  if (Object.keys(headers).length > 32 || ["GET", "HEAD"].includes(call.args.method) && call.args.body !== void 0) fail2("INVALID_HTTP_ARGUMENTS");
26671
26891
  if (url2.hostname === "localhost") url2.hostname = "127.0.0.1";
@@ -26673,9 +26893,9 @@ var NativeTools = class {
26673
26893
  const combined = AbortSignal.any([signal, AbortSignal.timeout(1e4)]);
26674
26894
  const response = await fetch(url2, { method: call.args.method, headers, body: call.args.body, redirect: "manual", signal: combined });
26675
26895
  const selectedHeaders = {};
26676
- for (const name of ["content-type", "content-length", "location", "etag", "last-modified"]) {
26677
- const value = response.headers.get(name);
26678
- if (value) selectedHeaders[name] = value.slice(0, 2048);
26896
+ for (const name2 of ["content-type", "content-length", "location", "etag", "last-modified"]) {
26897
+ const value = response.headers.get(name2);
26898
+ if (value) selectedHeaders[name2] = value.slice(0, 2048);
26679
26899
  }
26680
26900
  const reader = response.body?.getReader(), chunks = [];
26681
26901
  let count = 0, truncated = false;
@@ -26702,9 +26922,7 @@ var NativeTools = class {
26702
26922
  }
26703
26923
  if (call.name === "command_run") {
26704
26924
  const cwd2 = await resolve(call.args.cwd, true), program = this.resolveProgram(call.args.command, workspace);
26705
- const common2 = await this.gitCommonDir(cwd2, workspace, guard);
26706
- const claims2 = writeClaim(workspace.root);
26707
- if (common2) claims2.push({ path: common2, namespace: "git", mode: "write" });
26925
+ const claims2 = writeClaim(cwd2);
26708
26926
  return { call, claims: claims2, execution: { executable: program.executable, args: [...program.prefixArgs ?? [], ...call.args.args], cwd: cwd2 }, run: async (signal, onStarted, onOutput) => {
26709
26927
  const r = await runSupervised(this.options.helperPath, { executable: program.executable, args: [...program.prefixArgs ?? [], ...call.args.args], cwd: cwd2, timeoutMs: call.args.timeoutMs, maxProcesses: 32 }, { signal, maxOutputBytes: 9e4, onStarted, onOutput });
26710
26928
  const { pid: _pid, ...output2 } = r;
@@ -26720,9 +26938,9 @@ var NativeTools = class {
26720
26938
  else if (call.name === "git_diff") {
26721
26939
  argv = ["diff", "--no-ext-diff", "--no-textconv", ...call.args.staged ? ["--cached"] : []];
26722
26940
  if (call.args.file) {
26723
- const file2 = await resolve(path7.resolve(cwd, call.args.file));
26724
- const relative = path7.relative(cwd, file2);
26725
- if (relative.startsWith(".." + path7.sep) || relative === ".." || path7.isAbsolute(relative)) fail2("PATH_NOT_ALLOWED");
26941
+ const file2 = await resolve(path9.resolve(cwd, call.args.file));
26942
+ const relative = path9.relative(cwd, file2);
26943
+ if (relative.startsWith(".." + path9.sep) || relative === ".." || path9.isAbsolute(relative)) fail2("PATH_NOT_ALLOWED");
26726
26944
  argv.push("--", relative);
26727
26945
  } else argv.push("--stat");
26728
26946
  } else fail2("TOOL_MISSING");
@@ -26733,9 +26951,9 @@ var NativeTools = class {
26733
26951
  const listing = await this.list(guard, cwd, 1, 150, signal);
26734
26952
  let packageInfo = null;
26735
26953
  try {
26736
- const name = await guard.resolveExisting(path7.join(cwd, "package.json"));
26737
- guard.assertSafeFile(name);
26738
- const value = JSON.parse(utf8(await this.readFile(name, 64e3, signal)));
26954
+ const name2 = await guard.resolveExisting(path9.join(cwd, "package.json"));
26955
+ guard.assertSafeFile(name2);
26956
+ const value = JSON.parse(utf8(await this.readFile(name2, 64e3, signal)));
26739
26957
  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) : [] };
26740
26958
  } catch (error62) {
26741
26959
  if (error62 instanceof NativeToolError && ["FILE_READ_FAILED", "CANCELLED"].includes(error62.code)) throw error62;
@@ -26749,14 +26967,14 @@ var NativeTools = class {
26749
26967
  return { ...output2, resultCode: r.exitCode === 0 ? "SUCCESS" : "GIT_FAILED" };
26750
26968
  } };
26751
26969
  }
26752
- resolveProgram(name, workspace) {
26753
- const entry = Object.entries(this.options.programs).find(([key, value]) => key.toLowerCase() === name.toLowerCase() || path7.isAbsolute(name) && equalPath2(value.executable, path7.resolve(name)));
26754
- if (!entry || !workspace.allowedCommands.some((v) => v.toLowerCase() === entry[0].toLowerCase()) || !path7.isAbsolute(entry[1].executable)) fail2("COMMAND_NOT_ALLOWED");
26970
+ resolveProgram(name2, workspace) {
26971
+ const entry = Object.entries(this.options.programs).find(([key, value]) => key.toLowerCase() === name2.toLowerCase() || path9.isAbsolute(name2) && equalPath3(value.executable, path9.resolve(name2)));
26972
+ if (!entry || !workspace.allowedCommands.some((v) => v.toLowerCase() === entry[0].toLowerCase()) || !path9.isAbsolute(entry[1].executable)) fail2("COMMAND_NOT_ALLOWED");
26755
26973
  return { executable: entry[1].executable, prefixArgs: [...entry[1].prefixArgs ?? []] };
26756
26974
  }
26757
26975
  gitExecution(cwd, args) {
26758
26976
  const program = this.options.programs.git;
26759
- if (!program || !path7.isAbsolute(program.executable)) fail2("GIT_NOT_INSTALLED");
26977
+ if (!program || !path9.isAbsolute(program.executable)) fail2("GIT_NOT_INSTALLED");
26760
26978
  return { executable: program.executable, args: ["--no-pager", "--no-optional-locks", "-c", "core.fsmonitor=false", "-c", "core.hooksPath=" + (process.platform === "win32" ? "NUL" : "/dev/null"), "-c", "diff.external=", ...args], cwd };
26761
26979
  }
26762
26980
  async list(guard, root, depth, maxEntries, signal) {
@@ -26774,7 +26992,7 @@ var NativeTools = class {
26774
26992
  break;
26775
26993
  }
26776
26994
  if (item.isSymbolicLink() || excluded.has(item.name.toLowerCase())) continue;
26777
- const candidate = path7.join(current2.path, item.name);
26995
+ const candidate = path9.join(current2.path, item.name);
26778
26996
  let resolved;
26779
26997
  try {
26780
26998
  resolved = await guard.resolveExisting(candidate);
@@ -26782,13 +27000,13 @@ var NativeTools = class {
26782
27000
  } catch {
26783
27001
  continue;
26784
27002
  }
26785
- if (!equalPath2(candidate, resolved)) continue;
27003
+ if (!equalPath3(candidate, resolved)) continue;
26786
27004
  if (item.isDirectory()) {
26787
- entries.push({ path: path7.relative(root, resolved), type: "directory" });
27005
+ entries.push({ path: path9.relative(root, resolved), type: "directory" });
26788
27006
  if (current2.level < depth) queue.push({ path: resolved, level: current2.level + 1 });
26789
27007
  } else if (item.isFile()) {
26790
- const stat = await lstat4(resolved);
26791
- entries.push({ path: path7.relative(root, resolved), type: "file", size: stat.size });
27008
+ const stat = await lstat5(resolved);
27009
+ entries.push({ path: path9.relative(root, resolved), type: "file", size: stat.size });
26792
27010
  }
26793
27011
  }
26794
27012
  if (truncated) break;
@@ -26798,49 +27016,49 @@ var NativeTools = class {
26798
27016
  async gitCommonDir(cwd, workspace, guard) {
26799
27017
  let directory = cwd;
26800
27018
  while (guard.isWithin(directory, workspace.root)) {
26801
- const dotGit = path7.join(directory, ".git");
27019
+ const dotGit = path9.join(directory, ".git");
26802
27020
  try {
26803
- const stat = await lstat4(dotGit);
27021
+ const stat = await lstat5(dotGit);
26804
27022
  if (stat.isSymbolicLink()) fail2("GIT_METADATA_CHANGED");
26805
27023
  let gitDir;
26806
- if (stat.isDirectory()) gitDir = await realpath4(dotGit);
27024
+ if (stat.isDirectory()) gitDir = await realpath5(dotGit);
26807
27025
  else {
26808
27026
  const content = utf8(await this.readFile(dotGit, 4096)).trim();
26809
27027
  if (!content.startsWith("gitdir: ")) fail2("GIT_METADATA_CHANGED");
26810
- gitDir = await realpath4(path7.resolve(directory, content.slice(8)));
27028
+ gitDir = await realpath5(path9.resolve(directory, content.slice(8)));
26811
27029
  }
26812
27030
  if (guard.isWithin(gitDir, this.options.stateDirectory) || !guard.isWithin(gitDir, workspace.root) && (!workspace.gitCommonDir || !guard.isWithin(gitDir, workspace.gitCommonDir))) fail2("GIT_COMMON_DIRECTORY_NOT_APPROVED");
26813
27031
  let common = gitDir;
26814
27032
  try {
26815
- const content = utf8(await this.readFile(path7.join(gitDir, "commondir"), 4096)).trim();
27033
+ const content = utf8(await this.readFile(path9.join(gitDir, "commondir"), 4096)).trim();
26816
27034
  if (!content) fail2("GIT_METADATA_CHANGED");
26817
- common = await realpath4(path7.resolve(gitDir, content));
27035
+ common = await realpath5(path9.resolve(gitDir, content));
26818
27036
  } catch (e) {
26819
27037
  if (e.code !== "ENOENT") throw e;
26820
27038
  }
26821
- if (!(await lstat4(common)).isDirectory() || guard.isWithin(common, this.options.stateDirectory)) fail2("GIT_METADATA_CHANGED");
26822
- if (!guard.isWithin(common, workspace.root) && (!workspace.gitCommonDir || !equalPath2(common, workspace.gitCommonDir))) fail2("GIT_COMMON_DIRECTORY_NOT_APPROVED");
27039
+ if (!(await lstat5(common)).isDirectory() || guard.isWithin(common, this.options.stateDirectory)) fail2("GIT_METADATA_CHANGED");
27040
+ if (!guard.isWithin(common, workspace.root) && (!workspace.gitCommonDir || !equalPath3(common, workspace.gitCommonDir))) fail2("GIT_COMMON_DIRECTORY_NOT_APPROVED");
26823
27041
  return common;
26824
27042
  } catch (e) {
26825
27043
  if (e.code !== "ENOENT") throw e;
26826
27044
  }
26827
- if (equalPath2(directory, workspace.root)) break;
26828
- directory = path7.dirname(directory);
27045
+ if (equalPath3(directory, workspace.root)) break;
27046
+ directory = path9.dirname(directory);
26829
27047
  }
26830
27048
  return null;
26831
27049
  }
26832
27050
  };
26833
27051
 
26834
27052
  // agent/src/scheduler.ts
26835
- import path8 from "node:path";
27053
+ import path10 from "node:path";
26836
27054
  import os2 from "node:os";
26837
27055
  function canonical(value) {
26838
- const p = path8.resolve(value);
27056
+ const p = path10.resolve(value);
26839
27057
  return process.platform === "win32" ? p.toLowerCase() : p;
26840
27058
  }
26841
27059
  function ancestor(a, b) {
26842
- const relative = path8.relative(a, b);
26843
- return relative === "" || !path8.isAbsolute(relative) && relative !== ".." && !relative.startsWith(".." + path8.sep);
27060
+ const relative = path10.relative(a, b);
27061
+ return relative === "" || !path10.isAbsolute(relative) && relative !== ".." && !relative.startsWith(".." + path10.sep);
26844
27062
  }
26845
27063
  function claimsConflict(a, b) {
26846
27064
  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))));
@@ -26860,7 +27078,7 @@ var NativeScheduler = class {
26860
27078
  schedule(id, claims, deadlineAt, run, signal) {
26861
27079
  if (!this.accepting) return Promise.reject(Error("AGENT_PAUSED"));
26862
27080
  if (!id || id.length > 100 || this.active.has(id) || this.waiting.some((j) => j.id === id)) return Promise.reject(Error("DUPLICATE_SCHEDULED_EXECUTION"));
26863
- if (!Array.isArray(claims) || !claims.length || claims.length > 32 || claims.some((c) => !c || !path8.isAbsolute(c.path) || !["read", "write"].includes(c.mode))) return Promise.reject(Error("INVALID_RESOURCE_CLAIM"));
27081
+ if (!Array.isArray(claims) || !claims.length || claims.length > 32 || claims.some((c) => !c || !path10.isAbsolute(c.path) || !["read", "write"].includes(c.mode))) return Promise.reject(Error("INVALID_RESOURCE_CLAIM"));
26864
27082
  const deadline = deadlineAt.getTime();
26865
27083
  if (!Number.isFinite(deadline) || deadline <= Date.now()) return Promise.reject(Error("ADMISSION_DEADLINE_EXPIRED"));
26866
27084
  if (signal?.aborted) return Promise.reject(Error("CANCELLED_BEFORE_ACCEPTANCE"));
@@ -27320,17 +27538,17 @@ function unshapedResultTelemetry(result2) {
27320
27538
 
27321
27539
  // packages/optimization/src/live-telemetry.ts
27322
27540
  var LIVE_EFFICIENCY_EVENT_VERSION = 1;
27323
- var uuid14 = external_exports.string().uuid().toLowerCase();
27541
+ var uuid15 = external_exports.string().uuid().toLowerCase();
27324
27542
  var bytes2 = external_exports.number().int().min(0).max(1e9);
27325
27543
  var utc4 = external_exports.iso.datetime({ offset: false });
27326
27544
  var LiveEfficiencyEventSchema = external_exports.object({
27327
27545
  version: external_exports.literal(LIVE_EFFICIENCY_EVENT_VERSION),
27328
27546
  occurredAt: utc4,
27329
- tenantId: uuid14,
27330
- accountId: uuid14.nullable(),
27331
- sessionId: uuid14,
27332
- operationId: uuid14,
27333
- executionId: uuid14,
27547
+ tenantId: uuid15,
27548
+ accountId: uuid15.nullable(),
27549
+ sessionId: uuid15,
27550
+ operationId: uuid15,
27551
+ executionId: uuid15,
27334
27552
  toolName: external_exports.string().trim().min(1).max(120),
27335
27553
  outcome: external_exports.enum(["success", "failed", "timed_out", "cancelled", "unknown"]),
27336
27554
  parserId: external_exports.string().trim().min(1).max(120).nullable(),
@@ -27729,6 +27947,11 @@ var controlPayload = external_exports.object({ binding: ExecutionBindingSchema }
27729
27947
  function failure3(code) {
27730
27948
  return Object.assign(new Error(code), { code });
27731
27949
  }
27950
+ var MAX_METRIC_BYTES = 4194304;
27951
+ function terminalMetrics(result2) {
27952
+ if (!result2) return void 0;
27953
+ return { stdoutBytes: Math.min(Buffer.byteLength(result2.stdout, "utf8"), MAX_METRIC_BYTES), stderrBytes: Math.min(Buffer.byteLength(result2.stderr, "utf8"), MAX_METRIC_BYTES), outputTruncated: result2.stdoutTruncated || result2.stderrTruncated };
27954
+ }
27732
27955
  var NativeRelayBridge = class {
27733
27956
  constructor(runtime, sendTerminal, journal) {
27734
27957
  this.runtime = runtime;
@@ -27764,7 +27987,7 @@ var NativeRelayBridge = class {
27764
27987
  try {
27765
27988
  const binding2 = { tenantId: event.tenantId, deviceId: event.deviceId, grantId: event.grantId, sessionId: event.sessionId, operationId: event.operationId, executionId: id, connectionEpoch: event.connectionEpoch, workspaceGrantId: event.workspaceGrantId, policyVersion: event.policyVersion, payloadHash: event.payloadHash, deadlineAt: event.deadlineAt, ...event.accountId ? { accountId: event.accountId } : {} };
27766
27989
  if (!["finished", "failed", "cancelled", "unknown"].includes(event.state)) continue;
27767
- await this.sendTerminal(binding2, event.state, event.resultCode);
27990
+ await this.sendTerminal(binding2, event.state, event.resultCode, terminalMetrics(event.result));
27768
27991
  await this.journal.markReported(id, event.resultCode);
27769
27992
  } catch {
27770
27993
  } finally {
@@ -27812,10 +28035,10 @@ var NativeRelayBridge = class {
27812
28035
  const { binding: binding2, tool } = parsed2.data;
27813
28036
  this.binding(request, binding2);
27814
28037
  const prepared = await this.wait(this.execution, binding2.executionId, request, () => this.runtime.receive({ type: "prepare", version: 1, binding: binding2, tool }));
27815
- if (prepared.type === "not_accepted") return { accepted: false, provedNotStarted: prepared.provedNotStarted };
28038
+ if (prepared.type === "not_accepted") return { accepted: false, provedNotStarted: prepared.provedNotStarted, code: prepared.code };
27816
28039
  if (prepared.type !== "prepared") throw failure3("INFRA_UNAVAILABLE");
27817
28040
  const accepted = await this.wait(this.execution, binding2.executionId, request, () => this.runtime.receive({ type: "execute", version: 1, binding: binding2 }));
27818
- if (accepted.type === "not_accepted") return { accepted: false, provedNotStarted: accepted.provedNotStarted };
28041
+ if (accepted.type === "not_accepted") return { accepted: false, provedNotStarted: accepted.provedNotStarted, code: accepted.code };
27819
28042
  if (accepted.type !== "accepted") throw failure3("INFRA_UNAVAILABLE");
27820
28043
  return { accepted: true };
27821
28044
  }
@@ -27878,7 +28101,7 @@ function relayUrlFromEnrollment(enrollment) {
27878
28101
  url2.pathname = "/api/agent/relay";
27879
28102
  return url2.toString();
27880
28103
  }
27881
- function uuid15(value, code) {
28104
+ function uuid16(value, code) {
27882
28105
  if (typeof value !== "string" || !UUID2.test(value)) fail3(code);
27883
28106
  return value.toLowerCase();
27884
28107
  }
@@ -28008,37 +28231,38 @@ function sendJson(socket, value, maxBytes) {
28008
28231
  function validateChallenge(frame, expectedProtocol) {
28009
28232
  if (frame.type !== "challenge") fail3("RELAY_HANDSHAKE_INVALID");
28010
28233
  protocol(frame.protocolVersion, expectedProtocol);
28011
- uuid15(frame.gatewayId, "RELAY_HANDSHAKE_INVALID");
28234
+ uuid16(frame.gatewayId, "RELAY_HANDSHAKE_INVALID");
28012
28235
  if (typeof frame.nonce !== "string" || frame.nonce.length < 32 || frame.nonce.length > 512 || /[\u0000-\u001f\u007f]/u.test(frame.nonce)) fail3("RELAY_HANDSHAKE_INVALID");
28013
28236
  if (typeof frame.expiresAt !== "string" || !Number.isFinite(Date.parse(frame.expiresAt)) || Date.parse(frame.expiresAt) <= Date.now()) fail3("RELAY_HANDSHAKE_INVALID");
28014
28237
  return {
28015
- challengeId: uuid15(frame.challengeId, "RELAY_HANDSHAKE_INVALID"),
28238
+ challengeId: uuid16(frame.challengeId, "RELAY_HANDSHAKE_INVALID"),
28016
28239
  nonce: frame.nonce
28017
28240
  };
28018
28241
  }
28019
28242
  function validateReady(frame, enrollment, expectedProtocol) {
28020
28243
  if (frame.type !== "connected") fail3("RELAY_HANDSHAKE_INVALID");
28021
28244
  protocol(frame.protocolVersion, expectedProtocol);
28022
- if (uuid15(frame.tenantId, "RELAY_HANDSHAKE_INVALID") !== enrollment.tenantId.toLowerCase()) fail3("RELAY_ID_MISMATCH");
28023
- if (uuid15(frame.deviceId, "RELAY_HANDSHAKE_INVALID") !== enrollment.deviceId.toLowerCase()) fail3("RELAY_ID_MISMATCH");
28024
- return epoch2(frame.connectionEpoch);
28245
+ if (uuid16(frame.tenantId, "RELAY_HANDSHAKE_INVALID") !== enrollment.tenantId.toLowerCase()) fail3("RELAY_ID_MISMATCH");
28246
+ if (uuid16(frame.deviceId, "RELAY_HANDSHAKE_INVALID") !== enrollment.deviceId.toLowerCase()) fail3("RELAY_ID_MISMATCH");
28247
+ const terminalMetrics2 = Array.isArray(frame.capabilities) && frame.capabilities.includes(TERMINAL_METRICS_CAPABILITY);
28248
+ return { connectionEpoch: epoch2(frame.connectionEpoch), terminalMetrics: terminalMetrics2 };
28025
28249
  }
28026
28250
  function validateRequest(frame, enrollment, expectedProtocol, connectionEpoch) {
28027
28251
  if (frame.type !== "relayFrame") fail3("RELAY_REQUEST_INVALID");
28028
28252
  protocol(frame.protocolVersion, expectedProtocol);
28029
- const tenantId = uuid15(frame.tenantId, "RELAY_REQUEST_INVALID");
28030
- const deviceId = uuid15(frame.deviceId, "RELAY_REQUEST_INVALID");
28253
+ const tenantId = uuid16(frame.tenantId, "RELAY_REQUEST_INVALID");
28254
+ const deviceId = uuid16(frame.deviceId, "RELAY_REQUEST_INVALID");
28031
28255
  if (tenantId !== enrollment.tenantId.toLowerCase() || deviceId !== enrollment.deviceId.toLowerCase()) fail3("RELAY_ID_MISMATCH");
28032
28256
  if (epoch2(frame.connectionEpoch) !== connectionEpoch) fail3("RELAY_EPOCH_MISMATCH");
28033
28257
  const kind = frame.kind;
28034
28258
  if (typeof kind !== "string" || !REQUEST_KINDS.has(kind)) fail3("RELAY_REQUEST_INVALID");
28035
28259
  return {
28036
- requestId: uuid15(frame.requestId, "RELAY_REQUEST_INVALID"),
28260
+ requestId: uuid16(frame.requestId, "RELAY_REQUEST_INVALID"),
28037
28261
  tenantId,
28038
28262
  deviceId,
28039
28263
  connectionEpoch,
28040
- operationId: uuid15(frame.operationId, "RELAY_REQUEST_INVALID"),
28041
- executionId: uuid15(frame.executionId, "RELAY_REQUEST_INVALID"),
28264
+ operationId: uuid16(frame.operationId, "RELAY_REQUEST_INVALID"),
28265
+ executionId: uuid16(frame.executionId, "RELAY_REQUEST_INVALID"),
28042
28266
  kind,
28043
28267
  payload: frame.payload,
28044
28268
  deadlineAt: isoDate(frame.deadlineAt)
@@ -28078,8 +28302,8 @@ async function connectOnce(options) {
28078
28302
  const identity = await options.store.load();
28079
28303
  if (!identity || !identity.enrollment) fail3("ENROLLMENT_MISSING");
28080
28304
  const enrollment = identity.enrollment;
28081
- const tenantId = uuid15(enrollment.tenantId, "ENROLLMENT_INVALID");
28082
- const deviceId = uuid15(enrollment.deviceId, "ENROLLMENT_INVALID");
28305
+ const tenantId = uuid16(enrollment.tenantId, "ENROLLMENT_INVALID");
28306
+ const deviceId = uuid16(enrollment.deviceId, "ENROLLMENT_INVALID");
28083
28307
  const url2 = relayUrlFromEnrollment(enrollment);
28084
28308
  const socket = new wrapper_default(url2, [], {
28085
28309
  followRedirects: false,
@@ -28114,7 +28338,7 @@ async function connectOnce(options) {
28114
28338
  nonce: challenge.nonce,
28115
28339
  signature
28116
28340
  }, maxFrameBytes);
28117
- const connectionEpoch = validateReady(await waitForMessage(socket, maxFrameBytes, connectTimeoutMs, "RELAY_HANDSHAKE_TIMEOUT"), enrollment, protocolVersion2);
28341
+ const { connectionEpoch, terminalMetrics: terminalMetrics2 } = validateReady(await waitForMessage(socket, maxFrameBytes, connectTimeoutMs, "RELAY_HANDSHAKE_TIMEOUT"), enrollment, protocolVersion2);
28118
28342
  socket.off("message", bufferDuringReady);
28119
28343
  if (handshakeOverflow) fail3("RELAY_FRAME_TOO_LARGE");
28120
28344
  handshakeBuffer.shift();
@@ -28199,10 +28423,10 @@ async function connectOnce(options) {
28199
28423
  heartbeat: () => {
28200
28424
  if (socket.readyState !== wrapper_default.OPEN) fail3("RELAY_SOCKET_CLOSED");
28201
28425
  },
28202
- sendTerminal: (binding2, state, resultCode) => {
28426
+ sendTerminal: (binding2, state, resultCode, metrics) => {
28203
28427
  if (pendingTerminal.size >= 64) return Promise.reject(new RelayClientError("RELAY_PENDING_LIMIT"));
28204
28428
  const requestId = randomUUID5();
28205
- const event = { type: "executionResult", protocolVersion: 1, requestId, tenantId, deviceId, connectionEpoch, binding: binding2, state, resultCode };
28429
+ const event = { type: "executionResult", protocolVersion: 1, requestId, tenantId, deviceId, connectionEpoch, binding: binding2, state, resultCode, ...terminalMetrics2 && metrics ? { metrics } : {} };
28206
28430
  return new Promise((resolve, reject) => {
28207
28431
  const timer = setTimeout(() => {
28208
28432
  pendingTerminal.delete(requestId);
@@ -28299,10 +28523,10 @@ function canonicalOrigin2(value) {
28299
28523
  fail4("ORIGIN_INVALID");
28300
28524
  }
28301
28525
  }
28302
- function endpoint(origin, path11) {
28303
- return origin + path11;
28526
+ function endpoint(origin, path13) {
28527
+ return origin + path13;
28304
28528
  }
28305
- function uuid16(value, code) {
28529
+ function uuid17(value, code) {
28306
28530
  if (typeof value !== "string" || !UUID3.test(value)) fail4(code);
28307
28531
  return value.toLowerCase();
28308
28532
  }
@@ -28422,7 +28646,7 @@ var PairingClient = class {
28422
28646
  publicKey: identity.publicKeyPem,
28423
28647
  agentVersion: this.version
28424
28648
  }));
28425
- const pairingId = uuid16(response.pairingId, "PAIRING_RESPONSE_INVALID");
28649
+ const pairingId = uuid17(response.pairingId, "PAIRING_RESPONSE_INVALID");
28426
28650
  const expiresAt = parseDate(response.expiresAt, "PAIRING_RESPONSE_INVALID");
28427
28651
  const now = this.nowMs();
28428
28652
  if (expiresAt.getTime() <= now || expiresAt.getTime() - now > 30 * 6e4) fail4("PAIRING_RESPONSE_INVALID");
@@ -28456,9 +28680,9 @@ var PairingClient = class {
28456
28680
  }
28457
28681
  async completeOnce(beginResult, approved, displayNameValue) {
28458
28682
  const pairing = this.validateBeginResult(beginResult);
28459
- const tenantId = uuid16(approved.tenantId, "PAIRING_RESPONSE_INVALID");
28683
+ const tenantId = uuid17(approved.tenantId, "PAIRING_RESPONSE_INVALID");
28460
28684
  const email3 = accountEmail(approved.accountEmail);
28461
- const name = displayName(displayNameValue);
28685
+ const name2 = displayName(displayNameValue);
28462
28686
  const identity = await this.currentIdentity();
28463
28687
  const keyFingerprint = fingerprint2(identity.fingerprint);
28464
28688
  if (keyFingerprint !== pairing.keyFingerprint) fail4("IDENTITY_CHANGED");
@@ -28467,18 +28691,18 @@ var PairingClient = class {
28467
28691
  const response = assertJsonObject(await this.request(endpoint(this.origin, "/api/agent/pairings/" + pairing.pairingId + "/complete"), {
28468
28692
  pairingSecret: pairing.pairingSecret,
28469
28693
  signature,
28470
- displayName: name,
28694
+ displayName: name2,
28471
28695
  agentVersion: this.version
28472
28696
  }));
28473
- const completedTenant = uuid16(response.tenantId, "PAIRING_RESPONSE_INVALID");
28697
+ const completedTenant = uuid17(response.tenantId, "PAIRING_RESPONSE_INVALID");
28474
28698
  if (completedTenant !== tenantId) fail4("PAIRING_RESPONSE_INVALID");
28475
- const deviceId = uuid16(response.deviceId, "PAIRING_RESPONSE_INVALID");
28699
+ const deviceId = uuid17(response.deviceId, "PAIRING_RESPONSE_INVALID");
28476
28700
  const enrollment = {
28477
28701
  tenantId,
28478
28702
  deviceId,
28479
28703
  serverOrigin: this.origin,
28480
28704
  accountEmail: email3,
28481
- ...response.accountId !== void 0 ? { accountId: uuid16(response.accountId, "PAIRING_RESPONSE_INVALID") } : {}
28705
+ ...response.accountId !== void 0 ? { accountId: uuid17(response.accountId, "PAIRING_RESPONSE_INVALID") } : {}
28482
28706
  };
28483
28707
  await this.store.saveEnrollment(enrollment);
28484
28708
  return { ...enrollment };
@@ -28492,7 +28716,7 @@ var PairingClient = class {
28492
28716
  state: response.state,
28493
28717
  expiresAt: parseDate(response.expiresAt, "PAIRING_RESPONSE_INVALID")
28494
28718
  };
28495
- if (response.tenantId !== void 0) result2.tenantId = uuid16(response.tenantId, "PAIRING_RESPONSE_INVALID");
28719
+ if (response.tenantId !== void 0) result2.tenantId = uuid17(response.tenantId, "PAIRING_RESPONSE_INVALID");
28496
28720
  if (response.accountEmail !== void 0) result2.accountEmail = accountEmail(response.accountEmail);
28497
28721
  return result2;
28498
28722
  }
@@ -28504,10 +28728,10 @@ var PairingClient = class {
28504
28728
  }
28505
28729
  validateBeginResult(value) {
28506
28730
  return {
28507
- pairingId: uuid16(value.pairingId, "PAIRING_INVALID"),
28731
+ pairingId: uuid17(value.pairingId, "PAIRING_INVALID"),
28508
28732
  pairingSecret: pairingSecret(value.pairingSecret),
28509
28733
  confirmationCode: confirmationCode(value.confirmationCode),
28510
- approvalUrl: approvalUrl(value.approvalUrl, this.origin, uuid16(value.pairingId, "PAIRING_INVALID")),
28734
+ approvalUrl: approvalUrl(value.approvalUrl, this.origin, uuid17(value.pairingId, "PAIRING_INVALID")),
28511
28735
  expiresAt: value.expiresAt instanceof Date ? new Date(value.expiresAt.getTime()) : parseDate(value.expiresAt, "PAIRING_INVALID"),
28512
28736
  keyFingerprint: fingerprint2(value.keyFingerprint)
28513
28737
  };
@@ -28802,30 +29026,30 @@ async function deliverGuardEvidence(target, packet, options = {}) {
28802
29026
 
28803
29027
  // agent/src/optimization-ledger.ts
28804
29028
  import { constants as constants4 } from "node:fs";
28805
- import { lstat as lstat5, mkdir as mkdir4, open as open5, readFile as readFile4, realpath as realpath5 } from "node:fs/promises";
28806
- import path9 from "node:path";
29029
+ import { lstat as lstat6, mkdir as mkdir4, open as open5, readFile as readFile4, realpath as realpath6 } from "node:fs/promises";
29030
+ import path11 from "node:path";
28807
29031
  var MAX_LEDGER_BYTES = 64 * 1024 * 1024;
28808
29032
  var MAX_NOTICE_LEDGER_BYTES = 8 * 1024 * 1024;
28809
29033
  function failure4(code) {
28810
29034
  return Object.assign(new Error(code), { code });
28811
29035
  }
28812
29036
  async function safeDirectory2(directory) {
28813
- const absolute2 = path9.resolve(directory);
29037
+ const absolute2 = path11.resolve(directory);
28814
29038
  let current2 = absolute2;
28815
29039
  for (; ; ) {
28816
29040
  try {
28817
- if ((await lstat5(current2)).isSymbolicLink()) throw failure4("OPTIMIZATION_LEDGER_DIRECTORY_INVALID");
29041
+ if ((await lstat6(current2)).isSymbolicLink()) throw failure4("OPTIMIZATION_LEDGER_DIRECTORY_INVALID");
28818
29042
  } catch (error62) {
28819
29043
  if (error62.code !== "ENOENT") throw error62;
28820
29044
  }
28821
- const parent = path9.dirname(current2);
29045
+ const parent = path11.dirname(current2);
28822
29046
  if (parent === current2) break;
28823
29047
  current2 = parent;
28824
29048
  }
28825
29049
  await mkdir4(absolute2, { recursive: true, mode: 448 });
28826
- const stat = await lstat5(absolute2);
29050
+ const stat = await lstat6(absolute2);
28827
29051
  if (!stat.isDirectory() || stat.isSymbolicLink()) throw failure4("OPTIMIZATION_LEDGER_DIRECTORY_INVALID");
28828
- return realpath5(absolute2);
29052
+ return realpath6(absolute2);
28829
29053
  }
28830
29054
  var OptimizationLedger = class _OptimizationLedger {
28831
29055
  constructor(filename, handle, noticesFilename) {
@@ -28843,11 +29067,11 @@ var OptimizationLedger = class _OptimizationLedger {
28843
29067
  closed = false;
28844
29068
  static async open(directory) {
28845
29069
  const dir = await safeDirectory2(directory);
28846
- const filename = path9.join(dir, "live-efficiency.v1.jsonl");
28847
- const noticesFilename = path9.join(dir, "live-efficiency-notices.v1.jsonl");
29070
+ const filename = path11.join(dir, "live-efficiency.v1.jsonl");
29071
+ const noticesFilename = path11.join(dir, "live-efficiency-notices.v1.jsonl");
28848
29072
  let existing = "";
28849
29073
  try {
28850
- const stat = await lstat5(filename);
29074
+ const stat = await lstat6(filename);
28851
29075
  if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_LEDGER_BYTES) {
28852
29076
  throw failure4("OPTIMIZATION_LEDGER_INVALID");
28853
29077
  }
@@ -28863,7 +29087,7 @@ var OptimizationLedger = class _OptimizationLedger {
28863
29087
  const ledger = new _OptimizationLedger(filename, handle, noticesFilename);
28864
29088
  try {
28865
29089
  try {
28866
- const noticeStat = await lstat5(noticesFilename);
29090
+ const noticeStat = await lstat6(noticesFilename);
28867
29091
  if (!noticeStat.isFile() || noticeStat.isSymbolicLink() || noticeStat.size > MAX_NOTICE_LEDGER_BYTES) throw failure4("OPTIMIZATION_NOTICE_LEDGER_INVALID");
28868
29092
  const notices = await readFile4(noticesFilename, "utf8");
28869
29093
  for (const line of notices.split("\n")) {
@@ -28930,7 +29154,7 @@ var OptimizationLedger = class _OptimizationLedger {
28930
29154
  const marker = JSON.stringify({ sessionId: event.sessionId, checkpointCalls, deliveredAt: (/* @__PURE__ */ new Date()).toISOString() }) + "\n";
28931
29155
  let currentBytes = 0;
28932
29156
  try {
28933
- const stat = await lstat5(this.noticesFilename);
29157
+ const stat = await lstat6(this.noticesFilename);
28934
29158
  if (!stat.isFile() || stat.isSymbolicLink()) throw failure4("OPTIMIZATION_NOTICE_LEDGER_INVALID");
28935
29159
  currentBytes = stat.size;
28936
29160
  } catch (error62) {
@@ -28977,7 +29201,7 @@ var OptimizationLedger = class _OptimizationLedger {
28977
29201
  };
28978
29202
 
28979
29203
  // agent/src/main.ts
28980
- var AGENT_VERSION2 = true ? "0.3.3" : "0.3.2";
29204
+ var AGENT_VERSION2 = true ? "0.3.5" : "0.3.2";
28981
29205
  function processAlive(pid) {
28982
29206
  if (!Number.isInteger(pid) || pid <= 0) return false;
28983
29207
  try {
@@ -28989,7 +29213,7 @@ function processAlive(pid) {
28989
29213
  }
28990
29214
  async function claimAgentProcess(stateDir, runtimeDir, version2) {
28991
29215
  await mkdir5(stateDir, { recursive: true });
28992
- const file2 = path10.join(stateDir, "agent-process.json");
29216
+ const file2 = path12.join(stateDir, "agent-process.json");
28993
29217
  for (let attempt = 0; attempt < 2; attempt += 1) {
28994
29218
  try {
28995
29219
  const handle = await open6(file2, "wx", 384);
@@ -29045,9 +29269,9 @@ async function runAgent(options) {
29045
29269
  }
29046
29270
  const runtime = new NativeRuntime({ journal: options.journal, tools: options.tools, scheduler: new NativeScheduler(), workspaces: () => options.store.loadWorkspaces(Boolean(options.guard)), guard: options.guard, efficiencyLedger: options.efficiencyLedger });
29047
29271
  let connection = null;
29048
- const bridge = new NativeRelayBridge(runtime, (binding2, state, code) => {
29272
+ const bridge = new NativeRelayBridge(runtime, (binding2, state, code, metrics) => {
29049
29273
  if (!connection) throw Error("RELAY_SOCKET_CLOSED");
29050
- return connection.sendTerminal(binding2, state, code);
29274
+ return connection.sendTerminal(binding2, state, code, metrics);
29051
29275
  }, options.journal);
29052
29276
  const connect = options.connect ?? ((connectionOptions) => connectOnce(connectionOptions));
29053
29277
  try {
@@ -29100,10 +29324,10 @@ async function runAgent(options) {
29100
29324
  async function main() {
29101
29325
  if (process.platform !== "win32") throw Error("WINDOWS_REQUIRED");
29102
29326
  const appData = process.env.LOCALAPPDATA;
29103
- if (!appData || !path10.isAbsolute(appData)) throw Error("APP_DATA_MISSING");
29104
- const stateDir = process.env.LC_AGENT_STATE_DIR ?? path10.join(appData, "LocalCommander", "Agent");
29105
- const binaryDir = path10.dirname(process.execPath);
29106
- const ownerBridgePath = process.env.LC_OWNER_BRIDGE ?? path10.join(binaryDir, "OwnerBridge.exe");
29327
+ if (!appData || !path12.isAbsolute(appData)) throw Error("APP_DATA_MISSING");
29328
+ const stateDir = process.env.LC_AGENT_STATE_DIR ?? path12.join(appData, "LocalCommander", "Agent");
29329
+ const binaryDir = path12.dirname(process.execPath);
29330
+ const ownerBridgePath = process.env.LC_OWNER_BRIDGE ?? path12.join(binaryDir, "OwnerBridge.exe");
29107
29331
  const store = await WindowsPrivateStore.open(stateDir, ownerBridgePath);
29108
29332
  const command = process.argv[2] ?? "run";
29109
29333
  if (command === "pair") {
@@ -29125,18 +29349,33 @@ async function main() {
29125
29349
  }) + "\n");
29126
29350
  return;
29127
29351
  }
29352
+ if (command === "configure-access") {
29353
+ if (process.argv.length !== 3) throw Error("AGENT_COMMAND_INVALID");
29354
+ process.stdout.write(await store.configureAccess() ? "ACCESS_CONFIGURED\n" : "ACCESS_CANCELLED\n");
29355
+ return;
29356
+ }
29128
29357
  if (command === "approve-workspace") {
29129
29358
  process.stdout.write(await store.approveWorkspace() ? "WORKSPACE_APPROVED\n" : "WORKSPACE_CANCELLED\n");
29130
29359
  return;
29131
29360
  }
29132
29361
  if (command === "list-workspaces") {
29133
- process.stdout.write(JSON.stringify((await store.loadWorkspaces()).map((w) => ({ workspaceGrantId: w.workspaceGrantId, displayName: w.displayName, permissions: w.permissions, allowedCommands: w.allowedCommands, localhostPorts: w.localhostPorts }))) + "\n");
29362
+ const programs = await store.loadPrograms(), history = await store.loadPermissionHistory();
29363
+ process.stdout.write(JSON.stringify((await store.loadWorkspaces()).map((w) => ({
29364
+ workspaceGrantId: w.workspaceGrantId,
29365
+ displayName: w.displayName,
29366
+ path: w.root,
29367
+ permissions: w.permissions,
29368
+ allowedCommands: w.allowedCommands,
29369
+ executables: Object.fromEntries(w.allowedCommands.map((name2) => [name2, programs[name2]?.executable ?? null])),
29370
+ localhostPorts: w.localhostPorts,
29371
+ permissionHistory: history.filter((entry) => entry.workspaceGrantId === w.workspaceGrantId)
29372
+ }))) + "\n");
29134
29373
  return;
29135
29374
  }
29136
29375
  const args = process.argv.slice(3);
29137
29376
  if (command === "efficiency-report") {
29138
29377
  if (args.length) throw Error("AGENT_COMMAND_INVALID");
29139
- const ledger = await OptimizationLedger.open(path10.join(stateDir, "optimization"));
29378
+ const ledger = await OptimizationLedger.open(path12.join(stateDir, "optimization"));
29140
29379
  try {
29141
29380
  process.stdout.write(JSON.stringify(await ledger.report(), null, 2) + "\n");
29142
29381
  } finally {
@@ -29146,7 +29385,7 @@ async function main() {
29146
29385
  }
29147
29386
  if (command === "guard-configure") {
29148
29387
  if (args.length !== 1) throw Error("AGENT_COMMAND_INVALID");
29149
- const filename = await (await import("node:fs/promises")).realpath(path10.resolve(args[0]));
29388
+ const filename = await (await import("node:fs/promises")).realpath(path12.resolve(args[0]));
29150
29389
  const input2 = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readWindowsFile(ownerBridgePath, filename, 2e5)));
29151
29390
  if (!input2 || typeof input2 !== "object" || Object.keys(input2).sort().join(",") !== "compact,settings") throw Error("GUARD_CONFIGURATION_INVALID");
29152
29391
  await store.configureGuard(input2.settings, input2.compact);
@@ -29165,7 +29404,7 @@ async function main() {
29165
29404
  }
29166
29405
  if (command === "guard-evidence") {
29167
29406
  if (args.length) throw Error("AGENT_COMMAND_INVALID");
29168
- const journal = await NativeJournal.open(path10.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
29407
+ const journal = await NativeJournal.open(path12.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
29169
29408
  try {
29170
29409
  process.stdout.write(JSON.stringify(await journal.guardEvidence()) + "\n");
29171
29410
  } finally {
@@ -29177,7 +29416,7 @@ async function main() {
29177
29416
  if (args.length !== (command === "guard-export" ? 0 : 1)) throw Error("AGENT_COMMAND_INVALID");
29178
29417
  const identity = await store.load();
29179
29418
  if (!identity?.enrollment) throw Error("ENROLLMENT_MISSING");
29180
- const journal = await NativeJournal.open(path10.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
29419
+ const journal = await NativeJournal.open(path12.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
29181
29420
  try {
29182
29421
  const { tenantId, deviceId } = identity.enrollment;
29183
29422
  const records = (await journal.guardEvidence()).filter((record2) => record2.tenantId === tenantId && record2.deviceId === deviceId);
@@ -29216,10 +29455,10 @@ async function main() {
29216
29455
  if (!(await store.load())?.enrollment) throw Error("ENROLLMENT_MISSING");
29217
29456
  const releaseProcess = await claimAgentProcess(stateDir, binaryDir, AGENT_VERSION2);
29218
29457
  try {
29219
- const journal = await NativeJournal.open(path10.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
29220
- const efficiencyLedger = await OptimizationLedger.open(path10.join(stateDir, "optimization"));
29458
+ const journal = await NativeJournal.open(path12.join(stateDir, "journal"), new SecretBox({ "1": await store.loadDataKey() }));
29459
+ const efficiencyLedger = await OptimizationLedger.open(path12.join(stateDir, "optimization"));
29221
29460
  try {
29222
- const tools = new NativeTools({ stateDirectory: stateDir, helperPath: process.env.LC_JOB_HOST ?? path10.join(binaryDir, "JobHost.exe"), ownerBridgePath, programs: await store.loadPrograms() });
29461
+ const tools = new NativeTools({ stateDirectory: stateDir, helperPath: process.env.LC_JOB_HOST ?? path12.join(binaryDir, "JobHost.exe"), ownerBridgePath, programs: await store.loadPrograms() });
29223
29462
  const stop = new AbortController();
29224
29463
  process.once("SIGINT", () => stop.abort());
29225
29464
  process.once("SIGTERM", () => stop.abort());
@@ -29233,7 +29472,7 @@ async function main() {
29233
29472
  await releaseProcess();
29234
29473
  }
29235
29474
  }
29236
- if (process.argv[1] && path10.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
29475
+ if (process.argv[1] && path12.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
29237
29476
  void main().catch((error62) => {
29238
29477
  const code = error62 instanceof Error && /^[A-Z0-9_]{1,64}$/.test(error62.message) ? error62.message : "AGENT_START_FAILED";
29239
29478
  process.stderr.write(code + "\n");