@corenel/cli 0.9.5 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.js +1243 -320
  2. package/package.json +7 -7
package/dist/main.js CHANGED
@@ -52,7 +52,7 @@ function diskFullError(shownPath, e) {
52
52
  if (!code3 || !DISK_FULL_CODES.has(code3)) return null;
53
53
  return Object.assign(new Error(`Disk full: could not write ${shownPath}`), { code: code3, cause: e });
54
54
  }
55
- async function resolveTarget(abs, shown) {
55
+ async function resolveTarget(abs, shown2) {
56
56
  let target;
57
57
  try {
58
58
  target = await fs.realpath(abs);
@@ -62,7 +62,7 @@ async function resolveTarget(abs, shown) {
62
62
  if (codeOf(le) === "ENOENT") return null;
63
63
  throw le;
64
64
  });
65
- if (link?.isSymbolicLink()) throw new Error(`refusing to write through a dangling symlink: ${shown}`);
65
+ if (link?.isSymbolicLink()) throw new Error(`refusing to write through a dangling symlink: ${shown2}`);
66
66
  return { target: abs, st: null };
67
67
  }
68
68
  try {
@@ -85,9 +85,9 @@ async function renameWithRetry(from, to) {
85
85
  }
86
86
  }
87
87
  async function writeFileAtomic(abs, data, opts = {}) {
88
- const shown = opts.shownPath ?? abs;
89
- const fail = (e) => diskFullError(shown, e) ?? (e instanceof Error ? e : new Error(String(e)));
90
- const { target, st } = await resolveTarget(abs, shown);
88
+ const shown2 = opts.shownPath ?? abs;
89
+ const fail = (e) => diskFullError(shown2, e) ?? (e instanceof Error ? e : new Error(String(e)));
90
+ const { target, st } = await resolveTarget(abs, shown2);
91
91
  if (st && !st.isFile()) {
92
92
  try {
93
93
  await fs.writeFile(target, data);
@@ -178,8 +178,8 @@ function touchesGitDir(rel, platformSep = sep) {
178
178
  return seg === ".git";
179
179
  });
180
180
  }
181
- async function assertNotGitDir(root, abs, shown) {
182
- const refuse = () => new Error(`refusing to write inside a .git directory: ${shown}`);
181
+ async function assertNotGitDir(root, abs, shown2) {
182
+ const refuse = () => new Error(`refusing to write inside a .git directory: ${shown2}`);
183
183
  if (touchesGitDir(relative(root, abs))) throw refuse();
184
184
  let realRoot;
185
185
  try {
@@ -240,6 +240,11 @@ var init_fileService = __esm({
240
240
  /** An OUTER bound: the approved root this folder sits inside (a project
241
241
  * inside an operator's --root). See the constructor. */
242
242
  confineTo;
243
+ /** The absolute folder this service is rooted at (read-only), so a host can
244
+ * tell which folder a definition was loaded from. */
245
+ get rootDir() {
246
+ return this.root;
247
+ }
243
248
  /** `confineTo`: when `root` is a folder INSIDE an approved root, name that
244
249
  * approved root here. Every per-operation symlink check recomputes
245
250
  * realpath(root), so without it, swapping `root` itself for a link after
@@ -361,6 +366,10 @@ var init_fileService = __esm({
361
366
  async read(path) {
362
367
  return fs2.readFile(await this.realAbs(path), "utf8");
363
368
  }
369
+ /** Raw bytes, confined exactly as `read` is (lexical bound + symlink check). */
370
+ async readBytes(path) {
371
+ return new Uint8Array(await fs2.readFile(await this.realAbs(path)));
372
+ }
364
373
  async stat(path) {
365
374
  let a;
366
375
  try {
@@ -594,10 +603,10 @@ async function writeLoginCredential(token, opts = {}) {
594
603
  }
595
604
  }
596
605
  async function publishSignIn(credPath, tokPath, cred, notify) {
597
- const record = { ...await readForeignAuthSections(credPath, notify), ...cred };
606
+ const record2 = { ...await readForeignAuthSections(credPath, notify), ...cred };
598
607
  const credTmp = `${credPath}.tmp-${process.pid.toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
599
608
  const tokTmp = `${tokPath}.tmp-${process.pid.toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
600
- await fs3.writeFile(credTmp, `${JSON.stringify(record, null, 2)}
609
+ await fs3.writeFile(credTmp, `${JSON.stringify(record2, null, 2)}
601
610
  `, { mode: 384 });
602
611
  await fs3.writeFile(tokTmp, `${cred.accessToken}
603
612
  `, { mode: 384 });
@@ -727,9 +736,9 @@ async function resolveNodeCredential(opts = {}) {
727
736
  const fileToken = tokenRead.value;
728
737
  const unreadable = credRead.unreadable || tokenRead.unreadable ? { unreadable: true } : {};
729
738
  if (fileToken) {
730
- const same = cred && cred.accessToken === fileToken ? cred : null;
739
+ const same2 = cred && cred.accessToken === fileToken ? cred : null;
731
740
  return {
732
- ...withExpiry({ token: fileToken, source: "token-file", path: tokenFilePath(stateDir) }, same, now),
741
+ ...withExpiry({ token: fileToken, source: "token-file", path: tokenFilePath(stateDir) }, same2, now),
733
742
  ...unreadable
734
743
  };
735
744
  }
@@ -1766,14 +1775,14 @@ var require_foldFlowLines = __commonJS({
1766
1775
  var FOLD_FLOW = "flow";
1767
1776
  var FOLD_BLOCK = "block";
1768
1777
  var FOLD_QUOTED = "quoted";
1769
- function foldFlowLines(text, indent, mode = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
1778
+ function foldFlowLines(text2, indent, mode = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
1770
1779
  if (!lineWidth || lineWidth < 0)
1771
- return text;
1780
+ return text2;
1772
1781
  if (lineWidth < minContentWidth)
1773
1782
  minContentWidth = 0;
1774
1783
  const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length);
1775
- if (text.length <= endStep)
1776
- return text;
1784
+ if (text2.length <= endStep)
1785
+ return text2;
1777
1786
  const folds = [];
1778
1787
  const escapedFolds = {};
1779
1788
  let end = lineWidth - indent.length;
@@ -1790,14 +1799,14 @@ var require_foldFlowLines = __commonJS({
1790
1799
  let escStart = -1;
1791
1800
  let escEnd = -1;
1792
1801
  if (mode === FOLD_BLOCK) {
1793
- i = consumeMoreIndentedLines(text, i, indent.length);
1802
+ i = consumeMoreIndentedLines(text2, i, indent.length);
1794
1803
  if (i !== -1)
1795
1804
  end = i + endStep;
1796
1805
  }
1797
- for (let ch; ch = text[i += 1]; ) {
1806
+ for (let ch; ch = text2[i += 1]; ) {
1798
1807
  if (mode === FOLD_QUOTED && ch === "\\") {
1799
1808
  escStart = i;
1800
- switch (text[i + 1]) {
1809
+ switch (text2[i + 1]) {
1801
1810
  case "x":
1802
1811
  i += 3;
1803
1812
  break;
@@ -1814,12 +1823,12 @@ var require_foldFlowLines = __commonJS({
1814
1823
  }
1815
1824
  if (ch === "\n") {
1816
1825
  if (mode === FOLD_BLOCK)
1817
- i = consumeMoreIndentedLines(text, i, indent.length);
1826
+ i = consumeMoreIndentedLines(text2, i, indent.length);
1818
1827
  end = i + indent.length + endStep;
1819
1828
  split = void 0;
1820
1829
  } else {
1821
1830
  if (ch === " " && prev && prev !== " " && prev !== "\n" && prev !== " ") {
1822
- const next = text[i + 1];
1831
+ const next = text2[i + 1];
1823
1832
  if (next && next !== " " && next !== "\n" && next !== " ")
1824
1833
  split = i;
1825
1834
  }
@@ -1831,12 +1840,12 @@ var require_foldFlowLines = __commonJS({
1831
1840
  } else if (mode === FOLD_QUOTED) {
1832
1841
  while (prev === " " || prev === " ") {
1833
1842
  prev = ch;
1834
- ch = text[i += 1];
1843
+ ch = text2[i += 1];
1835
1844
  overflow = true;
1836
1845
  }
1837
1846
  const j = i > escEnd + 1 ? i - 2 : escStart - 1;
1838
1847
  if (escapedFolds[j])
1839
- return text;
1848
+ return text2;
1840
1849
  folds.push(j);
1841
1850
  escapedFolds[j] = true;
1842
1851
  end = j + endStep;
@@ -1851,39 +1860,39 @@ var require_foldFlowLines = __commonJS({
1851
1860
  if (overflow && onOverflow)
1852
1861
  onOverflow();
1853
1862
  if (folds.length === 0)
1854
- return text;
1863
+ return text2;
1855
1864
  if (onFold)
1856
1865
  onFold();
1857
- let res = text.slice(0, folds[0]);
1866
+ let res = text2.slice(0, folds[0]);
1858
1867
  for (let i2 = 0; i2 < folds.length; ++i2) {
1859
1868
  const fold = folds[i2];
1860
- const end2 = folds[i2 + 1] || text.length;
1869
+ const end2 = folds[i2 + 1] || text2.length;
1861
1870
  if (fold === 0)
1862
1871
  res = `
1863
- ${indent}${text.slice(0, end2)}`;
1872
+ ${indent}${text2.slice(0, end2)}`;
1864
1873
  else {
1865
1874
  if (mode === FOLD_QUOTED && escapedFolds[fold])
1866
- res += `${text[fold]}\\`;
1875
+ res += `${text2[fold]}\\`;
1867
1876
  res += `
1868
- ${indent}${text.slice(fold + 1, end2)}`;
1877
+ ${indent}${text2.slice(fold + 1, end2)}`;
1869
1878
  }
1870
1879
  }
1871
1880
  return res;
1872
1881
  }
1873
- function consumeMoreIndentedLines(text, i, indent) {
1882
+ function consumeMoreIndentedLines(text2, i, indent) {
1874
1883
  let end = i;
1875
1884
  let start = i + 1;
1876
- let ch = text[start];
1885
+ let ch = text2[start];
1877
1886
  while (ch === " " || ch === " ") {
1878
1887
  if (i < start + indent) {
1879
- ch = text[++i];
1888
+ ch = text2[++i];
1880
1889
  } else {
1881
1890
  do {
1882
- ch = text[++i];
1891
+ ch = text2[++i];
1883
1892
  } while (ch && ch !== "\n");
1884
1893
  end = i;
1885
1894
  start = i + 1;
1886
- ch = text[start];
1895
+ ch = text2[start];
1887
1896
  }
1888
1897
  }
1889
1898
  return end;
@@ -8014,7 +8023,7 @@ var require_public_api = __commonJS({
8014
8023
  }
8015
8024
  return doc;
8016
8025
  }
8017
- function parse3(src, reviver, options) {
8026
+ function parse4(src, reviver, options) {
8018
8027
  let _reviver = void 0;
8019
8028
  if (typeof reviver === "function") {
8020
8029
  _reviver = reviver;
@@ -8055,7 +8064,7 @@ var require_public_api = __commonJS({
8055
8064
  return value.toString(options);
8056
8065
  return new Document.Document(value, _replacer, options).toString(options);
8057
8066
  }
8058
- exports.parse = parse3;
8067
+ exports.parse = parse4;
8059
8068
  exports.parseAllDocuments = parseAllDocuments;
8060
8069
  exports.parseDocument = parseDocument;
8061
8070
  exports.stringify = stringify2;
@@ -8581,7 +8590,7 @@ var require_parse = __commonJS({
8581
8590
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/parse.js"(exports, module) {
8582
8591
  "use strict";
8583
8592
  var SemVer = require_semver();
8584
- var parse3 = (version2, options, throwErrors = false) => {
8593
+ var parse4 = (version2, options, throwErrors = false) => {
8585
8594
  if (version2 instanceof SemVer) {
8586
8595
  return version2;
8587
8596
  }
@@ -8594,7 +8603,7 @@ var require_parse = __commonJS({
8594
8603
  throw er;
8595
8604
  }
8596
8605
  };
8597
- module.exports = parse3;
8606
+ module.exports = parse4;
8598
8607
  }
8599
8608
  });
8600
8609
 
@@ -8602,9 +8611,9 @@ var require_parse = __commonJS({
8602
8611
  var require_valid = __commonJS({
8603
8612
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/valid.js"(exports, module) {
8604
8613
  "use strict";
8605
- var parse3 = require_parse();
8614
+ var parse4 = require_parse();
8606
8615
  var valid = (version2, options) => {
8607
- const v = parse3(version2, options);
8616
+ const v = parse4(version2, options);
8608
8617
  return v ? v.version : null;
8609
8618
  };
8610
8619
  module.exports = valid;
@@ -8615,9 +8624,9 @@ var require_valid = __commonJS({
8615
8624
  var require_clean = __commonJS({
8616
8625
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/clean.js"(exports, module) {
8617
8626
  "use strict";
8618
- var parse3 = require_parse();
8627
+ var parse4 = require_parse();
8619
8628
  var clean = (version2, options) => {
8620
- const s = parse3(version2.trim().replace(/^[=v]+/, ""), options);
8629
+ const s = parse4(version2.trim().replace(/^[=v]+/, ""), options);
8621
8630
  return s ? s.version : null;
8622
8631
  };
8623
8632
  module.exports = clean;
@@ -8652,10 +8661,10 @@ var require_inc = __commonJS({
8652
8661
  var require_diff = __commonJS({
8653
8662
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/diff.js"(exports, module) {
8654
8663
  "use strict";
8655
- var parse3 = require_parse();
8664
+ var parse4 = require_parse();
8656
8665
  var diff = (version1, version2) => {
8657
- const v1 = parse3(version1, null, true);
8658
- const v2 = parse3(version2, null, true);
8666
+ const v1 = parse4(version1, null, true);
8667
+ const v2 = parse4(version2, null, true);
8659
8668
  const comparison = v1.compare(v2);
8660
8669
  if (comparison === 0) {
8661
8670
  return null;
@@ -8726,9 +8735,9 @@ var require_patch = __commonJS({
8726
8735
  var require_prerelease = __commonJS({
8727
8736
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/prerelease.js"(exports, module) {
8728
8737
  "use strict";
8729
- var parse3 = require_parse();
8738
+ var parse4 = require_parse();
8730
8739
  var prerelease = (version2, options) => {
8731
- const parsed = parse3(version2, options);
8740
+ const parsed = parse4(version2, options);
8732
8741
  return parsed && parsed.prerelease.length ? parsed.prerelease : null;
8733
8742
  };
8734
8743
  module.exports = prerelease;
@@ -8914,7 +8923,7 @@ var require_coerce = __commonJS({
8914
8923
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/coerce.js"(exports, module) {
8915
8924
  "use strict";
8916
8925
  var SemVer = require_semver();
8917
- var parse3 = require_parse();
8926
+ var parse4 = require_parse();
8918
8927
  var { safeRe: re, t } = require_re();
8919
8928
  var coerce = (version2, options) => {
8920
8929
  if (version2 instanceof SemVer) {
@@ -8949,7 +8958,7 @@ var require_coerce = __commonJS({
8949
8958
  const patch = match[4] || "0";
8950
8959
  const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : "";
8951
8960
  const build = options.includePrerelease && match[6] ? `+${match[6]}` : "";
8952
- return parse3(`${major}.${minor}.${patch}${prerelease}${build}`, options);
8961
+ return parse4(`${major}.${minor}.${patch}${prerelease}${build}`, options);
8953
8962
  };
8954
8963
  module.exports = coerce;
8955
8964
  }
@@ -8959,7 +8968,7 @@ var require_coerce = __commonJS({
8959
8968
  var require_truncate = __commonJS({
8960
8969
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/truncate.js"(exports, module) {
8961
8970
  "use strict";
8962
- var parse3 = require_parse();
8971
+ var parse4 = require_parse();
8963
8972
  var constants2 = require_constants();
8964
8973
  var SemVer = require_semver();
8965
8974
  var truncate2 = (version2, truncation, options) => {
@@ -8971,7 +8980,7 @@ var require_truncate = __commonJS({
8971
8980
  };
8972
8981
  var cloneInputVersion = (version2, options) => {
8973
8982
  const versionStringToParse = version2 instanceof SemVer ? version2.version : version2;
8974
- return parse3(versionStringToParse, options);
8983
+ return parse4(versionStringToParse, options);
8975
8984
  };
8976
8985
  var doTruncation = (version2, truncation) => {
8977
8986
  if (isPrerelease(truncation)) {
@@ -9932,7 +9941,7 @@ var require_subset = __commonJS({
9932
9941
  }
9933
9942
  return true;
9934
9943
  }
9935
- let higher, lower;
9944
+ let higher, lower2;
9936
9945
  let hasDomLT, hasDomGT;
9937
9946
  let needDomLTPre = lt && !options.includePrerelease && lt.semver.prerelease.length ? lt.semver : false;
9938
9947
  let needDomGTPre = gt && !options.includePrerelease && gt.semver.prerelease.length ? gt.semver : false;
@@ -9964,8 +9973,8 @@ var require_subset = __commonJS({
9964
9973
  }
9965
9974
  }
9966
9975
  if (c.operator === "<" || c.operator === "<=") {
9967
- lower = lowerLT(lt, c, options);
9968
- if (lower === c && lower !== lt) {
9976
+ lower2 = lowerLT(lt, c, options);
9977
+ if (lower2 === c && lower2 !== lt) {
9969
9978
  return false;
9970
9979
  }
9971
9980
  } else if (lt.operator === "<=" && !c.test(lt.semver)) {
@@ -10013,7 +10022,7 @@ var require_semver2 = __commonJS({
10013
10022
  var constants2 = require_constants();
10014
10023
  var SemVer = require_semver();
10015
10024
  var identifiers = require_identifiers();
10016
- var parse3 = require_parse();
10025
+ var parse4 = require_parse();
10017
10026
  var valid = require_valid();
10018
10027
  var clean = require_clean();
10019
10028
  var inc = require_inc();
@@ -10052,7 +10061,7 @@ var require_semver2 = __commonJS({
10052
10061
  var simplifyRange = require_simplify();
10053
10062
  var subset = require_subset();
10054
10063
  module.exports = {
10055
- parse: parse3,
10064
+ parse: parse4,
10056
10065
  valid,
10057
10066
  clean,
10058
10067
  inc,
@@ -10955,7 +10964,7 @@ var require_lexer2 = __commonJS({
10955
10964
  this.colno--;
10956
10965
  }
10957
10966
  };
10958
- _proto.current = function current() {
10967
+ _proto.current = function current2() {
10959
10968
  if (!this.isFinished()) {
10960
10969
  return this.str.charAt(this.index);
10961
10970
  }
@@ -12439,7 +12448,7 @@ var require_parser2 = __commonJS({
12439
12448
  }
12440
12449
  return buf;
12441
12450
  };
12442
- _proto.parse = function parse3() {
12451
+ _proto.parse = function parse4() {
12443
12452
  return new nodes.NodeList(0, 0, this.parseNodes());
12444
12453
  };
12445
12454
  _proto.parseAsRoot = function parseAsRoot() {
@@ -12448,7 +12457,7 @@ var require_parser2 = __commonJS({
12448
12457
  return Parser2;
12449
12458
  }(Obj);
12450
12459
  module.exports = {
12451
- parse: function parse3(src, extensions, opts) {
12460
+ parse: function parse4(src, extensions, opts) {
12452
12461
  var p = new Parser(lexer.lex(src, opts));
12453
12462
  if (extensions !== void 0) {
12454
12463
  p.extensions = extensions;
@@ -14076,11 +14085,11 @@ var require_filters = __commonJS({
14076
14085
  }
14077
14086
  }
14078
14087
  _exports.list = list;
14079
- function lower(str) {
14088
+ function lower2(str) {
14080
14089
  str = normalize(str, "");
14081
14090
  return str.toLowerCase();
14082
14091
  }
14083
- _exports.lower = lower;
14092
+ _exports.lower = lower2;
14084
14093
  function nl2br(str) {
14085
14094
  if (str === null || str === void 0) {
14086
14095
  return "";
@@ -14663,10 +14672,10 @@ var require_tests = __commonJS({
14663
14672
  }
14664
14673
  exports.lessthan = lessthan;
14665
14674
  exports.lt = exports.lessthan;
14666
- function lower(value) {
14675
+ function lower2(value) {
14667
14676
  return value.toLowerCase() === value;
14668
14677
  }
14669
- exports.lower = lower;
14678
+ exports.lower = lower2;
14670
14679
  function ne(one, two) {
14671
14680
  return one !== two;
14672
14681
  }
@@ -16267,11 +16276,11 @@ var require_stream_writable = __commonJS({
16267
16276
  this.corkedRequestsFree = new CorkedRequest(this);
16268
16277
  }
16269
16278
  WritableState.prototype.getBuffer = function getBuffer() {
16270
- var current = this.bufferedRequest;
16279
+ var current2 = this.bufferedRequest;
16271
16280
  var out = [];
16272
- while (current) {
16273
- out.push(current);
16274
- current = current.next;
16281
+ while (current2) {
16282
+ out.push(current2);
16283
+ current2 = current2.next;
16275
16284
  }
16276
16285
  return out;
16277
16286
  };
@@ -21796,7 +21805,7 @@ var require_deflate2 = __commonJS({
21796
21805
  "use strict";
21797
21806
  var zlib_deflate = require_deflate();
21798
21807
  var utils = require_common();
21799
- var strings = require_strings();
21808
+ var strings2 = require_strings();
21800
21809
  var msg = require_messages();
21801
21810
  var ZStream = require_zstream();
21802
21811
  var toString = Object.prototype.toString;
@@ -21848,7 +21857,7 @@ var require_deflate2 = __commonJS({
21848
21857
  if (opt.dictionary) {
21849
21858
  var dict;
21850
21859
  if (typeof opt.dictionary === "string") {
21851
- dict = strings.string2buf(opt.dictionary);
21860
+ dict = strings2.string2buf(opt.dictionary);
21852
21861
  } else if (toString.call(opt.dictionary) === "[object ArrayBuffer]") {
21853
21862
  dict = new Uint8Array(opt.dictionary);
21854
21863
  } else {
@@ -21870,7 +21879,7 @@ var require_deflate2 = __commonJS({
21870
21879
  }
21871
21880
  _mode = mode === ~~mode ? mode : mode === true ? Z_FINISH : Z_NO_FLUSH;
21872
21881
  if (typeof data === "string") {
21873
- strm.input = strings.string2buf(data);
21882
+ strm.input = strings2.string2buf(data);
21874
21883
  } else if (toString.call(data) === "[object ArrayBuffer]") {
21875
21884
  strm.input = new Uint8Array(data);
21876
21885
  } else {
@@ -21892,7 +21901,7 @@ var require_deflate2 = __commonJS({
21892
21901
  }
21893
21902
  if (strm.avail_out === 0 || strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH)) {
21894
21903
  if (this.options.to === "string") {
21895
- this.onData(strings.buf2binstring(utils.shrinkBuf(strm.output, strm.next_out)));
21904
+ this.onData(strings2.buf2binstring(utils.shrinkBuf(strm.output, strm.next_out)));
21896
21905
  } else {
21897
21906
  this.onData(utils.shrinkBuf(strm.output, strm.next_out));
21898
21907
  }
@@ -23785,7 +23794,7 @@ var require_inflate2 = __commonJS({
23785
23794
  "use strict";
23786
23795
  var zlib_inflate = require_inflate();
23787
23796
  var utils = require_common();
23788
- var strings = require_strings();
23797
+ var strings2 = require_strings();
23789
23798
  var c = require_constants2();
23790
23799
  var msg = require_messages();
23791
23800
  var ZStream = require_zstream();
@@ -23830,7 +23839,7 @@ var require_inflate2 = __commonJS({
23830
23839
  zlib_inflate.inflateGetHeader(this.strm, this.header);
23831
23840
  if (opt.dictionary) {
23832
23841
  if (typeof opt.dictionary === "string") {
23833
- opt.dictionary = strings.string2buf(opt.dictionary);
23842
+ opt.dictionary = strings2.string2buf(opt.dictionary);
23834
23843
  } else if (toString.call(opt.dictionary) === "[object ArrayBuffer]") {
23835
23844
  opt.dictionary = new Uint8Array(opt.dictionary);
23836
23845
  }
@@ -23854,7 +23863,7 @@ var require_inflate2 = __commonJS({
23854
23863
  }
23855
23864
  _mode = mode === ~~mode ? mode : mode === true ? c.Z_FINISH : c.Z_NO_FLUSH;
23856
23865
  if (typeof data === "string") {
23857
- strm.input = strings.binstring2buf(data);
23866
+ strm.input = strings2.binstring2buf(data);
23858
23867
  } else if (toString.call(data) === "[object ArrayBuffer]") {
23859
23868
  strm.input = new Uint8Array(data);
23860
23869
  } else {
@@ -23884,9 +23893,9 @@ var require_inflate2 = __commonJS({
23884
23893
  if (strm.next_out) {
23885
23894
  if (strm.avail_out === 0 || status === c.Z_STREAM_END || strm.avail_in === 0 && (_mode === c.Z_FINISH || _mode === c.Z_SYNC_FLUSH)) {
23886
23895
  if (this.options.to === "string") {
23887
- next_out_utf8 = strings.utf8border(strm.output, strm.next_out);
23896
+ next_out_utf8 = strings2.utf8border(strm.output, strm.next_out);
23888
23897
  tail = strm.next_out - next_out_utf8;
23889
- utf8str = strings.buf2string(strm.output, next_out_utf8);
23898
+ utf8str = strings2.buf2string(strm.output, next_out_utf8);
23890
23899
  strm.next_out = tail;
23891
23900
  strm.avail_out = chunkSize - tail;
23892
23901
  if (tail) {
@@ -24231,9 +24240,9 @@ var require_ZipFileWorker = __commonJS({
24231
24240
  this.currentFile = streamInfo["file"].name;
24232
24241
  var streamedContent = this.streamFiles && !streamInfo["file"].dir;
24233
24242
  if (streamedContent) {
24234
- var record = generateZipParts(streamInfo, streamedContent, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName);
24243
+ var record2 = generateZipParts(streamInfo, streamedContent, false, this.currentSourceOffset, this.zipPlatform, this.encodeFileName);
24235
24244
  this.push({
24236
- data: record.fileRecord,
24245
+ data: record2.fileRecord,
24237
24246
  meta: { percent: 0 }
24238
24247
  });
24239
24248
  } else {
@@ -24243,8 +24252,8 @@ var require_ZipFileWorker = __commonJS({
24243
24252
  ZipFileWorker.prototype.closedSource = function(streamInfo) {
24244
24253
  this.accumulate = false;
24245
24254
  var streamedContent = this.streamFiles && !streamInfo["file"].dir;
24246
- var record = generateZipParts(streamInfo, streamedContent, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName);
24247
- this.dirRecords.push(record.dirRecord);
24255
+ var record2 = generateZipParts(streamInfo, streamedContent, true, this.currentSourceOffset, this.zipPlatform, this.encodeFileName);
24256
+ this.dirRecords.push(record2.dirRecord);
24248
24257
  if (streamedContent) {
24249
24258
  this.push({
24250
24259
  data: generateDataDescriptors(streamInfo),
@@ -24252,7 +24261,7 @@ var require_ZipFileWorker = __commonJS({
24252
24261
  });
24253
24262
  } else {
24254
24263
  this.push({
24255
- data: record.fileRecord,
24264
+ data: record2.fileRecord,
24256
24265
  meta: { percent: 0 }
24257
24266
  });
24258
24267
  while (this.contentBuffer.length) {
@@ -25510,7 +25519,10 @@ var require_lib4 = __commonJS({
25510
25519
  }
25511
25520
  });
25512
25521
 
25513
- // ../../node_modules/.pnpm/@prompd+core@0.6.0/node_modules/@prompd/core/dist/index.js
25522
+ // ../../node_modules/.pnpm/@prompd+core@0.7.0/node_modules/@prompd/core/dist/index.js
25523
+ function isValidPackageType(type) {
25524
+ return VALID_PACKAGE_TYPES.includes(type);
25525
+ }
25514
25526
  function posixNormalize(p) {
25515
25527
  const isAbs = p.startsWith("/");
25516
25528
  const out = [];
@@ -25603,15 +25615,15 @@ function extname(p) {
25603
25615
  return dot <= 0 ? "" : base.slice(dot);
25604
25616
  }
25605
25617
  function isPrompdFile(p) {
25606
- const lower = p.toLowerCase();
25607
- return lower.endsWith(".prmd") || lower.endsWith(".md");
25618
+ const lower2 = p.toLowerCase();
25619
+ return lower2.endsWith(".prmd") || lower2.endsWith(".md");
25608
25620
  }
25609
25621
  function parseDateExpr(input) {
25610
25622
  const v = (input ?? "").trim();
25611
25623
  if (!v) return null;
25612
- const lower = v.toLowerCase();
25613
- if (lower === "now" || lower === "today") return /* @__PURE__ */ new Date();
25614
- const rel = lower.match(/^(?:now|today)\s*([+-])\s*(\d+)\s*([a-z]+)$/);
25624
+ const lower2 = v.toLowerCase();
25625
+ if (lower2 === "now" || lower2 === "today") return /* @__PURE__ */ new Date();
25626
+ const rel = lower2.match(/^(?:now|today)\s*([+-])\s*(\d+)\s*([a-z]+)$/);
25615
25627
  if (rel) {
25616
25628
  const n = (rel[1] === "-" ? -1 : 1) * parseInt(rel[2], 10);
25617
25629
  const u = rel[3];
@@ -25654,37 +25666,483 @@ function getLanguageAliasesForExtension(ext) {
25654
25666
  function generateCompilationId() {
25655
25667
  return `compile-${++compilationCounter}-${Date.now()}`;
25656
25668
  }
25657
- function isBinaryAsset(name) {
25658
- const dot = name.lastIndexOf(".");
25659
- return dot >= 0 && BINARY_ASSET_EXT.has(name.slice(dot + 1).toLowerCase());
25669
+ function isPackageVerificationError(e) {
25670
+ if (!(e instanceof Error)) return false;
25671
+ const code3 = e.code;
25672
+ return e.name === "PackageVerificationError" && typeof code3 === "string";
25673
+ }
25674
+ function hasControl(s) {
25675
+ for (let i = 0; i < s.length; i++) {
25676
+ const c = s.charCodeAt(i);
25677
+ if (c < 32 || c >= 127 && c <= 159) return true;
25678
+ }
25679
+ return false;
25660
25680
  }
25661
- function isSymlinkEntry(perms) {
25662
- return typeof perms === "number" && (perms & 61440) === 40960;
25681
+ function shown(name) {
25682
+ if (hasControl(name) || BIDI_RE.test(name)) return "a file name in the package";
25683
+ return name.length > ARCHIVE_LIMITS.maxNameLength ? `${name.slice(0, ARCHIVE_LIMITS.maxNameLength)}...` : name;
25684
+ }
25685
+ function entryNameProblem(name) {
25686
+ if (hasControl(name)) return "a file name in the package holds a control character";
25687
+ if (!name) return "a file in the package has no name";
25688
+ if (BIDI_RE.test(name)) return "a file name in the package holds a text-direction character";
25689
+ if (name.length > ARCHIVE_LIMITS.maxNameLength) return `a file name in the package is too long (over ${ARCHIVE_LIMITS.maxNameLength} characters)`;
25690
+ if (name.includes("\\")) return `${name} uses a backslash; package paths use forward slashes`;
25691
+ if (name.startsWith("/") || /^[A-Za-z]:/.test(name)) return `${name} is an absolute path`;
25692
+ const segs = name.split("/");
25693
+ if (segs.some((s) => s === ".." || s === "." || s === "")) return `${name} has an empty, "." or ".." segment`;
25694
+ if (name.includes(":")) return `${name} holds a colon`;
25695
+ if (segs.length > ARCHIVE_LIMITS.maxSegments) return `${name} is nested too deeply`;
25696
+ for (const s of segs) {
25697
+ if (s.endsWith(".") || s.endsWith(" ")) return `${name} has a part that ends with a dot or a space`;
25698
+ const stem = s.split(".")[0]?.replace(/ +$/, "") ?? "";
25699
+ if (WINDOWS_DEVICE_RE.test(stem)) return `${name} uses a device name Windows has reserved`;
25700
+ }
25701
+ if (name !== name.normalize("NFC")) return `${name} is not in normalized (NFC) form`;
25702
+ return null;
25663
25703
  }
25664
- async function extractPdpkg(buffer) {
25665
- const zip = await import_jszip.default.loadAsync(buffer);
25666
- const out = /* @__PURE__ */ new Map();
25704
+ function u16(b, at) {
25705
+ return (b[at] ?? 0) | (b[at + 1] ?? 0) << 8;
25706
+ }
25707
+ function u32(b, at) {
25708
+ return u16(b, at) + u16(b, at + 2) * 65536;
25709
+ }
25710
+ function refuseUnicodePathField(raw, start, end, name) {
25711
+ let at = start;
25712
+ while (at < end) {
25713
+ if (at + 4 > end) throw new PackageVerificationError("ARCHIVE_INVALID", NOT_A_ZIP);
25714
+ const id = u16(raw, at);
25715
+ const len = u16(raw, at + 2);
25716
+ if (at + 4 + len > end) throw new PackageVerificationError("ARCHIVE_INVALID", NOT_A_ZIP);
25717
+ if (id === UNICODE_PATH_FIELD) throw new PackageVerificationError("UNSAFE_PATH", `${shown(name)} carries an alternate path field`, name);
25718
+ at += 4 + len;
25719
+ }
25720
+ }
25721
+ function checkLocalHeader(raw, centralName, name, localAt, centralStart) {
25722
+ if (localAt + LOCAL_LEN > centralStart || u32(raw, localAt) !== LOCAL_SIG) throw new PackageVerificationError("ARCHIVE_INVALID", NOT_A_ZIP, name);
25723
+ const nameLen = u16(raw, localAt + 26);
25724
+ const extraLen = u16(raw, localAt + 28);
25725
+ const nameEnd = localAt + LOCAL_LEN + nameLen;
25726
+ if (nameEnd + extraLen > centralStart) throw new PackageVerificationError("ARCHIVE_INVALID", NOT_A_ZIP, name);
25727
+ const localName = raw.subarray(localAt + LOCAL_LEN, nameEnd);
25728
+ if (localName.length !== centralName.length || !localName.every((b, i) => b === centralName[i])) {
25729
+ throw new PackageVerificationError("ARCHIVE_INVALID", `${shown(name)} is named differently in its local header`, name);
25730
+ }
25731
+ refuseUnicodePathField(raw, nameEnd, nameEnd + extraLen, name);
25732
+ }
25733
+ function scanCentralDirectory(raw) {
25734
+ const lowest = Math.max(0, raw.length - EOCD_LEN - 65535);
25735
+ let eocd = -1;
25736
+ for (let i = raw.length - EOCD_LEN; i >= lowest; i--) {
25737
+ if (u32(raw, i) === EOCD_SIG) {
25738
+ eocd = i;
25739
+ break;
25740
+ }
25741
+ }
25742
+ if (eocd < 0) throw new PackageVerificationError("ARCHIVE_INVALID", NOT_A_ZIP);
25743
+ if (eocd + EOCD_LEN + u16(raw, eocd + 20) !== raw.length) throw new PackageVerificationError("ARCHIVE_INVALID", NOT_A_ZIP);
25744
+ const count = u16(raw, eocd + 10);
25745
+ const size = u32(raw, eocd + 12);
25746
+ const offset = u32(raw, eocd + 16);
25747
+ if (count === 65535 || size === 4294967295 || offset === 4294967295) {
25748
+ throw new PackageVerificationError("ARCHIVE_INVALID", "the package is a zip64 archive, which a package never needs");
25749
+ }
25750
+ if (u16(raw, eocd + 4) !== 0 || u16(raw, eocd + 6) !== 0 || u16(raw, eocd + 8) !== count) {
25751
+ throw new PackageVerificationError("ARCHIVE_INVALID", NOT_A_ZIP);
25752
+ }
25753
+ if (count > ARCHIVE_LIMITS.maxEntries) {
25754
+ throw new PackageVerificationError("TOO_LARGE", `the package holds too many files (over ${ARCHIVE_LIMITS.maxEntries})`);
25755
+ }
25756
+ if (offset + size !== eocd) throw new PackageVerificationError("ARCHIVE_INVALID", NOT_A_ZIP);
25757
+ const out = [];
25667
25758
  let total = 0;
25668
- for (const entry of Object.values(zip.files)) {
25669
- if (entry.name.includes("\0")) {
25670
- throw new Error(`Security violation: null byte in entry name: ${entry.name}`);
25759
+ let at = offset;
25760
+ for (let i = 0; i < count; i++) {
25761
+ if (at + CENTRAL_LEN > eocd || u32(raw, at) !== CENTRAL_SIG) throw new PackageVerificationError("ARCHIVE_INVALID", NOT_A_ZIP);
25762
+ const compressed = u32(raw, at + 20);
25763
+ const uncompressed = u32(raw, at + 24);
25764
+ const nameLen = u16(raw, at + 28);
25765
+ const next = at + CENTRAL_LEN + nameLen + u16(raw, at + 30) + u16(raw, at + 32);
25766
+ if (next > eocd) throw new PackageVerificationError("ARCHIVE_INVALID", NOT_A_ZIP);
25767
+ let name;
25768
+ try {
25769
+ name = nameDecoder.decode(raw.subarray(at + CENTRAL_LEN, at + CENTRAL_LEN + nameLen));
25770
+ } catch {
25771
+ throw new PackageVerificationError("ARCHIVE_INVALID", "a file name in the package is not UTF-8");
25772
+ }
25773
+ const centralName = raw.subarray(at + CENTRAL_LEN, at + CENTRAL_LEN + nameLen);
25774
+ const extraStart = at + CENTRAL_LEN + nameLen;
25775
+ refuseUnicodePathField(raw, extraStart, extraStart + u16(raw, at + 30), name);
25776
+ checkLocalHeader(raw, centralName, name, u32(raw, at + 42), offset);
25777
+ const external = u32(raw, at + 38);
25778
+ if ((Math.floor(external / 65536) & 61440) === 40960) {
25779
+ throw new PackageVerificationError("UNSAFE_PATH", `${shown(name)} is a link`, name);
25780
+ }
25781
+ const folder = (external & 16) !== 0 || name.endsWith("/");
25782
+ if (folder && uncompressed !== 0) throw new PackageVerificationError("ARCHIVE_INVALID", `${shown(name)} is marked as a folder but holds data`, name);
25783
+ if (!folder) {
25784
+ if (uncompressed > ARCHIVE_LIMITS.maxFileBytes) throw new PackageVerificationError("TOO_LARGE", `${shown(name)} is over ${ARCHIVE_LIMITS.maxFileBytes} bytes`, name);
25785
+ if (uncompressed > 0 && compressed === 0) throw new PackageVerificationError("ARCHIVE_INVALID", NOT_A_ZIP, name);
25786
+ if (compressed > 0 && uncompressed / compressed > ARCHIVE_LIMITS.maxRatio) {
25787
+ throw new PackageVerificationError("TOO_LARGE", `${shown(name)} compresses more than ${ARCHIVE_LIMITS.maxRatio}:1`, name);
25788
+ }
25789
+ total += uncompressed;
25790
+ if (total > ARCHIVE_LIMITS.maxTotalBytes) throw new PackageVerificationError("TOO_LARGE", `the package is over ${ARCHIVE_LIMITS.maxTotalBytes} bytes unpacked`);
25791
+ }
25792
+ out.push({ name, compressed, uncompressed, folder });
25793
+ at = next;
25794
+ }
25795
+ if (at !== offset + size) throw new PackageVerificationError("ARCHIVE_INVALID", NOT_A_ZIP);
25796
+ return out;
25797
+ }
25798
+ function checkNames(records) {
25799
+ const keys = /* @__PURE__ */ new Set();
25800
+ const files = records.filter((r) => !r.folder);
25801
+ for (const r of files) {
25802
+ const problem = entryNameProblem(r.name);
25803
+ if (problem) throw new PackageVerificationError("UNSAFE_PATH", problem, r.name);
25804
+ const key = r.name.toLowerCase();
25805
+ if (keys.has(key)) throw new PackageVerificationError("UNSAFE_PATH", `the package holds two entries with the same name (${r.name})`, r.name);
25806
+ keys.add(key);
25807
+ }
25808
+ for (const r of files) {
25809
+ const segs = r.name.toLowerCase().split("/");
25810
+ for (let i = 1; i < segs.length; i++) {
25811
+ const parent = segs.slice(0, i).join("/");
25812
+ if (keys.has(parent)) throw new PackageVerificationError("UNSAFE_PATH", `${r.name} uses ${parent} as a folder, but it is a file`, r.name);
25813
+ }
25814
+ }
25815
+ }
25816
+ function inflateOne(entry, limit, state) {
25817
+ return new Promise((resolveBytes, reject) => {
25818
+ const chunks = [];
25819
+ let size = 0;
25820
+ let settled = false;
25821
+ const stream = entry.internalStream("uint8array");
25822
+ const fail = (e) => {
25823
+ if (!settled) {
25824
+ settled = true;
25825
+ stream.pause();
25826
+ reject(e);
25827
+ }
25828
+ };
25829
+ stream.on("data", (chunk) => {
25830
+ if (settled) return;
25831
+ size += chunk.length;
25832
+ state.total += chunk.length;
25833
+ if (size > limit || size > ARCHIVE_LIMITS.maxFileBytes) {
25834
+ fail(new PackageVerificationError("TOO_LARGE", `${shown(entry.name)} is larger than its header says`, entry.name));
25835
+ return;
25836
+ }
25837
+ if (state.total > ARCHIVE_LIMITS.maxTotalBytes) {
25838
+ fail(new PackageVerificationError("TOO_LARGE", `the package is over ${ARCHIVE_LIMITS.maxTotalBytes} bytes unpacked`));
25839
+ return;
25840
+ }
25841
+ chunks.push(chunk);
25842
+ });
25843
+ stream.on("error", (e) => fail(new PackageVerificationError("ARCHIVE_INVALID", `${shown(entry.name)} could not be unpacked: ${e.message}`, entry.name)));
25844
+ stream.on("end", () => {
25845
+ if (settled) return;
25846
+ settled = true;
25847
+ const out = new Uint8Array(size);
25848
+ let at = 0;
25849
+ for (const c of chunks) {
25850
+ out.set(c, at);
25851
+ at += c.length;
25852
+ }
25853
+ resolveBytes(out);
25854
+ });
25855
+ stream.resume();
25856
+ });
25857
+ }
25858
+ async function readArchive(raw) {
25859
+ const records = scanCentralDirectory(raw);
25860
+ checkNames(records);
25861
+ let zip;
25862
+ try {
25863
+ zip = await import_jszip.default.loadAsync(raw, { createFolders: false });
25864
+ } catch {
25865
+ throw new PackageVerificationError("ARCHIVE_INVALID", NOT_A_ZIP);
25866
+ }
25867
+ const all = Object.values(zip.files);
25868
+ if (all.length !== records.length) throw new PackageVerificationError("ARCHIVE_INVALID", "the package holds two entries with the same name");
25869
+ const declared = new Map(records.map((r) => [r.name, r.uncompressed]));
25870
+ const out = /* @__PURE__ */ new Map();
25871
+ const state = { total: 0 };
25872
+ for (const [i, entry] of all.entries()) {
25873
+ if (entry.name !== records[i]?.name) {
25874
+ throw new PackageVerificationError("ARCHIVE_INVALID", `${shown(entry.name)} does not match the package's central directory`, entry.name);
25875
+ }
25876
+ const original = entry.unsafeOriginalName ?? entry.name;
25877
+ if (original !== entry.name || !declared.has(original)) {
25878
+ throw new PackageVerificationError("UNSAFE_PATH", `${shown(original)} is not a plain path inside the package`, original);
25879
+ }
25880
+ if (entry.dir) continue;
25881
+ out.set(entry.name, await inflateOne(entry, declared.get(entry.name) ?? 0, state));
25882
+ }
25883
+ return out;
25884
+ }
25885
+ function subtle() {
25886
+ const c = globalThis.crypto;
25887
+ if (!c?.subtle) throw new Error("WebCrypto (crypto.subtle) is not available in this runtime; Node 20 or later is required.");
25888
+ return c.subtle;
25889
+ }
25890
+ async function sha256Hex(bytes) {
25891
+ const buf = await subtle().digest("SHA-256", bytes);
25892
+ const out = new Uint8Array(buf);
25893
+ let hex = "";
25894
+ for (let i = 0; i < out.length; i++) hex += out[i].toString(16).padStart(2, "0");
25895
+ return hex;
25896
+ }
25897
+ async function archiveDigest(bytes) {
25898
+ return `sha256:${await sha256Hex(bytes)}`;
25899
+ }
25900
+ function invalid(message) {
25901
+ return new PackageVerificationError("MANIFEST_INVALID", message, "prompd.json");
25902
+ }
25903
+ function isRecord(v) {
25904
+ return typeof v === "object" && v !== null && !Array.isArray(v);
25905
+ }
25906
+ function stringList(v, field) {
25907
+ if (v === void 0) return void 0;
25908
+ if (!Array.isArray(v) || v.some((s) => typeof s !== "string" || !s)) throw invalid(`${field} must be a list of names`);
25909
+ return v;
25910
+ }
25911
+ function unscopedName(name) {
25912
+ const slash = name.indexOf("/");
25913
+ return name.startsWith("@") && slash > 0 ? name.slice(slash + 1) : name;
25914
+ }
25915
+ function parseManifest(bytes) {
25916
+ let text2;
25917
+ try {
25918
+ text2 = decoder.decode(bytes);
25919
+ } catch {
25920
+ throw invalid("prompd.json is not UTF-8 text");
25921
+ }
25922
+ let raw;
25923
+ try {
25924
+ raw = JSON.parse(text2, (k, v) => PROTO_KEYS.has(k) ? void 0 : v);
25925
+ } catch {
25926
+ throw invalid("prompd.json is not valid JSON");
25927
+ }
25928
+ if (!isRecord(raw)) throw invalid("prompd.json is not a JSON object");
25929
+ const { name, version: version2, type, dependencies, requires } = raw;
25930
+ if (typeof name !== "string" || !PACKAGE_NAME_RE.test(name)) throw invalid('prompd.json "name" must be a scoped package name like @scope/name');
25931
+ if (typeof version2 !== "string" || import_semver.default.valid(version2) !== version2) throw invalid('prompd.json "version" must be an exact semver version');
25932
+ let resolvedType = "package";
25933
+ if (type !== void 0) {
25934
+ if (typeof type !== "string" || !isValidPackageType(type)) {
25935
+ throw new PackageVerificationError("TYPE_INVALID", `package type "${String(type)}" is not one of package, workflow, skill, agent`, "prompd.json");
25936
+ }
25937
+ resolvedType = type;
25938
+ }
25939
+ let deps;
25940
+ if (dependencies !== void 0) {
25941
+ if (!isRecord(dependencies)) throw invalid('prompd.json "dependencies" must be an object');
25942
+ deps = {};
25943
+ for (const [dep, range] of Object.entries(dependencies)) {
25944
+ if (!PACKAGE_NAME_RE.test(dep)) throw invalid(`dependency "${dep}" is not a scoped package name`);
25945
+ if (typeof range !== "string" || import_semver.default.validRange(range) === null) throw invalid(`dependency "${dep}" has an invalid version range`);
25946
+ deps[dep] = range;
25947
+ }
25948
+ }
25949
+ let req;
25950
+ if (requires !== void 0) {
25951
+ if (!isRecord(requires)) throw invalid('prompd.json "requires" must be an object');
25952
+ const mcp = stringList(requires.mcp, "requires.mcp");
25953
+ const skills = stringList(requires.skills, "requires.skills");
25954
+ req = { ...mcp ? { mcp } : {}, ...skills ? { skills } : {} };
25955
+ }
25956
+ return {
25957
+ ...raw,
25958
+ name,
25959
+ version: version2,
25960
+ type: resolvedType,
25961
+ ...deps ? { dependencies: deps } : {},
25962
+ ...req ? { requires: req } : {}
25963
+ };
25964
+ }
25965
+ function invalid2(message, path) {
25966
+ return new PackageVerificationError("MANIFEST_INVALID", message, path);
25967
+ }
25968
+ function text(files, name) {
25969
+ const b = files.get(name);
25970
+ if (!b) throw invalid2(`an agent package must contain ${name}`, name);
25971
+ try {
25972
+ return decoder2.decode(b);
25973
+ } catch {
25974
+ throw invalid2(`${name} is not UTF-8 text`, name);
25975
+ }
25976
+ }
25977
+ function record(v) {
25978
+ return typeof v === "object" && v !== null && !Array.isArray(v) ? v : {};
25979
+ }
25980
+ function strings(v) {
25981
+ if (!Array.isArray(v)) return [];
25982
+ return v.filter((s) => typeof s === "string").map((s) => s.trim()).filter((s) => s.length > 0);
25983
+ }
25984
+ function yamlOf(src, path) {
25985
+ try {
25986
+ return (0, import_yaml.parse)(src);
25987
+ } catch {
25988
+ throw invalid2(`${path} is not valid YAML`, path);
25989
+ }
25990
+ }
25991
+ function frontmatter(src) {
25992
+ const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(src);
25993
+ return m ? record(yamlOf(m[1], "AGENT.md")) : {};
25994
+ }
25995
+ function unique(xs) {
25996
+ return [...new Set(xs)];
25997
+ }
25998
+ function unnamedMcp(addr) {
25999
+ return invalid2(`POLICY.yaml allows "${addr}", which can reach MCP servers it does not name; MCP access in a package must name each server (mcp:<server>/<tool> or mcp:<server>/*)`, "POLICY.yaml");
26000
+ }
26001
+ function mcpWireName(addr) {
26002
+ return invalid2(`POLICY.yaml allows "${addr}", an MCP wire name; in a package, allow MCP tools as mcp:<server>/<tool> or mcp:<server>/*`, "POLICY.yaml");
26003
+ }
26004
+ function mcpServerOf(addr) {
26005
+ if (addr.startsWith(MCP_WIRE_PREFIX)) throw mcpWireName(addr);
26006
+ const glob = addr.search(GLOB_RE);
26007
+ if (glob >= 0) {
26008
+ const literal = addr.slice(0, glob);
26009
+ if (MCP_PREFIX.startsWith(literal)) throw unnamedMcp(addr);
26010
+ if (MCP_WIRE_PREFIX.startsWith(literal)) throw mcpWireName(addr);
26011
+ if (literal.startsWith(MCP_PREFIX)) {
26012
+ const slash2 = addr.indexOf("/", MCP_PREFIX.length);
26013
+ const server = addr.slice(MCP_PREFIX.length, slash2 < 0 ? void 0 : slash2);
26014
+ if (GLOB_RE.test(server)) throw unnamedMcp(addr);
26015
+ }
26016
+ }
26017
+ if (!addr.startsWith(MCP_PREFIX)) return null;
26018
+ const slash = addr.indexOf("/", MCP_PREFIX.length);
26019
+ if (addr.slice(MCP_PREFIX.length, slash < 0 ? void 0 : slash).includes("\\")) {
26020
+ throw invalid2(`POLICY.yaml allows "${addr}"; MCP server names with escaped characters cannot be used in a package`, "POLICY.yaml");
26021
+ }
26022
+ const m = NAMED_MCP_RE.exec(addr);
26023
+ if (!m) throw unnamedMcp(addr);
26024
+ return m[1];
26025
+ }
26026
+ function checkAgentPackage(manifest, files) {
26027
+ const allowed = new Set(AGENT_PACKAGE_FILES);
26028
+ for (const name of files.keys()) {
26029
+ if (!allowed.has(name)) throw invalid2(`an agent package may hold only ${AGENT_PACKAGE_FILES.join(", ")}; found ${name}`, name);
26030
+ }
26031
+ for (const name of AGENT_PACKAGE_FILES) {
26032
+ if (!files.has(name)) throw invalid2(`an agent package must contain ${name}`, name);
26033
+ }
26034
+ const fm = frontmatter(text(files, "AGENT.md"));
26035
+ const policy = record(yamlOf(text(files, "POLICY.yaml"), "POLICY.yaml"));
26036
+ const deps = new Set(Object.keys(manifest.dependencies ?? {}).map(unscopedName));
26037
+ const reqSkills = new Set(manifest.requires?.skills ?? []);
26038
+ const reqMcp = new Set(manifest.requires?.mcp ?? []);
26039
+ if (fm.canCallAll === true) throw invalid2("canCallAll cannot be used in a package; list the agents in canCall and declare them as dependencies", "AGENT.md");
26040
+ const skills = unique(strings(policy.skills));
26041
+ for (const s of skills) {
26042
+ if (!deps.has(s) && !reqSkills.has(s)) throw invalid2(`POLICY.yaml grants skill "${s}", which is neither a dependency nor listed in requires.skills`, "POLICY.yaml");
26043
+ }
26044
+ const after = [];
26045
+ for (const trig of Array.isArray(fm.triggers) ? fm.triggers : []) {
26046
+ const t = record(trig);
26047
+ if (t.type === "run-complete") after.push(...strings(record(t.config).after));
26048
+ }
26049
+ const agents = unique([...strings(fm.canCall), ...after]);
26050
+ for (const a of agents) {
26051
+ if (!deps.has(a)) throw invalid2(`AGENT.md calls agent "${a}", which is not a dependency`, "AGENT.md");
26052
+ }
26053
+ const mcp = [];
26054
+ for (const addr of strings(record(policy.tools).allow)) {
26055
+ const server = mcpServerOf(addr);
26056
+ if (server !== null) mcp.push(server);
26057
+ }
26058
+ const servers = unique(mcp);
26059
+ for (const s of servers) {
26060
+ if (!reqMcp.has(s)) throw invalid2(`POLICY.yaml allows MCP server "${s}", which is not listed in requires.mcp`, "POLICY.yaml");
26061
+ }
26062
+ return { skills: skills.filter((s) => deps.has(s)), agents, mcp: servers };
26063
+ }
26064
+ function integrityOf(raw) {
26065
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
26066
+ throw new PackageVerificationError("INTEGRITY_MISSING", 'the package has no integrity block; republish it with "prompd package create"', MANIFEST_FILE);
26067
+ }
26068
+ const r = raw;
26069
+ if (r.algorithm !== "sha256") {
26070
+ throw new PackageVerificationError("UNSUPPORTED_ALGORITHM", `integrity algorithm "${String(r.algorithm)}" is not supported (sha256 only)`, MANIFEST_FILE);
26071
+ }
26072
+ const files = r.files;
26073
+ if (typeof files !== "object" || files === null || Array.isArray(files)) {
26074
+ throw new PackageVerificationError("INTEGRITY_MISSING", "the integrity block lists no files", MANIFEST_FILE);
26075
+ }
26076
+ const out = {};
26077
+ for (const [p, h] of Object.entries(files)) {
26078
+ if (typeof h !== "string" || !HEX_RE.test(h)) throw new PackageVerificationError("MANIFEST_INVALID", `the recorded hash for ${p} is not a sha256 hex digest`, MANIFEST_FILE);
26079
+ out[p] = h;
26080
+ }
26081
+ return { algorithm: "sha256", files: out };
26082
+ }
26083
+ async function openPdpkg(input, expect = {}) {
26084
+ if (input.length > MAX_PACKAGE_BYTES) {
26085
+ throw new PackageVerificationError("TOO_LARGE", `the package is ${input.length} bytes (max ${MAX_PACKAGE_BYTES})`);
26086
+ }
26087
+ const bytes = new Uint8Array(input);
26088
+ const digest = await archiveDigest(bytes);
26089
+ if (expect.digest !== void 0 && expect.digest !== digest) {
26090
+ throw new PackageVerificationError("DIGEST_MISMATCH", `the package is ${digest}, expected ${expect.digest}`);
26091
+ }
26092
+ const entries = await readArchive(bytes);
26093
+ for (const name of entries.keys()) {
26094
+ const folded = name.toLowerCase();
26095
+ if (folded === RESERVED_MANIFEST || folded === MANIFEST_FILE && name !== MANIFEST_FILE) {
26096
+ throw new PackageVerificationError("MANIFEST_RESERVED", `the package holds a root ${name}; the manifest is prompd.json only`, name);
25671
26097
  }
25672
- if (entry.name.startsWith("/") || /(^|\/)\.\.(\/|$)/.test(entry.name)) {
25673
- throw new Error(`Security violation: path traversal in entry: ${entry.name}`);
26098
+ if (RESERVED_LAYOUT.has(folded)) {
26099
+ throw new PackageVerificationError("MANIFEST_RESERVED", `the package holds a root ${name}, a name the install writes itself`, name);
25674
26100
  }
25675
- if (isSymlinkEntry(entry.unixPermissions)) {
25676
- throw new Error(`Security violation: symlink entry in archive: ${entry.name}`);
26101
+ }
26102
+ const manifestBytes = entries.get(MANIFEST_FILE);
26103
+ if (!manifestBytes) throw new PackageVerificationError("MANIFEST_MISSING", "the package has no prompd.json", MANIFEST_FILE);
26104
+ const parsed = parseManifest(manifestBytes);
26105
+ const integrity = integrityOf(parsed.integrity);
26106
+ const files = /* @__PURE__ */ new Map();
26107
+ for (const [p, b] of entries) if (p !== MANIFEST_FILE) files.set(p, b);
26108
+ for (const p of files.keys()) {
26109
+ if (!Object.prototype.hasOwnProperty.call(integrity.files, p)) {
26110
+ throw new PackageVerificationError("FILE_UNLISTED", `${p} is not listed in the integrity block`, p);
25677
26111
  }
25678
- if (entry.dir || isBinaryAsset(entry.name)) continue;
25679
- const bytes = await entry.async("uint8array");
25680
- if (bytes.length > MAX_FILE_SIZE_IN_ZIP) {
25681
- throw new Error(`File too large in package: ${entry.name} (${bytes.length} bytes, max ${MAX_FILE_SIZE_IN_ZIP})`);
26112
+ }
26113
+ for (const p of Object.keys(integrity.files)) {
26114
+ if (!files.has(p)) throw new PackageVerificationError("FILE_MISSING", `${p} is listed in the integrity block but not in the package`, p);
26115
+ }
26116
+ for (const [p, b] of files) {
26117
+ if (await sha256Hex(b) !== integrity.files[p]) {
26118
+ throw new PackageVerificationError("HASH_MISMATCH", `${p} does not match its recorded hash`, p);
25682
26119
  }
25683
- total += bytes.length;
25684
- if (total > MAX_TOTAL_EXTRACTED_SIZE) {
25685
- throw new Error(`Package total decompressed size exceeds limit (${MAX_TOTAL_EXTRACTED_SIZE} bytes). Possible decompression bomb.`);
26120
+ }
26121
+ const manifest = { ...parsed, integrity };
26122
+ const agentRefs = manifest.type === "agent" ? checkAgentPackage(manifest, files) : void 0;
26123
+ if (expect.name !== void 0 && manifest.name !== expect.name) {
26124
+ throw new PackageVerificationError("NAME_MISMATCH", `asked for ${expect.name}, the package is ${manifest.name}`);
26125
+ }
26126
+ if (expect.range !== void 0 && !import_semver.default.satisfies(manifest.version, expect.range)) {
26127
+ throw new PackageVerificationError("VERSION_MISMATCH", `asked for ${expect.range}, the package is ${manifest.version}`);
26128
+ }
26129
+ return { manifest, manifestBytes, files, digest, ...agentRefs ? { agentRefs } : {} };
26130
+ }
26131
+ function isBinaryAsset(name) {
26132
+ const dot = name.lastIndexOf(".");
26133
+ return dot >= 0 && BINARY_ASSET_EXT.has(name.slice(dot + 1).toLowerCase());
26134
+ }
26135
+ async function extractPdpkg(buffer, expect = {}) {
26136
+ const pkg = await openPdpkg(buffer, expect);
26137
+ const out = /* @__PURE__ */ new Map();
26138
+ out.set("prompd.json", textDecoder.decode(pkg.manifestBytes));
26139
+ for (const [p, b] of pkg.files) {
26140
+ if (isBinaryAsset(p)) continue;
26141
+ try {
26142
+ out.set(p, textDecoder.decode(b));
26143
+ } catch {
26144
+ throw new Error(`${p} in ${pkg.manifest.name}@${pkg.manifest.version} is not UTF-8 text`);
25686
26145
  }
25687
- out.set(entry.name, pdpkgDecoder.decode(bytes));
25688
26146
  }
25689
26147
  return out;
25690
26148
  }
@@ -25734,10 +26192,29 @@ function createCoreStages() {
25734
26192
  new CodeGenerationStage()
25735
26193
  ];
25736
26194
  }
25737
- var yaml, import_semver, nunjucks, import_jszip, PrompdParser, PACKAGE_TYPE_DIRS, VALID_PACKAGE_TYPES, PrompdError, ParseError, ValidationError, CompilationError, SecurityError, CompilationContext, DEFAULT_SECURITY_CONFIG, PROMPD_EXTENSIONS, CompilerPipeline, LexicalAnalysisStage, DependencyResolutionStage, SemanticAnalysisStage, _SectionOverrideProcessor, SectionOverrideProcessor, EXTENSION_TO_LANGUAGE_ALIASES, globalIncludeStacks, compilationCounter, PrompdLoader, TemplateProcessingStage, MarkdownFormatter, OpenAIFormatter, AnthropicFormatter, CodeGenerationStage, BINARY_ASSET_EXT, MAX_FILE_SIZE_IN_ZIP, MAX_TOTAL_EXTRACTED_SIZE, pdpkgDecoder, _MemoryFileSystem, MemoryFileSystem, HybridFileSystem, MAX_PACKAGE_SIZE, PrompdCompiler, ASSIGNMENT_OPS, OP_CONSTRUCTS, OPS;
26195
+ function same(a, b) {
26196
+ if (a.length !== b.length) return false;
26197
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
26198
+ return true;
26199
+ }
26200
+ async function verifyInstalled(read, expectedDigest, expect = {}) {
26201
+ const archive = await read(ARCHIVE_COPY);
26202
+ if (!archive) {
26203
+ throw new PackageVerificationError("FILE_MISSING", `${ARCHIVE_COPY} is missing, so this install cannot be verified; reinstall the package`, ARCHIVE_COPY);
26204
+ }
26205
+ const pkg = await openPdpkg(archive, { ...expect, digest: expectedDigest });
26206
+ for (const [p, b] of pkg.files) {
26207
+ const onDisk = await read(p);
26208
+ if (!onDisk) throw new PackageVerificationError("FILE_MISSING", `${p} is missing from the installed package`, p);
26209
+ if (!same(onDisk, b)) throw new PackageVerificationError("HASH_MISMATCH", `${p} does not match its recorded hash`, p);
26210
+ }
26211
+ return pkg;
26212
+ }
26213
+ var yaml, import_yaml, import_semver, nunjucks, import_jszip, PrompdParser, PACKAGE_TYPE_DIRS, VALID_PACKAGE_TYPES, PrompdError, ParseError, ValidationError, CompilationError, SecurityError, CompilationContext, DEFAULT_SECURITY_CONFIG, PROMPD_EXTENSIONS, CompilerPipeline, LexicalAnalysisStage, DependencyResolutionStage, SemanticAnalysisStage, _SectionOverrideProcessor, SectionOverrideProcessor, EXTENSION_TO_LANGUAGE_ALIASES, globalIncludeStacks, compilationCounter, PrompdLoader, TemplateProcessingStage, MarkdownFormatter, OpenAIFormatter, AnthropicFormatter, CodeGenerationStage, PackageVerificationError, ARCHIVE_LIMITS, EOCD_SIG, CENTRAL_SIG, EOCD_LEN, CENTRAL_LEN, LOCAL_SIG, LOCAL_LEN, UNICODE_PATH_FIELD, WINDOWS_DEVICE_RE, NOT_A_ZIP, BIDI_RE, nameDecoder, PACKAGE_NAME_RE, decoder, PROTO_KEYS, AGENT_PACKAGE_FILES, decoder2, MCP_PREFIX, MCP_WIRE_PREFIX, GLOB_RE, NAMED_MCP_RE, ARCHIVE_COPY, META_FILE, MAX_PACKAGE_BYTES, MANIFEST_FILE, RESERVED_MANIFEST, RESERVED_LAYOUT, HEX_RE, BINARY_ASSET_EXT, textDecoder, MemoryFileSystem, HybridFileSystem, INSTALL_LIMITS, textDecoder2, PrompdCompiler, ASSIGNMENT_OPS, OP_CONSTRUCTS, OPS, RESERVED_LAYOUT2, encoder;
25738
26214
  var init_dist = __esm({
25739
- "../../node_modules/.pnpm/@prompd+core@0.6.0/node_modules/@prompd/core/dist/index.js"() {
26215
+ "../../node_modules/.pnpm/@prompd+core@0.7.0/node_modules/@prompd/core/dist/index.js"() {
25740
26216
  yaml = __toESM(require_dist(), 1);
26217
+ import_yaml = __toESM(require_dist(), 1);
25741
26218
  import_semver = __toESM(require_semver2(), 1);
25742
26219
  nunjucks = __toESM(require_nunjucks(), 1);
25743
26220
  import_jszip = __toESM(require_lib4(), 1);
@@ -25874,7 +26351,7 @@ var init_dist = __esm({
25874
26351
  "package": "packages",
25875
26352
  "workflow": "workflows",
25876
26353
  "skill": "skills",
25877
- "node-template": "templates"
26354
+ "agent": "agents"
25878
26355
  };
25879
26356
  VALID_PACKAGE_TYPES = Object.keys(PACKAGE_TYPE_DIRS);
25880
26357
  PrompdError = class _PrompdError extends Error {
@@ -27257,13 +27734,13 @@ ${yamlContent}` : yamlContent;
27257
27734
  const line = lines[i].trim();
27258
27735
  if (!line) continue;
27259
27736
  const values = this.parseCsvLine(line);
27260
- const record = {};
27737
+ const record3 = {};
27261
27738
  for (let j = 0; j < headers.length; j++) {
27262
27739
  const header = headers[j].trim();
27263
27740
  const value = values[j]?.trim() ?? "";
27264
- record[header] = value;
27741
+ record3[header] = value;
27265
27742
  }
27266
- records.push(record);
27743
+ records.push(record3);
27267
27744
  }
27268
27745
  return records;
27269
27746
  }
@@ -27272,25 +27749,25 @@ ${yamlContent}` : yamlContent;
27272
27749
  */
27273
27750
  parseCsvLine(line) {
27274
27751
  const result = [];
27275
- let current = "";
27752
+ let current2 = "";
27276
27753
  let inQuotes = false;
27277
27754
  for (let i = 0; i < line.length; i++) {
27278
27755
  const char = line[i];
27279
27756
  if (char === '"') {
27280
27757
  if (inQuotes && line[i + 1] === '"') {
27281
- current += '"';
27758
+ current2 += '"';
27282
27759
  i++;
27283
27760
  } else {
27284
27761
  inQuotes = !inQuotes;
27285
27762
  }
27286
27763
  } else if (char === "," && !inQuotes) {
27287
- result.push(current);
27288
- current = "";
27764
+ result.push(current2);
27765
+ current2 = "";
27289
27766
  } else {
27290
- current += char;
27767
+ current2 += char;
27291
27768
  }
27292
27769
  }
27293
- result.push(current);
27770
+ result.push(current2);
27294
27771
  return result;
27295
27772
  }
27296
27773
  async process(context) {
@@ -27418,8 +27895,8 @@ ${yamlContent}` : yamlContent;
27418
27895
  return content;
27419
27896
  }
27420
27897
  if (parentData.content) {
27421
- const parentDir = fs6.dirname(parentFile);
27422
- parentData.content = this.resolveIncludePaths(parentData.content, parentDir);
27898
+ const parentDir2 = fs6.dirname(parentFile);
27899
+ parentData.content = this.resolveIncludePaths(parentData.content, parentDir2);
27423
27900
  }
27424
27901
  const overrides = context.metadata?.override || {};
27425
27902
  if (parentData.content || content) {
@@ -27972,7 +28449,7 @@ ${content}` : parentData.content;
27972
28449
  async validateParentFileReferences(context, metadata, fs6, parentFile) {
27973
28450
  if (!metadata) return;
27974
28451
  const metadataAsRecord = metadata;
27975
- const parentDir = fs6.dirname(parentFile);
28452
+ const parentDir2 = fs6.dirname(parentFile);
27976
28453
  const fileFields = ["system", "task", "user", "assistant", "response", "output", "context"];
27977
28454
  for (const field of fileFields) {
27978
28455
  const fieldValue = metadataAsRecord[field];
@@ -27980,7 +28457,7 @@ ${content}` : parentData.content;
27980
28457
  const refs = Array.isArray(fieldValue) ? fieldValue.filter((v) => typeof v === "string") : typeof fieldValue === "string" ? [fieldValue] : [];
27981
28458
  for (const ref of refs) {
27982
28459
  if (!ref.startsWith("./") && !ref.startsWith("../")) continue;
27983
- const resolvedPath = fs6.resolve(parentDir, ref);
28460
+ const resolvedPath = fs6.resolve(parentDir2, ref);
27984
28461
  const exists = await Promise.resolve(fs6.exists(resolvedPath));
27985
28462
  if (!exists) {
27986
28463
  const location = context.findLocation(/inherits:/);
@@ -28315,6 +28792,49 @@ ${firstUserMsg.content}`;
28315
28792
  return "Code Generation";
28316
28793
  }
28317
28794
  };
28795
+ PackageVerificationError = class extends Error {
28796
+ constructor(code3, message, path) {
28797
+ super(message);
28798
+ this.name = "PackageVerificationError";
28799
+ this.code = code3;
28800
+ if (path !== void 0) this.path = path;
28801
+ }
28802
+ };
28803
+ ARCHIVE_LIMITS = {
28804
+ maxEntries: 2e3,
28805
+ maxFileBytes: 10 * 1024 * 1024,
28806
+ maxTotalBytes: 500 * 1024 * 1024,
28807
+ maxRatio: 100,
28808
+ maxNameLength: 512,
28809
+ maxSegments: 24
28810
+ };
28811
+ EOCD_SIG = 101010256;
28812
+ CENTRAL_SIG = 33639248;
28813
+ EOCD_LEN = 22;
28814
+ CENTRAL_LEN = 46;
28815
+ LOCAL_SIG = 67324752;
28816
+ LOCAL_LEN = 30;
28817
+ UNICODE_PATH_FIELD = 28789;
28818
+ WINDOWS_DEVICE_RE = /^(con|prn|aux|nul|conin\$|conout\$|com[0-9\u00b9\u00b2\u00b3]|lpt[0-9\u00b9\u00b2\u00b3])$/i;
28819
+ NOT_A_ZIP = "the package is not a readable zip";
28820
+ BIDI_RE = /[\u200e\u200f\u202a-\u202e\u2066-\u2069]/;
28821
+ nameDecoder = new TextDecoder("utf-8", { fatal: true });
28822
+ PACKAGE_NAME_RE = /^@(?!\.+\/)[a-z0-9._-]+\/(?!\.+$)[a-z0-9._-]+$/;
28823
+ decoder = new TextDecoder("utf-8", { fatal: true });
28824
+ PROTO_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
28825
+ AGENT_PACKAGE_FILES = ["AGENT.md", "SOUL.md", "PERSONA.md", "POLICY.yaml"];
28826
+ decoder2 = new TextDecoder("utf-8", { fatal: true });
28827
+ MCP_PREFIX = "mcp:";
28828
+ MCP_WIRE_PREFIX = "mcp_";
28829
+ GLOB_RE = /[*?]/;
28830
+ NAMED_MCP_RE = /^mcp:([^*?/]+)\//;
28831
+ ARCHIVE_COPY = ".package.pdpkg";
28832
+ META_FILE = ".prmdmeta";
28833
+ MAX_PACKAGE_BYTES = 50 * 1024 * 1024;
28834
+ MANIFEST_FILE = "prompd.json";
28835
+ RESERVED_MANIFEST = "manifest.json";
28836
+ RESERVED_LAYOUT = new Set([ARCHIVE_COPY, META_FILE].map((n) => n.toLowerCase()));
28837
+ HEX_RE = /^[0-9a-f]{64}$/;
28318
28838
  BINARY_ASSET_EXT = /* @__PURE__ */ new Set([
28319
28839
  "png",
28320
28840
  "jpg",
@@ -28350,10 +28870,8 @@ ${firstUserMsg.content}`;
28350
28870
  "mov",
28351
28871
  "avi"
28352
28872
  ]);
28353
- MAX_FILE_SIZE_IN_ZIP = 10 * 1024 * 1024;
28354
- MAX_TOTAL_EXTRACTED_SIZE = 500 * 1024 * 1024;
28355
- pdpkgDecoder = new TextDecoder();
28356
- _MemoryFileSystem = class _MemoryFileSystem2 {
28873
+ textDecoder = new TextDecoder("utf-8", { fatal: true });
28874
+ MemoryFileSystem = class {
28357
28875
  constructor(files = {}) {
28358
28876
  this.files = /* @__PURE__ */ new Map();
28359
28877
  for (const [filePath, content] of Object.entries(files)) {
@@ -28423,18 +28941,19 @@ ${firstUserMsg.content}`;
28423
28941
  /**
28424
28942
  * Extract a `.pdpkg` (ZIP) buffer into memory under getPackagePath(name, ver).
28425
28943
  *
28426
- * Uses JSZip — isomorphic (browser + Node) — so this is the SINGLE package-ingest
28427
- * path for every host (replacing the CLI's Node-only adm-zip subclass and the
28428
- * skill installer's ad-hoc unzip). Text files only: binary assets aren't
28944
+ * Verifies the archive through openPdpkg (isomorphic, browser + Node), so this is
28945
+ * the SINGLE package-ingest path for every host (replacing the CLI's Node-only
28946
+ * adm-zip subclass and the skill installer's ad-hoc unzip). Text files only: binary assets aren't
28429
28947
  * representable in the string-backed FS, so they're skipped (a `using:` package's
28430
28948
  * .prmd/.md/.json/.yaml is what matters for compilation). Validates entry paths
28431
28949
  * can't escape the package directory.
28432
28950
  */
28433
- async addPackage(packageName, version2, packageBuffer) {
28434
- if (packageBuffer.length > _MemoryFileSystem2.MAX_PACKAGE_SIZE) {
28435
- throw new Error(`Package too large: ${packageBuffer.length} bytes (max ${_MemoryFileSystem2.MAX_PACKAGE_SIZE})`);
28436
- }
28437
- const files = await extractPdpkg(packageBuffer);
28951
+ async addPackage(packageName, version2, packageBuffer, expect = {}) {
28952
+ const files = await extractPdpkg(packageBuffer, {
28953
+ name: packageName,
28954
+ ...import_semver.default.validRange(version2) !== null ? { range: version2 } : {},
28955
+ ...expect
28956
+ });
28438
28957
  const packagePath = this.getPackagePath(packageName, version2);
28439
28958
  const packagePrefix = this.normalizePath(packagePath.endsWith("/") ? packagePath : packagePath + "/");
28440
28959
  const packageRoot = this.normalizePath(packagePath);
@@ -28476,8 +28995,6 @@ ${firstUserMsg.content}`;
28476
28995
  return toRelKey(filePath);
28477
28996
  }
28478
28997
  };
28479
- _MemoryFileSystem.MAX_PACKAGE_SIZE = 50 * 1024 * 1024;
28480
- MemoryFileSystem = _MemoryFileSystem;
28481
28998
  HybridFileSystem = class {
28482
28999
  constructor(files = {}, backend) {
28483
29000
  this.mem = new MemoryFileSystem(files);
@@ -28497,8 +29014,8 @@ ${firstUserMsg.content}`;
28497
29014
  }
28498
29015
  /** Ingest a `.pdpkg` (ZIP) buffer into the in-memory layer, so package files are
28499
29016
  * served synchronously alongside the workspace sources. */
28500
- addPackage(packageName, version2, packageBuffer) {
28501
- return this.mem.addPackage(packageName, version2, packageBuffer);
29017
+ addPackage(packageName, version2, packageBuffer, expect = {}) {
29018
+ return this.mem.addPackage(packageName, version2, packageBuffer, expect);
28502
29019
  }
28503
29020
  exists(filePath) {
28504
29021
  if (this.mem.exists(filePath)) return true;
@@ -28535,7 +29052,15 @@ ${firstUserMsg.content}`;
28535
29052
  return toRelKey(filePath);
28536
29053
  }
28537
29054
  };
28538
- MAX_PACKAGE_SIZE = 50 * 1024 * 1024;
29055
+ INSTALL_LIMITS = {
29056
+ /** Dependencies one manifest may declare. */
29057
+ maxDependencies: 100,
29058
+ /** Packages in one install tree, the requested package included. */
29059
+ maxPackages: 500,
29060
+ /** Unpacked bytes across the whole tree (1 GiB). */
29061
+ maxTotalBytes: 1024 * 1024 * 1024
29062
+ };
29063
+ textDecoder2 = new TextDecoder("utf-8", { fatal: true });
28539
29064
  PrompdCompiler = class {
28540
29065
  constructor(options = {}) {
28541
29066
  this.securityConfig = options.securityConfig || DEFAULT_SECURITY_CONFIG;
@@ -28627,6 +29152,8 @@ ${firstUserMsg.content}`;
28627
29152
  "~",
28628
29153
  ";"
28629
29154
  ].sort((a, b) => b.length - a.length);
29155
+ RESERVED_LAYOUT2 = new Set([ARCHIVE_COPY, META_FILE].map((n) => n.toLowerCase()));
29156
+ encoder = new TextEncoder();
28630
29157
  }
28631
29158
  });
28632
29159
 
@@ -28870,11 +29397,11 @@ async function ensurePrivateDir(dir) {
28870
29397
  } catch {
28871
29398
  }
28872
29399
  }
28873
- async function writePrivate(abs, text) {
29400
+ async function writePrivate(abs, text2) {
28874
29401
  await fs5.mkdir(dirname4(abs), { recursive: true, mode: 448 });
28875
29402
  const tmp = join5(dirname4(abs), `.${basename3(abs)}.tmp-${randomBytes2(8).toString("hex")}`);
28876
29403
  try {
28877
- await fs5.writeFile(tmp, text, { encoding: "utf8", mode: 384 });
29404
+ await fs5.writeFile(tmp, text2, { encoding: "utf8", mode: 384 });
28878
29405
  try {
28879
29406
  await fs5.chmod(tmp, 384);
28880
29407
  } catch {
@@ -28895,8 +29422,8 @@ function fileTextStore(abs) {
28895
29422
  throw e;
28896
29423
  }
28897
29424
  },
28898
- write: (text) => writePrivate(abs, text),
28899
- preserve: (text) => writePrivate(`${abs}.bad`, text)
29425
+ write: (text2) => writePrivate(abs, text2),
29426
+ preserve: (text2) => writePrivate(`${abs}.bad`, text2)
28900
29427
  };
28901
29428
  }
28902
29429
  async function realOrAncestor(abs) {
@@ -28983,6 +29510,14 @@ var init_approvalsStore = __esm({
28983
29510
  });
28984
29511
 
28985
29512
  // ../tools-node/deviceLogin.ts
29513
+ function verificationLink(dc) {
29514
+ const base = dc.verification_uri;
29515
+ const complete = dc.verification_uri_complete;
29516
+ if (typeof complete === "string" && complete.startsWith(base) && (complete[base.length] === "?" || complete[base.length] === "&")) {
29517
+ return complete;
29518
+ }
29519
+ return `${base}${base.includes("?") ? "&" : "?"}code=${encodeURIComponent(dc.user_code)}`;
29520
+ }
28986
29521
  function deadlineSignal(ms, outer) {
28987
29522
  const ac = new AbortController();
28988
29523
  const onOuter = () => ac.abort();
@@ -29037,11 +29572,11 @@ async function deviceLogin(opts) {
29037
29572
  body: JSON.stringify(body),
29038
29573
  signal: opts.signal
29039
29574
  });
29040
- const text = await res.text();
29575
+ const text2 = await res.text();
29041
29576
  try {
29042
- return JSON.parse(text);
29577
+ return JSON.parse(text2);
29043
29578
  } catch {
29044
- const looksLikeHtml = /^\s*</.test(text);
29579
+ const looksLikeHtml = /^\s*</.test(text2);
29045
29580
  throw new Error(
29046
29581
  `${url} answered ${res.status} with ${looksLikeHtml ? "an HTML page" : "a non-JSON body"}, not JSON.` + (res.status === 404 ? `
29047
29582
  That usually means --base is wrong. The device endpoints live under /api \u2014 try --base ${base.replace(/\/api$/, "")}/api` : "")
@@ -29050,7 +29585,7 @@ async function deviceLogin(opts) {
29050
29585
  };
29051
29586
  const dc = await post("/oauth/device/code", { client_id: "corenel-cli", scope: "agent pair" });
29052
29587
  if (!dc.device_code) throw new Error("device authorization failed");
29053
- (opts.open ?? defaultOpen)(dc.verification_uri, dc.user_code);
29588
+ (opts.open ?? defaultOpen)(verificationLink(dc), dc.user_code);
29054
29589
  let interval = opts.pollMs ?? Math.max(MIN_POLL_MS, (dc.interval ?? 5) * 1e3);
29055
29590
  const lifetimeMs = (typeof dc.expires_in === "number" && dc.expires_in > 0 ? dc.expires_in : DEFAULT_LIFETIME_S) * 1e3;
29056
29591
  const deadline = Date.now() + lifetimeMs;
@@ -31239,7 +31774,7 @@ var require_extension = __commonJS({
31239
31774
  if (dest[name] === void 0) dest[name] = [elem];
31240
31775
  else dest[name].push(elem);
31241
31776
  }
31242
- function parse3(header) {
31777
+ function parse4(header) {
31243
31778
  const offers = /* @__PURE__ */ Object.create(null);
31244
31779
  let params = /* @__PURE__ */ Object.create(null);
31245
31780
  let mustUnescape = false;
@@ -31379,7 +31914,7 @@ var require_extension = __commonJS({
31379
31914
  }).join(", ");
31380
31915
  }).join(", ");
31381
31916
  }
31382
- module.exports = { format, parse: parse3 };
31917
+ module.exports = { format, parse: parse4 };
31383
31918
  }
31384
31919
  });
31385
31920
 
@@ -31413,7 +31948,7 @@ var require_websocket = __commonJS({
31413
31948
  var {
31414
31949
  EventTarget: { addEventListener, removeEventListener }
31415
31950
  } = require_event_target();
31416
- var { format, parse: parse3 } = require_extension();
31951
+ var { format, parse: parse4 } = require_extension();
31417
31952
  var { toBuffer } = require_buffer_util();
31418
31953
  var kAborted = Symbol("kAborted");
31419
31954
  var protocolVersions = [8, 13];
@@ -32090,7 +32625,7 @@ var require_websocket = __commonJS({
32090
32625
  }
32091
32626
  let extensions;
32092
32627
  try {
32093
- extensions = parse3(secWebSocketExtensions);
32628
+ extensions = parse4(secWebSocketExtensions);
32094
32629
  } catch (err) {
32095
32630
  const message = "Invalid Sec-WebSocket-Extensions header";
32096
32631
  abortHandshake(websocket, socket, message);
@@ -32382,7 +32917,7 @@ var require_subprotocol = __commonJS({
32382
32917
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/subprotocol.js"(exports, module) {
32383
32918
  "use strict";
32384
32919
  var { tokenChars } = require_validation();
32385
- function parse3(header) {
32920
+ function parse4(header) {
32386
32921
  const protocols = /* @__PURE__ */ new Set();
32387
32922
  let start = -1;
32388
32923
  let end = -1;
@@ -32418,7 +32953,7 @@ var require_subprotocol = __commonJS({
32418
32953
  protocols.add(protocol);
32419
32954
  return protocols;
32420
32955
  }
32421
- module.exports = { parse: parse3 };
32956
+ module.exports = { parse: parse4 };
32422
32957
  }
32423
32958
  });
32424
32959
 
@@ -32846,7 +33381,7 @@ function configWorkspaceRoot(base) {
32846
33381
  import { FileRecallStore, UNATTACHED_SESSION } from "@corenel/harness/sessions/fileRecallStore";
32847
33382
  import { makeSessionFoldStorage } from "@corenel/harness/sessions/foldStorage";
32848
33383
  import { makeSummarizer } from "@corenel/harness/core/summarize";
32849
- import { stateDirName as stateDirName7, sessionsRoot, isSourceRun } from "@corenel/protocol";
33384
+ import { stateDirName as stateDirName6, sessionsRoot, isSourceRun } from "@corenel/protocol";
32850
33385
  import { PermissionService as PermissionService6 } from "@corenel/harness/guardrail/permission-service";
32851
33386
 
32852
33387
  // src/nodeContext.ts
@@ -32948,6 +33483,8 @@ var crew_exports = {};
32948
33483
  __export(crew_exports, {
32949
33484
  AUTONOMY_TOOLS: () => AUTONOMY_TOOLS,
32950
33485
  CHECK_IN_BLOCK: () => CHECK_IN_BLOCK,
33486
+ COMMAND_CAPABILITIES: () => COMMAND_CAPABILITIES,
33487
+ CREW_DEFINITION_MARKERS: () => CREW_DEFINITION_MARKERS,
32951
33488
  CREW_EXCLUDED_TOOLS: () => CREW_EXCLUDED_TOOLS,
32952
33489
  CREW_SEG: () => CREW_SEG,
32953
33490
  DEPLOYMENT_FILE: () => DEPLOYMENT_FILE,
@@ -32957,16 +33494,23 @@ __export(crew_exports, {
32957
33494
  DONT_BLANK: () => DONT_BLANK,
32958
33495
  DONT_CONTROL: () => DONT_CONTROL,
32959
33496
  DONT_TOO_LONG: () => DONT_TOO_LONG,
33497
+ MANAGED_IN_SESSION_REFUSED: () => MANAGED_IN_SESSION_REFUSED,
33498
+ MANAGED_LOCKED: () => MANAGED_LOCKED,
33499
+ MANAGED_UNREADABLE: () => MANAGED_UNREADABLE,
33500
+ MANAGED_UNTRUSTED: () => MANAGED_UNTRUSTED,
32960
33501
  MAX_ROOM_BRIEF: () => MAX_ROOM_BRIEF,
33502
+ MCP_DENY_ALL: () => MCP_DENY_ALL,
32961
33503
  MEMORY_USERS_DIR: () => MEMORY_USERS_DIR,
32962
33504
  NOT_IN_YOUR_MEMORY: () => NOT_IN_YOUR_MEMORY,
32963
33505
  NO_ASKER_MEMORY_READ_ONLY: () => NO_ASKER_MEMORY_READ_ONLY,
33506
+ NO_TOOL_SENTINEL: () => NO_TOOL_SENTINEL,
32964
33507
  PROJECT_MARKER_FILE: () => PROJECT_MARKER_FILE,
32965
33508
  ROOM_KIND: () => ROOM_KIND,
32966
33509
  ROOM_MEMORY_READ_ONLY: () => ROOM_MEMORY_READ_ONLY,
32967
33510
  RUN_STATUS_VALUES: () => RUN_STATUS_VALUES,
32968
33511
  RoomReadError: () => RoomReadError,
32969
33512
  RoomStore: () => RoomStore,
33513
+ accessAllows: () => accessAllows,
32970
33514
  advance: () => advance,
32971
33515
  agentMemoryRoot: () => agentMemoryRoot,
32972
33516
  allowedAutonomy: () => allowedAutonomy,
@@ -32979,7 +33523,9 @@ __export(crew_exports, {
32979
33523
  callCandidates: () => callCandidates,
32980
33524
  callReach: () => callReach,
32981
33525
  closeRoomByHuman: () => closeRoomByHuman,
33526
+ copyCrewAgentAt: () => copyCrewAgentAt,
32982
33527
  crewAgentDir: () => crewAgentDir,
33528
+ crewAgentPresent: () => crewAgentPresent,
32983
33529
  crewAgentSessionsRoot: () => crewAgentSessionsRoot,
32984
33530
  crewBudgetConstraints: () => crewBudgetConstraints,
32985
33531
  crewListEntry: () => crewListEntry,
@@ -32994,16 +33540,22 @@ __export(crew_exports, {
32994
33540
  deploymentRootFor: () => deploymentRootFor,
32995
33541
  dontsProblems: () => dontsProblems,
32996
33542
  editFindingByHuman: () => editFindingByHuman,
33543
+ egressIsEmpty: () => egressIsEmpty,
32997
33544
  emptyDeployment: () => emptyDeployment,
32998
33545
  encodeRoomLine: () => encodeRoomLine,
32999
33546
  enforcedLevel: () => enforcedLevel,
33547
+ filterDefinition: () => filterDefinition,
33000
33548
  findingsPath: () => findingsPath,
33001
33549
  finishTurn: () => finishTurn,
33002
33550
  foldRoom: () => foldRoom,
33003
33551
  globMatch: () => globMatch,
33004
33552
  grantOfferedTools: () => grantOfferedTools,
33553
+ grantsCommandTools: () => grantsCommandTools,
33005
33554
  interjectHuman: () => interjectHuman,
33555
+ intersectAllowList: () => intersectAllowList,
33006
33556
  isAutonomyPreset: () => isAutonomyPreset,
33557
+ isManaged: () => isManaged,
33558
+ isManagedOnDisk: () => isManagedOnDisk,
33007
33559
  isOrchestrator: () => isOrchestrator,
33008
33560
  isRoomSafeTool: () => isRoomSafeTool,
33009
33561
  isSafeProjectPath: () => isSafeProjectPath,
@@ -33014,18 +33566,26 @@ __export(crew_exports, {
33014
33566
  listCrewSummariesAt: () => listCrewSummariesAt,
33015
33567
  loadCrewAgentAt: () => loadCrewAgentAt,
33016
33568
  loadCrewAgentAtIfExists: () => loadCrewAgentAtIfExists,
33569
+ loadCrewAgentAtIfPresent: () => loadCrewAgentAtIfPresent,
33017
33570
  loadCrewSummaryAt: () => loadCrewSummaryAt,
33018
33571
  makeAgentMemoryProvider: () => makeAgentMemoryProvider,
33019
33572
  makeCrewTurnRuntime: () => makeCrewTurnRuntime,
33020
33573
  makePartitionedMemoryProvider: () => makePartitionedMemoryProvider,
33021
33574
  makeReadOnlyMemoryProvider: () => makeReadOnlyMemoryProvider,
33575
+ managedCap: () => managedCap,
33576
+ managedClaimOf: () => managedClaimOf,
33577
+ managedLockReason: () => managedLockReason,
33578
+ managedTrusted: () => managedTrusted,
33022
33579
  matchFileChange: () => matchFileChange,
33023
33580
  matchRunComplete: () => matchRunComplete,
33581
+ narrowDefinition: () => narrowDefinition,
33024
33582
  newCrewDraft: () => newCrewDraft,
33025
33583
  nextCronAfter: () => nextCronAfter,
33026
33584
  normalizeRunStatus: () => normalizeRunStatus,
33585
+ offersCommandTools: () => offersCommandTools,
33027
33586
  openLineOf: () => openLineOf,
33028
33587
  openRoom: () => openRoom,
33588
+ packagePolicyModels: () => packagePolicyModels,
33029
33589
  parseCron: () => parseCron,
33030
33590
  parseDeployment: () => parseDeployment,
33031
33591
  parseFrontmatter: () => parseFrontmatter,
@@ -33037,6 +33597,8 @@ __export(crew_exports, {
33037
33597
  projectMarkerPath: () => projectMarkerPath,
33038
33598
  readAutonomy: () => readAutonomy,
33039
33599
  readCrewListing: () => readCrewListing,
33600
+ readManagedEntry: () => readManagedEntry,
33601
+ readManagedRef: () => readManagedRef,
33040
33602
  registerCrewPolicy: () => registerCrewPolicy,
33041
33603
  resolveCallSet: () => resolveCallSet,
33042
33604
  resolveCrewModel: () => resolveCrewModel,
@@ -33051,26 +33613,29 @@ __export(crew_exports, {
33051
33613
  runRoom: () => runRoom,
33052
33614
  runTurnRuntime: () => runTurnRuntime,
33053
33615
  serializeDeployment: () => serializeDeployment,
33616
+ setDefinitionFilter: () => setDefinitionFilter,
33617
+ setManagedTrust: () => setManagedTrust,
33054
33618
  splitRunStatus: () => splitRunStatus,
33055
33619
  stampAuthor: () => stampAuthor,
33056
33620
  stringArray: () => stringArray,
33057
33621
  takeTurn: () => takeTurn,
33058
33622
  tightenAutonomy: () => tightenAutonomy,
33059
33623
  turnCosts: () => turnCosts,
33624
+ unsandboxedCommandsFact: () => unsandboxedCommandsFact,
33060
33625
  userMemoryRoot: () => userMemoryRoot,
33061
33626
  validateRoomRequest: () => validateRoomRequest,
33062
33627
  writeCrewAgentAt: () => writeCrewAgentAt
33063
33628
  });
33064
33629
 
33065
33630
  // ../crew/frontmatter.ts
33066
- var import_yaml = __toESM(require_dist(), 1);
33631
+ var import_yaml2 = __toESM(require_dist(), 1);
33067
33632
  var FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
33068
- function parseFrontmatter(text) {
33069
- const m = text.match(FRONTMATTER);
33070
- if (!m) return { meta: {}, body: text };
33633
+ function parseFrontmatter(text2) {
33634
+ const m = text2.match(FRONTMATTER);
33635
+ if (!m) return { meta: {}, body: text2 };
33071
33636
  let meta = {};
33072
33637
  try {
33073
- const parsed = import_yaml.default.parse(m[1]);
33638
+ const parsed = import_yaml2.default.parse(m[1]);
33074
33639
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
33075
33640
  meta = parsed;
33076
33641
  }
@@ -33081,7 +33646,7 @@ function parseFrontmatter(text) {
33081
33646
  }
33082
33647
 
33083
33648
  // ../crew/policy.ts
33084
- var import_yaml2 = __toESM(require_dist(), 1);
33649
+ var import_yaml3 = __toESM(require_dist(), 1);
33085
33650
  var LEVELS = ["allow", "ask", "owner", "deny"];
33086
33651
  var UNATTENDED = ["deny", "park", "allow"];
33087
33652
  function asLevel(v) {
@@ -33111,11 +33676,11 @@ function coercePermissions(v) {
33111
33676
  }
33112
33677
  return out;
33113
33678
  }
33114
- function parsePolicyYaml(text, agentName) {
33679
+ function parsePolicyYaml(text2, agentName) {
33115
33680
  let raw = {};
33116
- if (text.trim()) {
33681
+ if (text2.trim()) {
33117
33682
  try {
33118
- const parsed = import_yaml2.default.parse(text);
33683
+ const parsed = import_yaml3.default.parse(text2);
33119
33684
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
33120
33685
  raw = parsed;
33121
33686
  }
@@ -33171,6 +33736,23 @@ function parsePolicyYaml(text, agentName) {
33171
33736
  return policy;
33172
33737
  }
33173
33738
 
33739
+ // ../crew/packagePolicy.ts
33740
+ var import_yaml4 = __toESM(require_dist(), 1);
33741
+ import { validateModelEgress } from "@corenel/protocol";
33742
+ function packagePolicyModels(text2) {
33743
+ let raw;
33744
+ try {
33745
+ raw = text2.trim() ? import_yaml4.default.parse(text2) : null;
33746
+ } catch {
33747
+ return { ok: false, error: "POLICY.yaml is not valid YAML" };
33748
+ }
33749
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return { ok: true, value: null };
33750
+ const models = raw.models;
33751
+ if (models === void 0) return { ok: true, value: null };
33752
+ const checked = validateModelEgress(models);
33753
+ return checked.ok ? { ok: true, value: checked.value } : { ok: false, error: checked.error };
33754
+ }
33755
+
33174
33756
  // ../crew/donts.ts
33175
33757
  import { DONTS_MAX, DONT_MAX_CHARS, hasControlChars } from "@corenel/protocol";
33176
33758
  var DONT_BLANK = "A don't cannot be blank.";
@@ -33250,6 +33832,24 @@ function enforcedLevel(policy, cap) {
33250
33832
  });
33251
33833
  }
33252
33834
 
33835
+ // ../crew/commandTools.ts
33836
+ var COMMAND_CAPABILITIES = [
33837
+ { tool: "sidecar_shell_exec", label: "Run shell commands", mutating: true, address: "sidecar:shell_exec", permission: "ask" },
33838
+ { tool: "sidecar_run_check", label: "Run confirmed checks", mutating: true, address: "sidecar:run_check", permission: "ask" },
33839
+ { tool: "proc_start", label: "Start long-running processes", mutating: true, address: "shell:spawn", permission: "ask" }
33840
+ ];
33841
+ function offersCommandTools(toolNames) {
33842
+ const names = new Set(toolNames);
33843
+ return COMMAND_CAPABILITIES.some((c) => names.has(c.tool));
33844
+ }
33845
+ function grantsCommandTools(policy) {
33846
+ return COMMAND_CAPABILITIES.some((c) => enforcedLevel(policy, c) !== "deny");
33847
+ }
33848
+ function unsandboxedCommandsFact(policy, offeredToolNames) {
33849
+ const offered = new Set(offeredToolNames);
33850
+ return COMMAND_CAPABILITIES.some((c) => offered.has(c.tool) && enforcedLevel(policy, c) !== "deny") ? { unsandboxedCommands: true } : {};
33851
+ }
33852
+
33253
33853
  // ../crew/autonomy.ts
33254
33854
  import { SIDECAR_GIT_PUSH, SIDECAR_OPEN_PR } from "@corenel/protocol";
33255
33855
  import { toolAddress, resolveNamespace } from "@corenel/harness/tools/namespaces";
@@ -33308,8 +33908,8 @@ function allowedAutonomy(def) {
33308
33908
  function tightenAutonomy(def, requested) {
33309
33909
  if (!isAutonomyPreset(requested)) return { ok: false, reason: "Unknown autonomy level." };
33310
33910
  if (!fits(def, requested)) {
33311
- const current = readAutonomy(def);
33312
- const name = current === "custom" ? "a custom policy" : LABEL[current];
33911
+ const current2 = readAutonomy(def);
33912
+ const name = current2 === "custom" ? "a custom policy" : LABEL[current2];
33313
33913
  return { ok: false, reason: `This orchestrator is set to ${name}; a task cannot run as ${LABEL[requested]}. Change it on the agent.` };
33314
33914
  }
33315
33915
  const want = PRESET_LEVEL[requested];
@@ -33326,8 +33926,90 @@ function tightenAutonomy(def, requested) {
33326
33926
  }
33327
33927
 
33328
33928
  // ../crew/store.ts
33329
- var import_yaml3 = __toESM(require_dist(), 1);
33330
- import { flattenFiles as flattenFiles3 } from "@corenel/protocol";
33929
+ var import_yaml5 = __toESM(require_dist(), 1);
33930
+ init_dist();
33931
+ import {
33932
+ flattenFiles as flattenFiles3,
33933
+ PACKAGE_REF_FILE as PACKAGE_REF_FILE2,
33934
+ packageInstallDir,
33935
+ parentDir,
33936
+ parsePackageRef as parsePackageRef2
33937
+ } from "@corenel/protocol";
33938
+
33939
+ // ../crew/notFound.ts
33940
+ function isNotFound(e) {
33941
+ if (!e || typeof e !== "object") return false;
33942
+ const o = e;
33943
+ if (o.code === "ENOENT" || o.code === "ENOTDIR" || o.name === "NotFoundError") return true;
33944
+ return typeof o.message === "string" && /^(not found|no such file( or directory)?)(:|$)/i.test(o.message);
33945
+ }
33946
+
33947
+ // ../crew/managed.ts
33948
+ import { PACKAGE_REF_FILE, parsePackageRef } from "@corenel/protocol";
33949
+ var MANAGED_UNTRUSTED = "managed by a deployment this node does not hold";
33950
+ var MANAGED_LOCKED = "is managed by the fleet; its definition and settings cannot be changed, copied or deleted on this machine";
33951
+ var MANAGED_UNREADABLE = "has a PACKAGE.json that cannot be read, so it is treated as managed by the fleet: it cannot be changed, copied or deleted on this machine";
33952
+ var trust = null;
33953
+ function setManagedTrust(check) {
33954
+ trust = check;
33955
+ }
33956
+ function managedTrusted(name, managed) {
33957
+ if (!trust) return false;
33958
+ try {
33959
+ return trust(name, managed) === true;
33960
+ } catch {
33961
+ return false;
33962
+ }
33963
+ }
33964
+ function isManaged(x) {
33965
+ return x.source?.managed !== void 0;
33966
+ }
33967
+ async function readManagedRef(files, root, name) {
33968
+ const path = `${root}/${name}/${PACKAGE_REF_FILE}`;
33969
+ try {
33970
+ const st = await files.stat(path);
33971
+ if (st === null) return null;
33972
+ } catch (e) {
33973
+ return isNotFound(e) ? null : "unknown";
33974
+ }
33975
+ let text2;
33976
+ try {
33977
+ text2 = await files.read(path);
33978
+ } catch {
33979
+ return "unknown";
33980
+ }
33981
+ return managedClaimOf(text2);
33982
+ }
33983
+ function managedClaimOf(text2) {
33984
+ let ref;
33985
+ try {
33986
+ ref = parsePackageRef(text2);
33987
+ } catch {
33988
+ return "unknown";
33989
+ }
33990
+ return ref.managed ? { ...ref, managed: ref.managed } : null;
33991
+ }
33992
+ async function readManagedEntry(files, root, name) {
33993
+ const ref = await readManagedRef(files, root, name);
33994
+ return ref === null || ref === "unknown" ? ref : ref.managed;
33995
+ }
33996
+ async function managedLockReason(files, root, name) {
33997
+ const m = await readManagedEntry(files, root, name);
33998
+ if (m === null) return null;
33999
+ return m === "unknown" ? MANAGED_UNREADABLE : MANAGED_LOCKED;
34000
+ }
34001
+ async function isManagedOnDisk(files, root, name) {
34002
+ return await readManagedEntry(files, root, name) !== null;
34003
+ }
34004
+
34005
+ // ../crew/definitionFilter.ts
34006
+ var current = null;
34007
+ function setDefinitionFilter(f) {
34008
+ current = f;
34009
+ }
34010
+ function filterDefinition(def, at) {
34011
+ return current ? current(def, at) : def;
34012
+ }
33331
34013
 
33332
34014
  // ../crew/sessionBinding.ts
33333
34015
  var SESSION_NAME_RE = /^[a-z0-9_-]{1,32}$/;
@@ -33384,6 +34066,73 @@ async function readOr(files, path, fallback = "") {
33384
34066
  return fallback;
33385
34067
  }
33386
34068
  }
34069
+ var DEFINITION_FILES = ["AGENT.md", "SOUL.md", "PERSONA.md", "POLICY.yaml"];
34070
+ var textDecoder3 = new TextDecoder();
34071
+ async function isFile(files, path) {
34072
+ try {
34073
+ return (await files.stat(path))?.kind === "file";
34074
+ } catch (e) {
34075
+ if (isNotFound(e)) return false;
34076
+ throw e;
34077
+ }
34078
+ }
34079
+ var CREW_DEFINITION_MARKERS = ["AGENT.md", PACKAGE_REF_FILE2];
34080
+ async function crewAgentPresent(files, root, name) {
34081
+ if (!isValidAgentName(name)) return false;
34082
+ for (const f of CREW_DEFINITION_MARKERS) {
34083
+ if (await isFile(files, `${root}/${name}/${f}`)) return true;
34084
+ }
34085
+ return false;
34086
+ }
34087
+ async function definitionSource(files, root, name) {
34088
+ const dir = `${root}/${name}`;
34089
+ if (!await isFile(files, `${dir}/${PACKAGE_REF_FILE2}`)) {
34090
+ return { read: (f) => readOr(files, `${dir}/${f}`) };
34091
+ }
34092
+ for (const f of DEFINITION_FILES) {
34093
+ if (await isFile(files, `${dir}/${f}`)) {
34094
+ throw new Error(`crew agent ${name}: the folder holds both ${PACKAGE_REF_FILE2} and definition files (${f}); remove one`);
34095
+ }
34096
+ }
34097
+ let ref;
34098
+ try {
34099
+ ref = parsePackageRef2(await files.read(`${dir}/${PACKAGE_REF_FILE2}`));
34100
+ } catch (e) {
34101
+ throw new Error(`crew agent ${name}: ${e.message}`);
34102
+ }
34103
+ if (ref.managed && !managedTrusted(name, ref.managed)) {
34104
+ throw new Error(`crew agent ${name}: ${MANAGED_UNTRUSTED}`);
34105
+ }
34106
+ const label = `${ref.package}@${ref.version} (${ref.digest})`;
34107
+ const readBytes = files.readBytes?.bind(files);
34108
+ if (!readBytes) {
34109
+ throw new Error(`crew agent ${name}: package ${label} cannot be loaded: cannot read package archives on this host (its file service has no binary reads)`);
34110
+ }
34111
+ const installDir = packageInstallDir(parentDir(root), "agent", ref);
34112
+ let pkg;
34113
+ try {
34114
+ pkg = await verifyInstalled(async (rel) => {
34115
+ try {
34116
+ return await readBytes(`${installDir}/${rel}`);
34117
+ } catch {
34118
+ return null;
34119
+ }
34120
+ }, ref.digest, { name: ref.package, range: ref.version });
34121
+ } catch (e) {
34122
+ if (isPackageVerificationError(e) && e.code === "FILE_MISSING" && e.path === ARCHIVE_COPY) {
34123
+ throw new Error(`crew agent ${name}: package ${label} is not installed`);
34124
+ }
34125
+ throw new Error(`crew agent ${name}: package ${ref.package}@${ref.version} failed verification: ${e.message}`);
34126
+ }
34127
+ const source = { kind: "package", package: ref.package, version: ref.version, digest: ref.digest, ...ref.managed ? { managed: ref.managed } : {} };
34128
+ return {
34129
+ read: async (f) => {
34130
+ const b = pkg.files.get(f);
34131
+ return b ? textDecoder3.decode(b) : "";
34132
+ },
34133
+ source
34134
+ };
34135
+ }
33387
34136
  function parseTriggers(meta) {
33388
34137
  const raw = meta.triggers;
33389
34138
  if (!Array.isArray(raw)) return [];
@@ -33450,13 +34199,16 @@ function parseWorkRoots(raw) {
33450
34199
  }
33451
34200
  return Object.keys(out).length ? out : void 0;
33452
34201
  }
33453
- function parseSettings(text) {
34202
+ function parseSettings(text2) {
33454
34203
  try {
33455
- const raw = JSON.parse(text);
34204
+ const raw = JSON.parse(text2);
33456
34205
  if (raw && typeof raw === "object" && !Array.isArray(raw)) {
33457
34206
  const o = raw;
33458
34207
  return {
33459
34208
  model: typeof o.model === "string" ? o.model : void 0,
34209
+ /* Meaningful only for a package agent (its AGENT.md is immutable); a
34210
+ * local agent's switch lives in AGENT.md and this is ignored for it. */
34211
+ enabled: typeof o.enabled === "boolean" ? o.enabled : void 0,
33460
34212
  temperature: typeof o.temperature === "number" ? o.temperature : void 0,
33461
34213
  /* Carried through as-is. Validation belongs to the daemon, which is the
33462
34214
  * only side that knows its own approved roots -- checking here would be
@@ -33470,45 +34222,60 @@ function parseSettings(text) {
33470
34222
  }
33471
34223
  return {};
33472
34224
  }
34225
+ function packageModelsOf(policyText) {
34226
+ const m = packagePolicyModels(policyText);
34227
+ if (!m.ok) return { packageModels: { allow: [] } };
34228
+ return m.value === null ? {} : { packageModels: m.value };
34229
+ }
33473
34230
  async function loadCrewAgentAt(files, root, name, scope = "workspace") {
33474
34231
  if (!isValidAgentName(name)) throw new Error(`invalid crew agent name: ${name}`);
33475
34232
  const dir = `${root}/${name}`;
33476
- const { meta, body } = parseFrontmatter(await readOr(files, `${dir}/AGENT.md`));
34233
+ const src = await definitionSource(files, root, name);
34234
+ const { meta, body } = parseFrontmatter(await src.read("AGENT.md"));
34235
+ const settings = parseSettings(await readOr(files, `${dir}/settings.json`, "{}"));
34236
+ if (!src.source) delete settings.enabled;
33477
34237
  const session = parseSessionBinding(meta);
33478
34238
  const orchestration = parseOrchestration(meta);
33479
34239
  const tags = (0, tags_exports.parseTags)(meta);
33480
- return {
34240
+ const policyText = await src.read("POLICY.yaml");
34241
+ return filterDefinition({
33481
34242
  name,
33482
34243
  jobTitle: typeof meta.jobTitle === "string" ? meta.jobTitle : "",
33483
34244
  description: typeof meta.description === "string" ? meta.description : "",
33484
34245
  ...tags ? { tags } : {},
33485
34246
  scope,
33486
- enabled: meta.enabled !== false,
33487
- // absent/anything-but-false -> enabled
34247
+ // absent/anything-but-false -> enabled; a package agent's switch is in settings.json
34248
+ enabled: src.source ? settings.enabled !== false : meta.enabled !== false,
33488
34249
  triggers: parseTriggers(meta),
33489
34250
  instructions: body,
33490
- soul: await readOr(files, `${dir}/SOUL.md`),
33491
- persona: await readOr(files, `${dir}/PERSONA.md`),
33492
- policy: parsePolicyYaml(await readOr(files, `${dir}/POLICY.yaml`), name),
33493
- settings: parseSettings(await readOr(files, `${dir}/settings.json`, "{}")),
34251
+ soul: await src.read("SOUL.md"),
34252
+ persona: await src.read("PERSONA.md"),
34253
+ policy: parsePolicyYaml(policyText, name),
34254
+ settings,
33494
34255
  budget: parseBudget(meta),
33495
34256
  canCall: parseCanCall(meta),
33496
34257
  canCallAll: meta.canCallAll === true,
33497
34258
  ...orchestration !== void 0 ? { orchestration } : {},
33498
34259
  ...session.kind === "binding" ? { session: session.binding } : {},
33499
- ...session.kind === "malformed" ? { sessionError: session.reason } : {}
33500
- };
34260
+ ...session.kind === "malformed" ? { sessionError: session.reason } : {},
34261
+ ...src.source ? { source: src.source } : {},
34262
+ ...src.source ? packageModelsOf(policyText) : {}
34263
+ }, { files, root });
33501
34264
  }
33502
34265
  async function loadCrewAgentAtIfExists(files, root, name, scope = "workspace") {
33503
34266
  if (!isValidAgentName(name)) return null;
33504
34267
  try {
33505
- const st = await files.stat(`${root}/${name}/AGENT.md`);
33506
- if (st?.kind !== "file") return null;
34268
+ if (!await crewAgentPresent(files, root, name)) return null;
33507
34269
  return await loadCrewAgentAt(files, root, name, scope);
33508
34270
  } catch {
33509
34271
  return null;
33510
34272
  }
33511
34273
  }
34274
+ async function loadCrewAgentAtIfPresent(files, root, name, scope = "workspace") {
34275
+ if (!isValidAgentName(name)) return null;
34276
+ if (!await crewAgentPresent(files, root, name)) return null;
34277
+ return loadCrewAgentAt(files, root, name, scope);
34278
+ }
33512
34279
  async function listCrewAgentsAt(files, root, opts = {}) {
33513
34280
  let nodes;
33514
34281
  try {
@@ -33545,7 +34312,7 @@ function serializePolicy(policy) {
33545
34312
  if (policy.unattended) ordered.unattended = policy.unattended;
33546
34313
  if (typeof policy.parkTimeoutMs === "number") ordered.parkTimeoutMs = policy.parkTimeoutMs;
33547
34314
  if (typeof policy.pushWaitMs === "number") ordered.pushWaitMs = policy.pushWaitMs;
33548
- return import_yaml3.default.stringify(ordered, { lineWidth: 0 });
34315
+ return import_yaml5.default.stringify(ordered, { lineWidth: 0 });
33549
34316
  }
33550
34317
  function serializeAgentMd(def) {
33551
34318
  const meta = { name: def.name };
@@ -33571,13 +34338,15 @@ function serializeAgentMd(def) {
33571
34338
  meta.session = def.session.createIfMissing ? { name: def.session.name } : { name: def.session.name, createIfMissing: false };
33572
34339
  }
33573
34340
  return `---
33574
- ${import_yaml3.default.stringify(meta, { lineWidth: 0 })}---
34341
+ ${import_yaml5.default.stringify(meta, { lineWidth: 0 })}---
33575
34342
  ${def.instructions.replace(/\n+$/, "")}
33576
34343
  `;
33577
34344
  }
33578
34345
  async function loadCrewSummaryAt(files, root, name, scope = "workspace") {
33579
34346
  if (!isValidAgentName(name)) throw new Error(`invalid crew agent name: ${name}`);
33580
- const { meta } = parseFrontmatter(await readOr(files, `${root}/${name}/AGENT.md`));
34347
+ const src = await definitionSource(files, root, name);
34348
+ const { meta } = parseFrontmatter(await src.read("AGENT.md"));
34349
+ const enabled = src.source ? parseSettings(await readOr(files, `${root}/${name}/settings.json`, "{}")).enabled !== false : meta.enabled !== false;
33581
34350
  const tags = (0, tags_exports.parseTags)(meta);
33582
34351
  return {
33583
34352
  name,
@@ -33585,20 +34354,30 @@ async function loadCrewSummaryAt(files, root, name, scope = "workspace") {
33585
34354
  description: typeof meta.description === "string" ? meta.description : "",
33586
34355
  ...tags ? { tags } : {},
33587
34356
  triggers: parseTriggers(meta).map((t) => t.type),
33588
- enabled: meta.enabled !== false,
34357
+ enabled,
33589
34358
  scope,
33590
34359
  delegates: Array.isArray(meta.canCall) && meta.canCall.length > 0 || meta.canCallAll === true,
33591
- orchestrator: orchestrationBlock(meta) !== void 0
34360
+ orchestrator: orchestrationBlock(meta) !== void 0,
34361
+ ...src.source ? { source: src.source } : {}
33592
34362
  };
33593
34363
  }
34364
+ async function referencedSource(files, dir) {
34365
+ try {
34366
+ const ref = parsePackageRef2(await files.read(`${dir}/${PACKAGE_REF_FILE2}`));
34367
+ return { kind: "package", package: ref.package, version: ref.version, digest: ref.digest, ...ref.managed ? { managed: ref.managed } : {} };
34368
+ } catch {
34369
+ return void 0;
34370
+ }
34371
+ }
33594
34372
  async function listCrewSummariesAt(files, root, scope = "workspace", opts = {}) {
33595
34373
  const names = await listCrewAgentsAt(files, root, opts);
33596
34374
  const out = [];
33597
34375
  for (const name of names.sort()) {
33598
34376
  try {
33599
34377
  out.push(await loadCrewSummaryAt(files, root, name, scope));
33600
- } catch {
33601
- out.push({ name, description: "", enabled: true, scope, delegates: false, orchestrator: false });
34378
+ } catch (e) {
34379
+ const source = await referencedSource(files, `${root}/${name}`);
34380
+ out.push({ name, description: "", enabled: false, scope, delegates: false, orchestrator: false, ...source ? { source } : {}, loadError: e.message });
33602
34381
  }
33603
34382
  }
33604
34383
  return out;
@@ -33612,22 +34391,37 @@ async function put(files, path, content) {
33612
34391
  }
33613
34392
  function stripWorkRoots(settings) {
33614
34393
  const { workRoots: _workRoots, ...rest } = settings;
34394
+ for (const k of Object.keys(rest)) {
34395
+ if (rest[k] === void 0) delete rest[k];
34396
+ }
33615
34397
  return rest;
33616
34398
  }
33617
34399
  async function dontsUnchanged(files, dir, def) {
33618
- let text;
34400
+ let text2;
33619
34401
  try {
33620
- text = await files.read(`${dir}/POLICY.yaml`);
34402
+ text2 = await files.read(`${dir}/POLICY.yaml`);
33621
34403
  } catch {
33622
34404
  return false;
33623
34405
  }
33624
- const stored = parsePolicyYaml(text, def.name).donts ?? [];
34406
+ const stored = parsePolicyYaml(text2, def.name).donts ?? [];
33625
34407
  const next = (def.policy.donts ?? []).map((d) => d.trim());
33626
34408
  return stored.length === next.length && stored.every((d, i) => d === next[i]);
33627
34409
  }
33628
34410
  async function writeCrewAgentAt(files, root, def) {
33629
34411
  if (!isValidAgentName(def.name)) throw new Error(`invalid crew agent name: ${def.name}`);
33630
34412
  const dir = `${root}/${def.name}`;
34413
+ if (await isFile(files, `${dir}/${PACKAGE_REF_FILE2}`)) {
34414
+ const locked2 = await managedLockReason(files, root, def.name);
34415
+ if (locked2) throw new Error(`crew agent ${def.name} ${locked2}`);
34416
+ await put(files, `${dir}/settings.json`, `${JSON.stringify(stripWorkRoots({ ...def.settings, enabled: def.enabled }), null, 2)}
34417
+ `);
34418
+ return;
34419
+ }
34420
+ if (def.source) {
34421
+ throw new Error(`crew agent ${def.name} is package ${def.source.package}@${def.source.version} but its folder has no ${PACKAGE_REF_FILE2}; copy it to make a local agent`);
34422
+ }
34423
+ const localSettings = { ...def.settings };
34424
+ delete localSettings.enabled;
33631
34425
  if (!await dontsUnchanged(files, dir, def)) {
33632
34426
  const problems = dontsProblems(def.policy);
33633
34427
  if (problems.length) throw new Error(problems.join(" "));
@@ -33636,11 +34430,25 @@ async function writeCrewAgentAt(files, root, def) {
33636
34430
  await put(files, `${dir}/SOUL.md`, def.soul);
33637
34431
  await put(files, `${dir}/PERSONA.md`, def.persona);
33638
34432
  await put(files, `${dir}/POLICY.yaml`, serializePolicy(def.policy));
33639
- await put(files, `${dir}/settings.json`, `${JSON.stringify(stripWorkRoots(def.settings), null, 2)}
34433
+ await put(files, `${dir}/settings.json`, `${JSON.stringify(stripWorkRoots(localSettings), null, 2)}
33640
34434
  `);
33641
34435
  }
34436
+ async function copyCrewAgentAt(files, root, from, to) {
34437
+ if (!isValidAgentName(to)) throw new Error(`invalid crew agent name: ${to}`);
34438
+ if (await crewAgentPresent(files, root, to)) throw new Error(`crew agent ${to} already exists`);
34439
+ const def = await loadCrewAgentAt(files, root, from);
34440
+ const locked2 = isManaged(def) ? MANAGED_LOCKED : await managedLockReason(files, root, from);
34441
+ if (locked2) throw new Error(`crew agent ${from} ${locked2}`);
34442
+ const copy = { ...def, name: to, settings: { ...def.settings } };
34443
+ delete copy.source;
34444
+ delete copy.settings.enabled;
34445
+ await writeCrewAgentAt(files, root, copy);
34446
+ return copy;
34447
+ }
33642
34448
  async function deleteCrewAgentAt(files, root, name) {
33643
34449
  if (!isValidAgentName(name)) throw new Error(`invalid crew agent name: ${name}`);
34450
+ const locked2 = await managedLockReason(files, root, name);
34451
+ if (locked2) throw new Error(`crew agent ${name} ${locked2}`);
33644
34452
  await files.remove(`${root}/${name}`);
33645
34453
  }
33646
34454
 
@@ -33918,10 +34726,10 @@ function normalizeRunStatus(raw) {
33918
34726
  return RUN_STATUS_BY_RAW.get((raw ?? "").trim()) ?? "error";
33919
34727
  }
33920
34728
  function splitRunStatus(raw) {
33921
- const text = (raw ?? "").trim();
33922
- const stopReason = normalizeRunStatus(text);
33923
- if (stopReason !== "error" || text === "error" || !text) return { stopReason };
33924
- return { stopReason, message: text };
34729
+ const text2 = (raw ?? "").trim();
34730
+ const stopReason = normalizeRunStatus(text2);
34731
+ if (stopReason !== "error" || text2 === "error" || !text2) return { stopReason };
34732
+ return { stopReason, message: text2 };
33925
34733
  }
33926
34734
  function matchRunComplete(config, completion) {
33927
34735
  const after = stringArray(config.after);
@@ -33955,11 +34763,11 @@ function emptyDeployment() {
33955
34763
  function deploymentKey(name, wsId) {
33956
34764
  return wsId ? `workspaces/${wsId}/crew/${name}` : `crew/${name}`;
33957
34765
  }
33958
- function parseDeployment(text) {
34766
+ function parseDeployment(text2) {
33959
34767
  const out = emptyDeployment();
33960
34768
  let raw;
33961
34769
  try {
33962
- raw = JSON.parse(text);
34770
+ raw = JSON.parse(text2);
33963
34771
  } catch {
33964
34772
  return out;
33965
34773
  }
@@ -34110,11 +34918,12 @@ function nextCronAfter(f, from) {
34110
34918
  }
34111
34919
 
34112
34920
  // ../crew/offerGrants.ts
34113
- import { policyNamesTool, toolGateCovers } from "@corenel/harness/guardrail";
34921
+ import { matchesAnyGlob as matchesAnyGlob2, policyNamesTool, toolGateCovers } from "@corenel/harness/guardrail";
34114
34922
  import { toolAddress as toolAddress2 } from "@corenel/harness/tools/namespaces";
34115
- function grantOfferedTools(policy, offered) {
34923
+ function grantOfferedTools(policy, offered, cap = null) {
34116
34924
  const missing = offered.filter((name) => {
34117
34925
  const subject = { name, address: toolAddress2({ name }) };
34926
+ if (cap !== null && !matchesAnyGlob2(subject.name, cap) && !matchesAnyGlob2(subject.address, cap)) return false;
34118
34927
  return !policyNamesTool(policy, subject) && !toolGateCovers(policy, subject);
34119
34928
  });
34120
34929
  if (!missing.length) return policy;
@@ -34122,6 +34931,93 @@ function grantOfferedTools(policy, offered) {
34122
34931
  for (const name of missing) permissions[name] = "allow";
34123
34932
  return { ...policy, permissions };
34124
34933
  }
34934
+ function managedCap(def) {
34935
+ if (!def.source?.managed) return null;
34936
+ const allow = def.policy.tools?.allow ?? [];
34937
+ return allow.length ? [...allow] : null;
34938
+ }
34939
+
34940
+ // ../crew/acl.ts
34941
+ import {
34942
+ intersectModelEgress,
34943
+ toolsWider
34944
+ } from "@corenel/protocol";
34945
+ var NO_TOOL_SENTINEL = "__none__";
34946
+ var MCP_DENY_ALL = "mcp:**";
34947
+ var MANAGED_IN_SESSION_REFUSED = "managed agents run only on this machine's daemon, never in a session";
34948
+ function uniq(xs) {
34949
+ return [...new Set(xs)];
34950
+ }
34951
+ function intersectAllowList(pkg, acl) {
34952
+ const p = pkg ?? [];
34953
+ const entries = uniq(acl);
34954
+ const widened = toolsWider(entries, p);
34955
+ return { allow: entries.filter((e) => !widened.includes(e)), widened };
34956
+ }
34957
+ function egressIsEmpty(e) {
34958
+ if (e === "any") return false;
34959
+ return e.allow.every((ep) => ep.models !== "*" && ep.models.length === 0);
34960
+ }
34961
+ function accessAllows(level, userId, adminId) {
34962
+ if (level === void 0 || level === "members") return true;
34963
+ return !!userId && !!adminId && userId === adminId;
34964
+ }
34965
+ function lower(a, b) {
34966
+ if (a === void 0) return b;
34967
+ if (b === void 0) return a;
34968
+ return Math.min(a, b);
34969
+ }
34970
+ function narrowDefinition(def, acl, nodePolicy) {
34971
+ let refused;
34972
+ const refuse = (why) => {
34973
+ if (refused === void 0) refused = why;
34974
+ };
34975
+ if (def.session !== void 0 || def.sessionError !== void 0) refuse(MANAGED_IN_SESSION_REFUSED);
34976
+ const pkgAllow = def.policy.tools?.allow ?? [];
34977
+ let allow = [...pkgAllow];
34978
+ if (acl.tools) {
34979
+ const r = intersectAllowList(pkgAllow, acl.tools.allow);
34980
+ if (r.widened.length) refuse(`tools would widen the package: ${r.widened.join(", ")}`);
34981
+ allow = r.allow.length ? r.allow : [NO_TOOL_SENTINEL];
34982
+ }
34983
+ const deny = [...def.policy.tools?.deny ?? []];
34984
+ if (allow.length === 0 && !deny.includes(MCP_DENY_ALL)) deny.push(MCP_DENY_ALL);
34985
+ const tools = allow.length || deny.length ? { ...allow.length ? { allow } : {}, ...deny.length ? { deny } : {} } : void 0;
34986
+ let skills = def.policy.skills;
34987
+ const aclSkills = acl.tools?.skills;
34988
+ if (aclSkills) {
34989
+ const pkgSkills = def.policy.skills ?? [];
34990
+ const kept = pkgSkills.filter((s) => aclSkills.includes(s));
34991
+ const widened = aclSkills.filter((s) => !pkgSkills.includes(s));
34992
+ if (widened.length) refuse(`skills would widen the package: ${widened.join(", ")}`);
34993
+ skills = kept.length ? kept : [NO_TOOL_SENTINEL];
34994
+ }
34995
+ const { tools: _tools, skills: _skills, ...policyRest } = def.policy;
34996
+ const policy = { ...policyRest, ...tools ? { tools } : {}, ...skills ? { skills } : {} };
34997
+ const allowedTriggers = acl.triggers?.allow;
34998
+ const triggers = allowedTriggers ? def.triggers.filter((t) => allowedTriggers.includes(t.type)) : [...def.triggers];
34999
+ const budget = { ...def.budget ?? {} };
35000
+ if (acl.budget) {
35001
+ const usd = lower(budget.maxUsd, acl.budget.perRunUsd);
35002
+ const tok = lower(budget.maxTokens, acl.budget.perRunTokens);
35003
+ if (usd !== void 0) budget.maxUsd = usd;
35004
+ if (tok !== void 0) budget.maxTokens = tok;
35005
+ }
35006
+ const effectiveModels = intersectModelEgress(
35007
+ intersectModelEgress(nodePolicy.models, def.packageModels ?? "any"),
35008
+ acl.models ?? "any"
35009
+ );
35010
+ if (egressIsEmpty(effectiveModels)) refuse("no allowed model");
35011
+ const out = {
35012
+ ...def,
35013
+ policy,
35014
+ triggers,
35015
+ budget,
35016
+ egress: effectiveModels,
35017
+ ...acl.access ? { aclAccess: { run: acl.access.run } } : {}
35018
+ };
35019
+ return refused === void 0 ? { def: out, effectiveModels } : { def: out, effectiveModels, refused };
35020
+ }
34125
35021
 
34126
35022
  // ../crew/memory.ts
34127
35023
  import { MEMORY_USERS_DIR } from "@corenel/protocol";
@@ -34274,9 +35170,9 @@ var ROOM_KIND = "room";
34274
35170
  function encodeRoomLine(line) {
34275
35171
  return JSON.stringify(line) + "\n";
34276
35172
  }
34277
- function roomLines(text) {
35173
+ function roomLines(text2) {
34278
35174
  const out = [];
34279
- for (const raw of text.split("\n")) {
35175
+ for (const raw of text2.split("\n")) {
34280
35176
  const s = raw.trim();
34281
35177
  if (!s) continue;
34282
35178
  let line;
@@ -34289,14 +35185,14 @@ function roomLines(text) {
34289
35185
  }
34290
35186
  return out;
34291
35187
  }
34292
- function openLineOf(text) {
34293
- for (const line of roomLines(text)) if (line.op === "open") return line;
35188
+ function openLineOf(text2) {
35189
+ for (const line of roomLines(text2)) if (line.op === "open") return line;
34294
35190
  return null;
34295
35191
  }
34296
- function foldRoom(text) {
35192
+ function foldRoom(text2) {
34297
35193
  let state = null;
34298
35194
  let lastAt;
34299
- for (const line of roomLines(text)) {
35195
+ for (const line of roomLines(text2)) {
34300
35196
  if (typeof line.at === "number" && (lastAt === void 0 || line.at > lastAt)) lastAt = line.at;
34301
35197
  if (line.op === "open") {
34302
35198
  if (state) continue;
@@ -34346,9 +35242,9 @@ function foldRoom(text) {
34346
35242
  if (state && lastAt !== void 0) state = { ...state, lastAt };
34347
35243
  return state;
34348
35244
  }
34349
- function pendingParticipant(text) {
35245
+ function pendingParticipant(text2) {
34350
35246
  let pending = null;
34351
- for (const line of roomLines(text)) {
35247
+ for (const line of roomLines(text2)) {
34352
35248
  if (line.op === "pending") {
34353
35249
  if (typeof line.participant === "string") pending = line.participant;
34354
35250
  } else if (line.op === "floor" || line.op === "close") {
@@ -34357,9 +35253,9 @@ function pendingParticipant(text) {
34357
35253
  }
34358
35254
  return pending;
34359
35255
  }
34360
- function pendingReason(text) {
35256
+ function pendingReason(text2) {
34361
35257
  let reason = null;
34362
- for (const line of roomLines(text)) {
35258
+ for (const line of roomLines(text2)) {
34363
35259
  if (line.op === "pending") {
34364
35260
  reason = typeof line.reason === "string" ? line.reason : null;
34365
35261
  } else if (line.op === "floor" || line.op === "close") {
@@ -34368,10 +35264,10 @@ function pendingReason(text) {
34368
35264
  }
34369
35265
  return reason;
34370
35266
  }
34371
- function turnCosts(text) {
35267
+ function turnCosts(text2) {
34372
35268
  const out = [];
34373
35269
  let opened = false;
34374
- for (const line of roomLines(text)) {
35270
+ for (const line of roomLines(text2)) {
34375
35271
  if (line.op === "open") {
34376
35272
  if (typeof line.roomId === "string" && Array.isArray(line.participants) && typeof line.maxTurns === "number") opened = true;
34377
35273
  continue;
@@ -34470,8 +35366,8 @@ var RoomStore = class {
34470
35366
  * reader wants a document either way. A file that exists but cannot be read
34471
35367
  * throws (see `textAt`). */
34472
35368
  async readFindings(roomId) {
34473
- const text = await this.textAt(findingsPath(this.getRoot(), roomId));
34474
- return text == null ? [] : foldFindings(text);
35369
+ const text2 = await this.textAt(findingsPath(this.getRoot(), roomId));
35370
+ return text2 == null ? [] : foldFindings(text2);
34475
35371
  }
34476
35372
  /** Append one finding op. A genuine read-then-concat append, exactly as
34477
35373
  * `append` does for the room fold, because the engine and a human's edit both
@@ -34483,8 +35379,8 @@ var RoomStore = class {
34483
35379
  await files.write(path, prior + encodeFindingLine(line));
34484
35380
  }
34485
35381
  async read(roomId) {
34486
- const text = await this.text(roomId);
34487
- return text == null ? null : foldRoom(text);
35382
+ const text2 = await this.text(roomId);
35383
+ return text2 == null ? null : foldRoom(text2);
34488
35384
  }
34489
35385
  /** Every room this store can find on disk, folded to its current state.
34490
35386
  * Mirrors `JsonlSessionStore.list()` (packages/harness/sessions/
@@ -34500,38 +35396,38 @@ var RoomStore = class {
34500
35396
  const roomFiles = flattenFiles4(nodes).filter((f) => f.name === "SESSION.jsonl" && f.path.startsWith(`${root}/`));
34501
35397
  const out = [];
34502
35398
  for (const f of roomFiles) {
34503
- const text = await files.read(f.path).catch(() => null);
34504
- const state = text != null ? foldRoom(text) : null;
35399
+ const text2 = await files.read(f.path).catch(() => null);
35400
+ const state = text2 != null ? foldRoom(text2) : null;
34505
35401
  if (state) out.push(state);
34506
35402
  }
34507
35403
  return out;
34508
35404
  }
34509
35405
  async readSession(roomId) {
34510
- const text = await this.text(roomId);
34511
- return text == null ? null : foldSession(text);
35406
+ const text2 = await this.text(roomId);
35407
+ return text2 == null ? null : foldSession(text2);
34512
35408
  }
34513
35409
  /** The participant the room is currently parked on, or null. Lets a caller
34514
35410
  * that re-polls a parked room (`runRoom`) tell "still parked on the same
34515
35411
  * person" from "needs a fresh `{op:'pending'}` line" without appending one
34516
35412
  * just to find out. */
34517
35413
  async pendingParticipant(roomId) {
34518
- const text = await this.text(roomId);
34519
- return text == null ? null : pendingParticipant(text);
35414
+ const text2 = await this.text(roomId);
35415
+ return text2 == null ? null : pendingParticipant(text2);
34520
35416
  }
34521
35417
  /** Why the room is parked, when the park was not simply someone's turn (see
34522
35418
  * `pendingReason` in lines.ts). Null for an ordinary human turn, and for a
34523
35419
  * room that is not parked. */
34524
35420
  async pendingReason(roomId) {
34525
- const text = await this.text(roomId);
34526
- return text == null ? null : pendingReason(text);
35421
+ const text2 = await this.text(roomId);
35422
+ return text2 == null ? null : pendingReason(text2);
34527
35423
  }
34528
35424
  /** What each of this room's turns cost, in order (see `turnCosts` in
34529
35425
  * lines.ts). Empty for a room that has taken no turn, and for a room that
34530
35426
  * does not exist -- a reader of a transcript wants an array it can index by
34531
35427
  * turn, and "no room" and "no turns yet" annotate that transcript alike. */
34532
35428
  async turnCosts(roomId) {
34533
- const text = await this.text(roomId);
34534
- return text == null ? [] : turnCosts(text);
35429
+ const text2 = await this.text(roomId);
35430
+ return text2 == null ? [] : turnCosts(text2);
34535
35431
  }
34536
35432
  };
34537
35433
 
@@ -34740,7 +35636,7 @@ function makeCrewTurnRuntime(opts) {
34740
35636
  const { def, participants, meId, deps } = opts;
34741
35637
  const findings = opts.findings ?? [];
34742
35638
  const refs = participants.map((p) => ({ id: p.id, name: p.name }));
34743
- const policy = grantOfferedTools(def.policy, [...ROOM_TOOL_NAMES]);
35639
+ const policy = grantOfferedTools(def.policy, [...ROOM_TOOL_NAMES], managedCap(def));
34744
35640
  const permission = new PermissionService2({
34745
35641
  policy,
34746
35642
  ...deps.prompt ? { prompt: deps.prompt } : {},
@@ -34962,7 +35858,7 @@ async function runRoom(roomId, deps) {
34962
35858
  }
34963
35859
  }
34964
35860
  }
34965
- async function answerHumanTurn(roomId, participantId, text, deps, addressed) {
35861
+ async function answerHumanTurn(roomId, participantId, text2, deps, addressed) {
34966
35862
  const state = await deps.store.read(roomId);
34967
35863
  if (!state) throw new Error(`No room "${roomId}".`);
34968
35864
  if (state.closed) {
@@ -34999,7 +35895,7 @@ async function answerHumanTurn(roomId, participantId, text, deps, addressed) {
34999
35895
  }
35000
35896
  target = res.id;
35001
35897
  }
35002
- const message = stampAuthor({ role: "user", content: text }, participantId);
35898
+ const message = stampAuthor({ role: "user", content: text2 }, participantId);
35003
35899
  await appendMessages(deps.store, roomId, [message], deps.now());
35004
35900
  let next = advance(state, target);
35005
35901
  if (next.closed) {
@@ -35030,14 +35926,14 @@ function requireHuman(roomId, state, participantId) {
35030
35926
  }
35031
35927
  return found;
35032
35928
  }
35033
- async function interjectHuman(roomId, participantId, text, deps) {
35929
+ async function interjectHuman(roomId, participantId, text2, deps) {
35034
35930
  const state = await deps.store.read(roomId);
35035
35931
  if (!state) throw new Error(`No room "${roomId}".`);
35036
35932
  if (state.closed) {
35037
35933
  throw new Error(`Room "${roomId}" is closed (${state.closed.reason}), so nothing further can be said in it.`);
35038
35934
  }
35039
35935
  const speaker = requireHuman(roomId, state, participantId);
35040
- const body = text.trim();
35936
+ const body = text2.trim();
35041
35937
  if (!body) {
35042
35938
  throw new Error(`${speaker.name} said nothing: an empty interjection is not appended.`);
35043
35939
  }
@@ -35106,7 +36002,7 @@ import { createChatClient, setGatewayBase } from "@corenel/harness/providers/gat
35106
36002
  // src/apiBase.ts
35107
36003
  init_tools_node();
35108
36004
  import { DEFAULT_API_BASE as DEFAULT_API_BASE2 } from "@corenel/protocol";
35109
- import { DEV_PROFILE } from "@corenel/protocol";
36005
+ import { DEV_PROFILE, SANDBOX_GATEWAY_BASE_ENV } from "@corenel/protocol";
35110
36006
  var InvalidApiBaseError = class extends Error {
35111
36007
  constructor(value, why) {
35112
36008
  super(`invalid API base ${JSON.stringify(value)} -- ${why}`);
@@ -35160,7 +36056,10 @@ async function resolveCliApiBase(explicit, opts = {}) {
35160
36056
  if (url.protocol !== "https:" && url.protocol !== "http:") {
35161
36057
  throw new InvalidApiBaseError(value, `the scheme must be https or http, not ${url.protocol.replace(/:$/, "")}`);
35162
36058
  }
35163
- if (url.protocol === "http:" && !isLoopback(url.hostname) && !warnedCleartext) {
36059
+ const trim2 = (s) => s.trim().replace(/\/+$/, "");
36060
+ const marker = env[SANDBOX_GATEWAY_BASE_ENV];
36061
+ const sanctioned = typeof marker === "string" && marker.trim() !== "" && trim2(marker) === trim2(value);
36062
+ if (url.protocol === "http:" && !isLoopback(url.hostname) && !sanctioned && !warnedCleartext) {
35164
36063
  warnedCleartext = true;
35165
36064
  process.stderr.write(
35166
36065
  `corenel: warning: ${url.host} is plain http, so your access token is sent in cleartext. Use https unless this host is on a private network you trust.
@@ -35341,16 +36240,25 @@ var EXTENSIONS = [
35341
36240
  }
35342
36241
  },
35343
36242
  {
35344
- command: "sessions",
36243
+ command: "sandboxes",
35345
36244
  ...SIDECAR,
35346
- summary: "list and inspect local sandbox sessions",
35347
- argv: (rest) => ["sessions", ...rest]
36245
+ summary: "create, list and run in local sandboxes",
36246
+ argv: (rest) => ["sandboxes", ...rest]
35348
36247
  },
35349
36248
  {
35350
36249
  command: "crew",
35351
36250
  ...SIDECAR,
35352
36251
  summary: "deploy, undeploy, pause and resume crew agents on this machine",
35353
36252
  argv: (rest) => ["crew", ...rest]
36253
+ },
36254
+ {
36255
+ command: "fleet",
36256
+ pkg: "@corenel/fleet",
36257
+ entry: "dist/server/main.js",
36258
+ summary: "run a fleet control plane (enroll, lease and revoke sidecars)",
36259
+ monorepoOnly: true,
36260
+ // 'corenel fleet start --data d' reads naturally; the server takes flags directly.
36261
+ argv: (rest) => rest[0] === "start" ? rest.slice(1) : rest
35354
36262
  }
35355
36263
  ];
35356
36264
  function findExtension(command) {
@@ -35358,6 +36266,13 @@ function findExtension(command) {
35358
36266
  }
35359
36267
  var EXTENSION_COMMANDS = EXTENSIONS.map((e) => e.command);
35360
36268
  function missingMessage(e) {
36269
+ if (e.monorepoOnly) {
36270
+ return [
36271
+ `${e.command} needs ${e.pkg}, which is not published yet and only runs from a checkout of the monorepo.`,
36272
+ "",
36273
+ " pnpm fleet:start"
36274
+ ].join("\n");
36275
+ }
35361
36276
  return [
35362
36277
  `${e.command} needs ${e.pkg}, which is not installed.`,
35363
36278
  "",
@@ -35448,15 +36363,15 @@ async function runExtension(ext, rest, look = {}) {
35448
36363
  }
35449
36364
 
35450
36365
  // src/commands.ts
35451
- import { stateDirName as stateDirName4 } from "@corenel/protocol";
35452
36366
  var COMMANDS = [
35453
36367
  { name: "", args: "", summary: "with no command: an interactive agent in this directory" },
35454
- { name: "run", args: '"<prompt>" [--allow-mutations] | --session ID "<prompt>"', summary: "one-shot turn, then exit -- refuses writes/shell unless --allow-mutations; --session runs the bare prompt in a sandbox instead and ignores every other flag" },
36368
+ { name: "run", args: '"<prompt>" [--allow-mutations] | --sandbox ID "<prompt>"', summary: "one-shot turn, then exit -- refuses writes/shell unless --allow-mutations; --sandbox runs the bare prompt in a sandbox instead and ignores every other flag" },
35455
36369
  { name: "run-agent", args: '<name> --input "<text>" [--allow-mutations]', summary: "run a crew agent (same refuse-by-default gate as run); events as JSON Lines on stdout" },
35456
36370
  { name: "sidecar", args: "[start] [flags]", summary: "run the sidecar on this machine" },
35457
36371
  { name: "acp", args: "<agent> [flags]", summary: "proxy an external coding agent under Corenel policy" },
35458
- { name: "sessions", args: "[list|show|create|run]", summary: "create, list and run in local sandbox sessions" },
36372
+ { name: "sandboxes", args: "[list|show|create|run|pause|resume|destroy]", summary: "create, list and run in local sandboxes" },
35459
36373
  { name: "crew", args: "deployments | deploy|undeploy|resume <agent> | pause <agent> --reason R", summary: "deploy, undeploy, pause and resume crew agents on this machine" },
36374
+ { name: "fleet", args: "[start] --data <dir> [flags] | keys new", summary: "run a fleet control plane (enroll, lease and revoke sidecars)" },
35460
36375
  { name: "login", args: "[--base URL]", summary: "sign in through your browser (device flow)" },
35461
36376
  { name: "auth", summary: "show whether you are signed in, and as what" },
35462
36377
  { name: "logout", summary: "forget the stored token" },
@@ -35474,16 +36389,16 @@ function isVersionFlag(a) {
35474
36389
  return a === "--version" || a === "-v" || a === "version";
35475
36390
  }
35476
36391
  function helpText(version2) {
35477
- const shown = COMMANDS.filter((c) => c.name);
36392
+ const shown2 = COMMANDS.filter((c) => c.name);
35478
36393
  const left = (c) => `corenel ${c.name}${c.args ? ` ${c.args}` : ""}`;
35479
- const width = Math.max(...shown.map((c) => left(c).length));
36394
+ const width = Math.max(...shown2.map((c) => left(c).length));
35480
36395
  const bare = COMMANDS.find((c) => !c.name);
35481
36396
  return [
35482
36397
  `corenel ${version2} \u2014 the harness, in node.`,
35483
36398
  "",
35484
36399
  "Usage:",
35485
36400
  ` corenel${" ".repeat(Math.max(1, width - 7))} ${bare ? bare.summary : ""}`,
35486
- ...shown.map((c) => ` ${left(c).padEnd(width)} ${c.summary}`),
36401
+ ...shown2.map((c) => ` ${left(c).padEnd(width)} ${c.summary}`),
35487
36402
  "",
35488
36403
  "Common flags:",
35489
36404
  " --model <id> model for this turn (default gpt-4o-mini)",
@@ -35508,13 +36423,9 @@ function helpText(version2) {
35508
36423
  " --version, -v print the version",
35509
36424
  " --help, -h print this",
35510
36425
  "",
35511
- "--resume reopens a CONVERSATION (this face's own chat log, saved under",
35512
- `${stateDirName4()}/sessions/) -- not the same thing as \`run --session ID\` or the`,
35513
- "`sessions` command below, which forward into a sandbox on the sidecar.",
35514
- "Same word, two different nouns.",
35515
- "",
35516
- "sidecar, acp, sessions and crew are provided by @corenel/sidecar, installed separately.",
36426
+ "sidecar, acp, sandboxes and crew are provided by @corenel/sidecar, installed separately.",
35517
36427
  "Each takes its own flags: `corenel sidecar --help`.",
36428
+ "fleet is provided by @corenel/fleet, installed separately: `corenel fleet --help`.",
35518
36429
  "",
35519
36430
  "Exit codes (corenel run, corenel run-agent):",
35520
36431
  " 0 the turn completed with an answer",
@@ -35694,7 +36605,9 @@ var KNOWN_KEYS = [
35694
36605
  "speech",
35695
36606
  "speechModel",
35696
36607
  "peerCallTimeoutMs",
35697
- "peers"
36608
+ "peers",
36609
+ "models",
36610
+ "providers"
35698
36611
  ];
35699
36612
  function daemonConfigPath(stateDir) {
35700
36613
  return join8(stateDir, "daemon.json");
@@ -36039,8 +36952,8 @@ function isQuit(line) {
36039
36952
  const t = line.trim().toLowerCase();
36040
36953
  return t === "/exit" || t === "/quit" || t === "exit" || t === "quit";
36041
36954
  }
36042
- function nextShownCursor(itemsLength, shown) {
36043
- return itemsLength < shown ? 0 : shown;
36955
+ function nextShownCursor(itemsLength, shown2) {
36956
+ return itemsLength < shown2 ? 0 : shown2;
36044
36957
  }
36045
36958
  function formatWriteDiff(diff) {
36046
36959
  if (diff.noop) return " (no change -- new content is identical to what's on disk)\n";
@@ -36175,12 +37088,12 @@ async function runRepl(deps) {
36175
37088
  ...deps.policy ? { policy: deps.policy } : {},
36176
37089
  ...deps.policySource ? { policySource: deps.policySource } : {}
36177
37090
  });
36178
- let shown = 0;
37091
+ let shown2 = 0;
36179
37092
  session.subscribe(() => {
36180
37093
  const items = session.getSnapshot().committed;
36181
- shown = nextShownCursor(items.length, shown);
36182
- for (; shown < items.length; shown++) {
36183
- const it = items[shown];
37094
+ shown2 = nextShownCursor(items.length, shown2);
37095
+ for (; shown2 < items.length; shown2++) {
37096
+ const it = items[shown2];
36184
37097
  if (it.kind !== "note") continue;
36185
37098
  writeLine(` ${it.level === "info" ? "" : "! "}${it.text}
36186
37099
  `);
@@ -36292,11 +37205,11 @@ async function runRepl(deps) {
36292
37205
  for (; ; ) {
36293
37206
  const line = await ask("\u203A ");
36294
37207
  if (line === null) break;
36295
- const text = line.trim();
36296
- if (!text) continue;
36297
- if (isQuit(text)) break;
37208
+ const text2 = line.trim();
37209
+ if (!text2) continue;
37210
+ if (isQuit(text2)) break;
36298
37211
  turnActive = true;
36299
- await session.submit(text);
37212
+ await session.submit(text2);
36300
37213
  turnActive = false;
36301
37214
  await askSuggestions();
36302
37215
  if (session.wantsExit) break;
@@ -36448,9 +37361,9 @@ ${rules(r.workspace)}`);
36448
37361
  return 0;
36449
37362
  }
36450
37363
  if (sub === "set") {
36451
- let current;
37364
+ let current2;
36452
37365
  try {
36453
- current = await svc.settingsStrict();
37366
+ current2 = await svc.settingsStrict();
36454
37367
  } catch (e) {
36455
37368
  deps.err(`could not read settings: ${e instanceof Error ? e.message : String(e)}
36456
37369
  `);
@@ -36458,13 +37371,13 @@ ${rules(r.workspace)}`);
36458
37371
  }
36459
37372
  if (arg === "threshold") {
36460
37373
  const threshold = Number(value);
36461
- await svc.saveSettings({ ...current, threshold });
37374
+ await svc.saveSettings({ ...current2, threshold });
36462
37375
  deps.out(threshold === 0 ? "suggestions off\n" : `suggest after ${threshold} approvals
36463
37376
  `);
36464
37377
  return 0;
36465
37378
  }
36466
37379
  const raw = value.toLowerCase();
36467
- await svc.saveSettings({ ...current, captureRawArgs: raw === "on" });
37380
+ await svc.saveSettings({ ...current2, captureRawArgs: raw === "on" });
36468
37381
  deps.out(`raw argument capture ${raw}
36469
37382
  `);
36470
37383
  return 0;
@@ -36626,8 +37539,8 @@ function shellTool(cwd) {
36626
37539
  import { procTools } from "@corenel/harness/tools/procs";
36627
37540
 
36628
37541
  // src/sidecarConnect.ts
36629
- import { stateDirName as stateDirName5 } from "@corenel/protocol";
36630
- import { SidecarHost, isSidecarKeyMismatch, isSidecarAccountRefusal } from "@corenel/harness/sidecar/host";
37542
+ import { stateDirName as stateDirName4 } from "@corenel/protocol";
37543
+ import { SidecarHost, isSidecarKeyMismatch, isSidecarAccountRefusal, isFleetLoginsRefusal } from "@corenel/harness/sidecar/host";
36631
37544
 
36632
37545
  // ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/wrapper.mjs
36633
37546
  var import_stream = __toESM(require_stream2(), 1);
@@ -36769,8 +37682,8 @@ function hostBackedProcs(host, seed = []) {
36769
37682
  if (!e) return { chunks: [], truncated: false };
36770
37683
  return { chunks: e.chunks.filter((c) => c.seq > sinceSeq), truncated: e.truncated };
36771
37684
  },
36772
- write: (procId, text) => {
36773
- void host.procInput(procId, text).catch(() => {
37685
+ write: (procId, text2) => {
37686
+ void host.procInput(procId, text2).catch(() => {
36774
37687
  });
36775
37688
  },
36776
37689
  kill: (procId) => {
@@ -36805,10 +37718,10 @@ function isCliDevice(v) {
36805
37718
  const k = r.privateJwk;
36806
37719
  return typeof r.id === "string" && B64.test(r.id) && typeof r.sidecarJkt === "string" && B43.test(r.sidecarJkt) && typeof k === "object" && k !== null && !!asEcPublicJwk({ kty: k.kty, crv: k.crv, x: k.x, y: k.y }) && typeof k.d === "string" && B43.test(k.d);
36807
37720
  }
36808
- function parse2(text) {
37721
+ function parse3(text2) {
36809
37722
  let raw;
36810
37723
  try {
36811
- raw = JSON.parse(text);
37724
+ raw = JSON.parse(text2);
36812
37725
  } catch {
36813
37726
  return null;
36814
37727
  }
@@ -36827,8 +37740,8 @@ function cliDeviceStore(path = cliDevicesPath()) {
36827
37740
  const file = fileTextStore(path);
36828
37741
  const dir = join10(path, "..");
36829
37742
  const load = async () => {
36830
- const text = await file.read();
36831
- return text === null ? { version: 1, devices: /* @__PURE__ */ Object.create(null) } : parse2(text);
37743
+ const text2 = await file.read();
37744
+ return text2 === null ? { version: 1, devices: /* @__PURE__ */ Object.create(null) } : parse3(text2);
36832
37745
  };
36833
37746
  const change = async (edit) => {
36834
37747
  const f = await load();
@@ -36967,6 +37880,11 @@ async function reportHandshakeFailure(e, url, usedDevice, store, identity2, fall
36967
37880
  return;
36968
37881
  }
36969
37882
  if (isSidecarAccountRefusal(e)) {
37883
+ if (isFleetLoginsRefusal(e)) {
37884
+ process.stderr.write(`corenel: the sidecar at ${url} did not accept this CLI: sign-in to it is limited by its fleet policy. A fleet admin can change that. -- ${fallback}
37885
+ `);
37886
+ return;
37887
+ }
36970
37888
  const problem = identity2.problem() ?? "the sidecar verified this account and did not admit it (not its owner, or not a member of its organization, or a device another member paired).";
36971
37889
  process.stderr.write(`corenel: the sidecar at ${url} did not accept this CLI: ${problem} -- ${fallback}
36972
37890
  `);
@@ -37018,7 +37936,7 @@ async function connectSidecarProcs(env = process.env, store = cliDeviceStore(),
37018
37936
  const host = new SidecarHost({
37019
37937
  channel,
37020
37938
  ...credential,
37021
- stateDir: stateDirName5(),
37939
+ stateDir: stateDirName4(),
37022
37940
  clientId: `corenel-cli-${process.pid}`,
37023
37941
  clientName: cliDeviceName(),
37024
37942
  onIdentityChallenge: identity2.answer,
@@ -37063,7 +37981,7 @@ async function connectMcpAdmin(env = process.env, store = cliDeviceStore(), iden
37063
37981
  const host = new SidecarHost({
37064
37982
  channel,
37065
37983
  ...credential,
37066
- stateDir: stateDirName5(),
37984
+ stateDir: stateDirName4(),
37067
37985
  clientId: `corenel-cli-${process.pid}`,
37068
37986
  clientName: cliDeviceName(),
37069
37987
  onIdentityChallenge: identity2.answer,
@@ -37226,8 +38144,7 @@ function isFailedTurn(outcome) {
37226
38144
  import { stateReadDirs } from "@corenel/protocol";
37227
38145
  import { loadModes, loadPersonas } from "@corenel/harness/prompts/config";
37228
38146
  import { composeAgentSystem as composeAgentSystem2 } from "@corenel/harness/prompts";
37229
- import { listSkills, stripFrontmatter } from "@corenel/harness/skills";
37230
- import { configWorkspace } from "@corenel/harness/prompts/host";
38147
+ import { listSkills, readSkillInstructions, stripFrontmatter } from "@corenel/harness/skills";
37231
38148
  function createIdentityState() {
37232
38149
  return { mode: "auto", persona: "" };
37233
38150
  }
@@ -37261,7 +38178,8 @@ async function armSkillById(id) {
37261
38178
  const found = skills.find((s) => s.name === id && s.instructions !== null);
37262
38179
  if (!found || !found.instructions) return null;
37263
38180
  try {
37264
- const raw = await configWorkspace().read(found.instructions);
38181
+ const raw = await readSkillInstructions(found.name);
38182
+ if (raw === null) return null;
37265
38183
  return { id: found.name, label: found.name, instructions: stripFrontmatter(raw) };
37266
38184
  } catch {
37267
38185
  return null;
@@ -37331,7 +38249,7 @@ async function resolveStrategyPrompt(files, id) {
37331
38249
  init_tools_node();
37332
38250
  import { readFile as readFile2, stat } from "node:fs/promises";
37333
38251
  import { join as join11 } from "node:path";
37334
- import { stateDirName as stateDirName6 } from "@corenel/protocol";
38252
+ import { stateDirName as stateDirName5 } from "@corenel/protocol";
37335
38253
  import { BUILTIN_POLICIES, STANDARD_POLICY as STANDARD_POLICY3, policyFromYaml } from "@corenel/harness/guardrail";
37336
38254
  var PolicyResolutionError = class extends Error {
37337
38255
  detail;
@@ -37346,9 +38264,9 @@ function isErrnoException(e) {
37346
38264
  return e instanceof Error && "code" in e;
37347
38265
  }
37348
38266
  async function loadRequiredPolicyFile(path, notFoundMessage) {
37349
- let text;
38267
+ let text2;
37350
38268
  try {
37351
- text = await readFile2(path, "utf8");
38269
+ text2 = await readFile2(path, "utf8");
37352
38270
  } catch (e) {
37353
38271
  if (isErrnoException(e) && e.code === "ENOENT") {
37354
38272
  throw new PolicyResolutionError(notFoundMessage);
@@ -37357,22 +38275,22 @@ async function loadRequiredPolicyFile(path, notFoundMessage) {
37357
38275
  `corenel: could not read policy file "${path}": ${e instanceof Error ? e.message : String(e)}`
37358
38276
  );
37359
38277
  }
37360
- return validateOrThrow(text, path);
38278
+ return validateOrThrow(text2, path);
37361
38279
  }
37362
38280
  async function loadDiscoveredPolicyFile(path) {
37363
- let text;
38281
+ let text2;
37364
38282
  try {
37365
- text = await readFile2(path, "utf8");
38283
+ text2 = await readFile2(path, "utf8");
37366
38284
  } catch (e) {
37367
38285
  if (isErrnoException(e) && e.code === "ENOENT") return void 0;
37368
38286
  throw new PolicyResolutionError(
37369
38287
  `corenel: could not read policy file "${path}": ${e instanceof Error ? e.message : String(e)}`
37370
38288
  );
37371
38289
  }
37372
- return validateOrThrow(text, path);
38290
+ return validateOrThrow(text2, path);
37373
38291
  }
37374
- function validateOrThrow(text, path) {
37375
- const result = policyFromYaml(text);
38292
+ function validateOrThrow(text2, path) {
38293
+ const result = policyFromYaml(text2);
37376
38294
  if (!result.ok || !result.policy) {
37377
38295
  throw new PolicyResolutionError(`corenel: policy file "${path}" is not a valid policy document.`, result.errors);
37378
38296
  }
@@ -37416,7 +38334,7 @@ async function resolvePolicy(opts) {
37416
38334
  }
37417
38335
  return { policy: STANDARD_POLICY3, source: { kind: "default" }, warnings };
37418
38336
  }
37419
- const workspacePath = join11(cwd, stateDirName6(), "policy.yaml");
38337
+ const workspacePath = join11(cwd, stateDirName5(), "policy.yaml");
37420
38338
  if (await fileExists(workspacePath)) {
37421
38339
  warnings.push(
37422
38340
  `corenel: ${workspacePath} ignored -- a policy inside the workspace can be written by the agent or arrive in a cloned repo. To use it for this folder, move it to ${projectPath}, or pass --policy ${workspacePath} explicitly.`
@@ -37450,14 +38368,14 @@ var McpHttpClient = class {
37450
38368
  }
37451
38369
  async listTools() {
37452
38370
  const result = await this.send("tools/list", {});
37453
- const tools = isRecord(result) ? result.tools : void 0;
38371
+ const tools = isRecord2(result) ? result.tools : void 0;
37454
38372
  if (!Array.isArray(tools)) return [];
37455
38373
  return tools.filter(isMcpTool);
37456
38374
  }
37457
38375
  async callTool(name, args) {
37458
38376
  const result = await this.send("tools/call", { name, arguments: args });
37459
- const record = isRecord(result) ? result : {};
37460
- return { content: record.content, isError: record.isError === true };
38377
+ const record2 = isRecord2(result) ? result : {};
38378
+ return { content: record2.content, isError: record2.isError === true };
37461
38379
  }
37462
38380
  /** Send one JSON-RPC request, retrying exactly once on a 401 that the
37463
38381
  * AuthProvider says it recovered from. `isRetry` prevents a second retry
@@ -37507,12 +38425,12 @@ var McpHttpClient = class {
37507
38425
  throw new Error(`MCP server "${this.server.name}" closed the stream without a response`);
37508
38426
  }
37509
38427
  const reader = res.body.getReader();
37510
- const decoder = new TextDecoder();
38428
+ const decoder3 = new TextDecoder();
37511
38429
  let buffer = "";
37512
38430
  try {
37513
38431
  for (; ; ) {
37514
38432
  const { done, value } = await reader.read();
37515
- if (value) buffer += decoder.decode(value, { stream: true });
38433
+ if (value) buffer += decoder3.decode(value, { stream: true });
37516
38434
  buffer = buffer.replace(/\r\n/g, "\n");
37517
38435
  let boundary = buffer.indexOf("\n\n");
37518
38436
  while (boundary !== -1) {
@@ -37543,7 +38461,7 @@ var McpHttpClient = class {
37543
38461
  } catch {
37544
38462
  return null;
37545
38463
  }
37546
- if (!isRecord(parsed) || parsed.id !== id) return null;
38464
+ if (!isRecord2(parsed) || parsed.id !== id) return null;
37547
38465
  if (!("result" in parsed) && !("error" in parsed)) return null;
37548
38466
  return parsed;
37549
38467
  }
@@ -37577,11 +38495,11 @@ var McpHttpClient = class {
37577
38495
  return headers;
37578
38496
  }
37579
38497
  };
37580
- function isRecord(value) {
38498
+ function isRecord2(value) {
37581
38499
  return typeof value === "object" && value !== null;
37582
38500
  }
37583
38501
  function isMcpTool(value) {
37584
- return isRecord(value) && typeof value.name === "string" && "inputSchema" in value;
38502
+ return isRecord2(value) && typeof value.name === "string" && "inputSchema" in value;
37585
38503
  }
37586
38504
 
37587
38505
  // ../mcp/src/config.ts
@@ -38345,7 +39263,7 @@ var McpRegistry = class {
38345
39263
  const inflight = this.slotConnecting.get(key);
38346
39264
  if (inflight) return inflight;
38347
39265
  const self2 = {};
38348
- const current = () => self2.attempt !== void 0 && this.slotConnecting.get(key) === self2.attempt;
39266
+ const current2 = () => self2.attempt !== void 0 && this.slotConnecting.get(key) === self2.attempt;
38349
39267
  const attempt = (async () => {
38350
39268
  const def = (await readMcpServers(this.stateDir, this.configEnv)).find((s) => s.name === server);
38351
39269
  if (!def) throw new Error(`MCP server "${server}" is not configured on this daemon`);
@@ -38354,10 +39272,10 @@ var McpRegistry = class {
38354
39272
  await client.initialize();
38355
39273
  return { client, tools: await client.listTools() };
38356
39274
  })(), SERVER_CONNECT_TIMEOUT_MS, `MCP server "${server}" timed out after ${SERVER_CONNECT_TIMEOUT_MS / 1e3}s`);
38357
- if (current()) this.slotted.set(key, entry);
39275
+ if (current2()) this.slotted.set(key, entry);
38358
39276
  return entry;
38359
39277
  })().finally(() => {
38360
- if (current()) this.slotConnecting.delete(key);
39278
+ if (current2()) this.slotConnecting.delete(key);
38361
39279
  });
38362
39280
  self2.attempt = attempt;
38363
39281
  this.slotConnecting.set(key, attempt);
@@ -38378,10 +39296,10 @@ var McpRegistry = class {
38378
39296
  };
38379
39297
 
38380
39298
  // ../mcp/src/policy.ts
38381
- import { PermissionService as PermissionService5, matchesAnyGlob as matchesAnyGlob2 } from "@corenel/harness/guardrail";
39299
+ import { PermissionService as PermissionService5, matchesAnyGlob as matchesAnyGlob3 } from "@corenel/harness/guardrail";
38382
39300
  function mcpCallAllowed(address, policy) {
38383
39301
  const allow = policy.tools?.allow ?? [];
38384
- if (!matchesAnyGlob2(address, allow)) {
39302
+ if (!matchesAnyGlob3(address, allow)) {
38385
39303
  return { ok: false, reason: `${address} is not allowed - add it with: corenel config add mcpAllow ${address}` };
38386
39304
  }
38387
39305
  const service = new PermissionService5({
@@ -38403,7 +39321,7 @@ function mcpCallAllowed(address, policy) {
38403
39321
  import {
38404
39322
  mcpToolAddress,
38405
39323
  parseMcpToolAddress,
38406
- mcpWireName,
39324
+ mcpWireName as mcpWireName2,
38407
39325
  parseMcpWireName,
38408
39326
  canEncodeMcpWireName,
38409
39327
  looksLikeMcpWireName
@@ -38443,7 +39361,7 @@ function asAgentTools(registry) {
38443
39361
  return out;
38444
39362
  }
38445
39363
  function toAgentTool(registry, server, tool) {
38446
- const name = mcpWireName(server, tool.name);
39364
+ const name = mcpWireName2(server, tool.name);
38447
39365
  const address = mcpToolAddress(server, tool.name);
38448
39366
  return {
38449
39367
  name,
@@ -38453,14 +39371,14 @@ function toAgentTool(registry, server, tool) {
38453
39371
  mutates: true,
38454
39372
  async run(args) {
38455
39373
  const result = await registry.call(server, tool.name, args);
38456
- const text = formatContent(result.content);
38457
- return result.isError ? `Error: ${text}` : text;
39374
+ const text2 = formatContent(result.content);
39375
+ return result.isError ? `Error: ${text2}` : text2;
38458
39376
  }
38459
39377
  };
38460
39378
  }
38461
39379
 
38462
39380
  // ../mcp/src/portTools.ts
38463
- import { MCP_CALL_FAILED, canEncodeMcpWireName as canEncodeMcpWireName2, mcpWireName as mcpWireName2, parseMcpToolAddress as parseMcpToolAddress2 } from "@corenel/protocol";
39381
+ import { MCP_CALL_FAILED, canEncodeMcpWireName as canEncodeMcpWireName2, mcpWireName as mcpWireName3, parseMcpToolAddress as parseMcpToolAddress2 } from "@corenel/protocol";
38464
39382
  var CALL_FAILED_TEXT = `Error: ${MCP_CALL_FAILED}: the MCP call failed before a result came back; it may or may not have run, so do not repeat it without checking.`;
38465
39383
 
38466
39384
  // ../mcp/src/gatedAgentTools.ts
@@ -38470,7 +39388,7 @@ function gatedAgentTools(registry, policy) {
38470
39388
  const wrapped = [];
38471
39389
  for (const { server, tool } of registry.tools()) {
38472
39390
  if (!canEncodeMcpWireName(server, tool.name)) continue;
38473
- const name = mcpWireName(server, tool.name);
39391
+ const name = mcpWireName2(server, tool.name);
38474
39392
  const original = byWireName.get(name);
38475
39393
  if (!original) continue;
38476
39394
  const address = mcpToolAddress(server, tool.name);
@@ -38613,12 +39531,12 @@ async function registerClient(meta, redirectUri, fetchImpl) {
38613
39531
  if (typeof body !== "object" || body === null || Array.isArray(body)) {
38614
39532
  throw new Error(`Client registration at ${meta.registrationEndpoint} returned a malformed response`);
38615
39533
  }
38616
- const record = body;
38617
- const clientId = record.client_id;
39534
+ const record2 = body;
39535
+ const clientId = record2.client_id;
38618
39536
  if (typeof clientId !== "string" || clientId.length === 0) {
38619
39537
  throw new Error(`Client registration at ${meta.registrationEndpoint} did not return a client_id`);
38620
39538
  }
38621
- const clientSecret = typeof record.client_secret === "string" ? record.client_secret : void 0;
39539
+ const clientSecret = typeof record2.client_secret === "string" ? record2.client_secret : void 0;
38622
39540
  return { clientId, clientSecret };
38623
39541
  }
38624
39542
 
@@ -38958,7 +39876,7 @@ async function agentSetup(argv, chosenModel) {
38958
39876
  try {
38959
39877
  const migrated = await migrateHomeLayout();
38960
39878
  if (migrated.moved.length) {
38961
- console.error(`layout: moved ${migrated.moved.length} item(s) into the current ~/${stateDirName7()} layout`);
39879
+ console.error(`layout: moved ${migrated.moved.length} item(s) into the current ~/${stateDirName6()} layout`);
38962
39880
  }
38963
39881
  for (const left of migrated.skipped) console.error(`layout: left ${left.path} alone (${left.reason})`);
38964
39882
  } catch (e) {
@@ -39026,19 +39944,23 @@ async function buildRunPermission(opts) {
39026
39944
  }) };
39027
39945
  }
39028
39946
  async function run(argv) {
39947
+ if (hasValueFlag(argv, "session")) {
39948
+ process.stderr.write("corenel: --session is not a flag of `run`. To run inside a sandbox use --sandbox ID.\n");
39949
+ process.exit(2);
39950
+ }
39029
39951
  const prompt = promptOf(argv);
39030
39952
  if (!prompt) {
39031
- process.stderr.write('usage: corenel run "<prompt>" [--model M] [--base URL] [--session ID] [--allow-mutations]\n [--max-usd N] [--max-tokens N] [--max-ms N] [--on-budget stop|warn]\n');
39953
+ process.stderr.write('usage: corenel run "<prompt>" [--model M] [--base URL] [--sandbox ID] [--allow-mutations]\n [--max-usd N] [--max-tokens N] [--max-ms N] [--on-budget stop|warn]\n');
39032
39954
  process.exit(2);
39033
39955
  }
39034
39956
  const budget = budgetConstraintsFrom(argv);
39035
- const session = flag(argv, "session", "");
39036
- if (session) {
39957
+ const sandbox = flag(argv, "sandbox", "");
39958
+ if (sandbox) {
39037
39959
  if (hasAllowMutationsFlag(argv) || hasValueFlag(argv, "model") || hasValueFlag(argv, "base") || budget) {
39038
- process.stderr.write("corenel: note: --session ignores every other flag on this line -- the sandboxed run uses its own defaults.\n");
39960
+ process.stderr.write("corenel: note: --sandbox ignores every other flag on this line -- the sandboxed run uses its own defaults.\n");
39039
39961
  }
39040
- const ext = findExtension("sessions");
39041
- process.exitCode = ext ? await runExtension(ext, ["run", session, prompt]) : 2;
39962
+ const ext = findExtension("sandboxes");
39963
+ process.exitCode = ext ? await runExtension(ext, ["run", sandbox, prompt]) : 2;
39042
39964
  return;
39043
39965
  }
39044
39966
  const { client, model, system, tools, policy, memory, disconnect } = await agentSetup(argv);
@@ -39395,8 +40317,9 @@ async function main() {
39395
40317
  }
39396
40318
  case "sidecar":
39397
40319
  case "acp":
39398
- case "sessions":
39399
- case "crew": {
40320
+ case "sandboxes":
40321
+ case "crew":
40322
+ case "fleet": {
39400
40323
  const ext = findExtension(cmd);
39401
40324
  process.exitCode = ext ? await runExtension(ext, rest) : 2;
39402
40325
  break;