@corenel/cli 0.10.0 → 0.12.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 +1200 -295
  2. package/package.json +8 -8
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);
25671
25813
  }
25672
- if (entry.name.startsWith("/") || /(^|\/)\.\.(\/|$)/.test(entry.name)) {
25673
- throw new Error(`Security violation: path traversal in entry: ${entry.name}`);
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);
25674
25875
  }
25675
- if (isSymlinkEntry(entry.unixPermissions)) {
25676
- throw new Error(`Security violation: symlink entry in archive: ${entry.name}`);
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);
25677
25879
  }
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})`);
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);
25682
26097
  }
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.`);
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);
26100
+ }
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);
26111
+ }
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);
26119
+ }
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) {
@@ -29045,11 +29572,11 @@ async function deviceLogin(opts) {
29045
29572
  body: JSON.stringify(body),
29046
29573
  signal: opts.signal
29047
29574
  });
29048
- const text = await res.text();
29575
+ const text2 = await res.text();
29049
29576
  try {
29050
- return JSON.parse(text);
29577
+ return JSON.parse(text2);
29051
29578
  } catch {
29052
- const looksLikeHtml = /^\s*</.test(text);
29579
+ const looksLikeHtml = /^\s*</.test(text2);
29053
29580
  throw new Error(
29054
29581
  `${url} answered ${res.status} with ${looksLikeHtml ? "an HTML page" : "a non-JSON body"}, not JSON.` + (res.status === 404 ? `
29055
29582
  That usually means --base is wrong. The device endpoints live under /api \u2014 try --base ${base.replace(/\/api$/, "")}/api` : "")
@@ -31247,7 +31774,7 @@ var require_extension = __commonJS({
31247
31774
  if (dest[name] === void 0) dest[name] = [elem];
31248
31775
  else dest[name].push(elem);
31249
31776
  }
31250
- function parse3(header) {
31777
+ function parse4(header) {
31251
31778
  const offers = /* @__PURE__ */ Object.create(null);
31252
31779
  let params = /* @__PURE__ */ Object.create(null);
31253
31780
  let mustUnescape = false;
@@ -31387,7 +31914,7 @@ var require_extension = __commonJS({
31387
31914
  }).join(", ");
31388
31915
  }).join(", ");
31389
31916
  }
31390
- module.exports = { format, parse: parse3 };
31917
+ module.exports = { format, parse: parse4 };
31391
31918
  }
31392
31919
  });
31393
31920
 
@@ -31421,7 +31948,7 @@ var require_websocket = __commonJS({
31421
31948
  var {
31422
31949
  EventTarget: { addEventListener, removeEventListener }
31423
31950
  } = require_event_target();
31424
- var { format, parse: parse3 } = require_extension();
31951
+ var { format, parse: parse4 } = require_extension();
31425
31952
  var { toBuffer } = require_buffer_util();
31426
31953
  var kAborted = Symbol("kAborted");
31427
31954
  var protocolVersions = [8, 13];
@@ -32098,7 +32625,7 @@ var require_websocket = __commonJS({
32098
32625
  }
32099
32626
  let extensions;
32100
32627
  try {
32101
- extensions = parse3(secWebSocketExtensions);
32628
+ extensions = parse4(secWebSocketExtensions);
32102
32629
  } catch (err) {
32103
32630
  const message = "Invalid Sec-WebSocket-Extensions header";
32104
32631
  abortHandshake(websocket, socket, message);
@@ -32390,7 +32917,7 @@ var require_subprotocol = __commonJS({
32390
32917
  "../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/lib/subprotocol.js"(exports, module) {
32391
32918
  "use strict";
32392
32919
  var { tokenChars } = require_validation();
32393
- function parse3(header) {
32920
+ function parse4(header) {
32394
32921
  const protocols = /* @__PURE__ */ new Set();
32395
32922
  let start = -1;
32396
32923
  let end = -1;
@@ -32426,7 +32953,7 @@ var require_subprotocol = __commonJS({
32426
32953
  protocols.add(protocol);
32427
32954
  return protocols;
32428
32955
  }
32429
- module.exports = { parse: parse3 };
32956
+ module.exports = { parse: parse4 };
32430
32957
  }
32431
32958
  });
32432
32959
 
@@ -32839,6 +33366,7 @@ import { resolveContextWindow as resolveContextWindow3, resolveContextWindowWith
32839
33366
  import { basename as basename5 } from "node:path";
32840
33367
  import { randomUUID } from "node:crypto";
32841
33368
  import { allTools as allTools3 } from "@corenel/harness/tools/builtins";
33369
+ import { splitByTier as splitByTier2 } from "@corenel/harness/tools/toolSearch";
32842
33370
  import { registerGuard as registerGuard2 } from "@corenel/harness/guards";
32843
33371
  import { setPromptHost } from "@corenel/harness/prompts/host";
32844
33372
  import { composeAgentSystem as composeAgentSystem3 } from "@corenel/harness/prompts";
@@ -32860,6 +33388,7 @@ import { PermissionService as PermissionService6 } from "@corenel/harness/guardr
32860
33388
  // src/nodeContext.ts
32861
33389
  import { ROOT_NODE_ID } from "@corenel/protocol";
32862
33390
  import { makeSpawn } from "@corenel/harness/core/spawn";
33391
+ import { isDeferredTool } from "@corenel/harness/tools/toolSearch";
32863
33392
  function inMemoryMemory() {
32864
33393
  const items = /* @__PURE__ */ new Map();
32865
33394
  return {
@@ -32943,6 +33472,8 @@ function nodeToolCtx(signal, opts = {}) {
32943
33472
  policy: opts.spawn.policy,
32944
33473
  permission: opts.spawn.permission,
32945
33474
  compression: opts.spawn.compression,
33475
+ // A sub-agent defers the same tools its parent does.
33476
+ deferTool: isDeferredTool,
32946
33477
  nodeId: ROOT_NODE_ID
32947
33478
  // No onNodeEvent: the CLI has no DAG canvas to forward sub-agent progress
32948
33479
  // to. A sub-agent's own tool-call/assistant events are invisible on this
@@ -32957,6 +33488,7 @@ __export(crew_exports, {
32957
33488
  AUTONOMY_TOOLS: () => AUTONOMY_TOOLS,
32958
33489
  CHECK_IN_BLOCK: () => CHECK_IN_BLOCK,
32959
33490
  COMMAND_CAPABILITIES: () => COMMAND_CAPABILITIES,
33491
+ CREW_DEFINITION_MARKERS: () => CREW_DEFINITION_MARKERS,
32960
33492
  CREW_EXCLUDED_TOOLS: () => CREW_EXCLUDED_TOOLS,
32961
33493
  CREW_SEG: () => CREW_SEG,
32962
33494
  DEPLOYMENT_FILE: () => DEPLOYMENT_FILE,
@@ -32966,16 +33498,23 @@ __export(crew_exports, {
32966
33498
  DONT_BLANK: () => DONT_BLANK,
32967
33499
  DONT_CONTROL: () => DONT_CONTROL,
32968
33500
  DONT_TOO_LONG: () => DONT_TOO_LONG,
33501
+ MANAGED_IN_SESSION_REFUSED: () => MANAGED_IN_SESSION_REFUSED,
33502
+ MANAGED_LOCKED: () => MANAGED_LOCKED,
33503
+ MANAGED_UNREADABLE: () => MANAGED_UNREADABLE,
33504
+ MANAGED_UNTRUSTED: () => MANAGED_UNTRUSTED,
32969
33505
  MAX_ROOM_BRIEF: () => MAX_ROOM_BRIEF,
33506
+ MCP_DENY_ALL: () => MCP_DENY_ALL,
32970
33507
  MEMORY_USERS_DIR: () => MEMORY_USERS_DIR,
32971
33508
  NOT_IN_YOUR_MEMORY: () => NOT_IN_YOUR_MEMORY,
32972
33509
  NO_ASKER_MEMORY_READ_ONLY: () => NO_ASKER_MEMORY_READ_ONLY,
33510
+ NO_TOOL_SENTINEL: () => NO_TOOL_SENTINEL,
32973
33511
  PROJECT_MARKER_FILE: () => PROJECT_MARKER_FILE,
32974
33512
  ROOM_KIND: () => ROOM_KIND,
32975
33513
  ROOM_MEMORY_READ_ONLY: () => ROOM_MEMORY_READ_ONLY,
32976
33514
  RUN_STATUS_VALUES: () => RUN_STATUS_VALUES,
32977
33515
  RoomReadError: () => RoomReadError,
32978
33516
  RoomStore: () => RoomStore,
33517
+ accessAllows: () => accessAllows,
32979
33518
  advance: () => advance,
32980
33519
  agentMemoryRoot: () => agentMemoryRoot,
32981
33520
  allowedAutonomy: () => allowedAutonomy,
@@ -32988,7 +33527,9 @@ __export(crew_exports, {
32988
33527
  callCandidates: () => callCandidates,
32989
33528
  callReach: () => callReach,
32990
33529
  closeRoomByHuman: () => closeRoomByHuman,
33530
+ copyCrewAgentAt: () => copyCrewAgentAt,
32991
33531
  crewAgentDir: () => crewAgentDir,
33532
+ crewAgentPresent: () => crewAgentPresent,
32992
33533
  crewAgentSessionsRoot: () => crewAgentSessionsRoot,
32993
33534
  crewBudgetConstraints: () => crewBudgetConstraints,
32994
33535
  crewListEntry: () => crewListEntry,
@@ -33003,9 +33544,11 @@ __export(crew_exports, {
33003
33544
  deploymentRootFor: () => deploymentRootFor,
33004
33545
  dontsProblems: () => dontsProblems,
33005
33546
  editFindingByHuman: () => editFindingByHuman,
33547
+ egressIsEmpty: () => egressIsEmpty,
33006
33548
  emptyDeployment: () => emptyDeployment,
33007
33549
  encodeRoomLine: () => encodeRoomLine,
33008
33550
  enforcedLevel: () => enforcedLevel,
33551
+ filterDefinition: () => filterDefinition,
33009
33552
  findingsPath: () => findingsPath,
33010
33553
  finishTurn: () => finishTurn,
33011
33554
  foldRoom: () => foldRoom,
@@ -33013,7 +33556,10 @@ __export(crew_exports, {
33013
33556
  grantOfferedTools: () => grantOfferedTools,
33014
33557
  grantsCommandTools: () => grantsCommandTools,
33015
33558
  interjectHuman: () => interjectHuman,
33559
+ intersectAllowList: () => intersectAllowList,
33016
33560
  isAutonomyPreset: () => isAutonomyPreset,
33561
+ isManaged: () => isManaged,
33562
+ isManagedOnDisk: () => isManagedOnDisk,
33017
33563
  isOrchestrator: () => isOrchestrator,
33018
33564
  isRoomSafeTool: () => isRoomSafeTool,
33019
33565
  isSafeProjectPath: () => isSafeProjectPath,
@@ -33024,19 +33570,26 @@ __export(crew_exports, {
33024
33570
  listCrewSummariesAt: () => listCrewSummariesAt,
33025
33571
  loadCrewAgentAt: () => loadCrewAgentAt,
33026
33572
  loadCrewAgentAtIfExists: () => loadCrewAgentAtIfExists,
33573
+ loadCrewAgentAtIfPresent: () => loadCrewAgentAtIfPresent,
33027
33574
  loadCrewSummaryAt: () => loadCrewSummaryAt,
33028
33575
  makeAgentMemoryProvider: () => makeAgentMemoryProvider,
33029
33576
  makeCrewTurnRuntime: () => makeCrewTurnRuntime,
33030
33577
  makePartitionedMemoryProvider: () => makePartitionedMemoryProvider,
33031
33578
  makeReadOnlyMemoryProvider: () => makeReadOnlyMemoryProvider,
33579
+ managedCap: () => managedCap,
33580
+ managedClaimOf: () => managedClaimOf,
33581
+ managedLockReason: () => managedLockReason,
33582
+ managedTrusted: () => managedTrusted,
33032
33583
  matchFileChange: () => matchFileChange,
33033
33584
  matchRunComplete: () => matchRunComplete,
33585
+ narrowDefinition: () => narrowDefinition,
33034
33586
  newCrewDraft: () => newCrewDraft,
33035
33587
  nextCronAfter: () => nextCronAfter,
33036
33588
  normalizeRunStatus: () => normalizeRunStatus,
33037
33589
  offersCommandTools: () => offersCommandTools,
33038
33590
  openLineOf: () => openLineOf,
33039
33591
  openRoom: () => openRoom,
33592
+ packagePolicyModels: () => packagePolicyModels,
33040
33593
  parseCron: () => parseCron,
33041
33594
  parseDeployment: () => parseDeployment,
33042
33595
  parseFrontmatter: () => parseFrontmatter,
@@ -33048,6 +33601,8 @@ __export(crew_exports, {
33048
33601
  projectMarkerPath: () => projectMarkerPath,
33049
33602
  readAutonomy: () => readAutonomy,
33050
33603
  readCrewListing: () => readCrewListing,
33604
+ readManagedEntry: () => readManagedEntry,
33605
+ readManagedRef: () => readManagedRef,
33051
33606
  registerCrewPolicy: () => registerCrewPolicy,
33052
33607
  resolveCallSet: () => resolveCallSet,
33053
33608
  resolveCrewModel: () => resolveCrewModel,
@@ -33062,6 +33617,8 @@ __export(crew_exports, {
33062
33617
  runRoom: () => runRoom,
33063
33618
  runTurnRuntime: () => runTurnRuntime,
33064
33619
  serializeDeployment: () => serializeDeployment,
33620
+ setDefinitionFilter: () => setDefinitionFilter,
33621
+ setManagedTrust: () => setManagedTrust,
33065
33622
  splitRunStatus: () => splitRunStatus,
33066
33623
  stampAuthor: () => stampAuthor,
33067
33624
  stringArray: () => stringArray,
@@ -33075,14 +33632,14 @@ __export(crew_exports, {
33075
33632
  });
33076
33633
 
33077
33634
  // ../crew/frontmatter.ts
33078
- var import_yaml = __toESM(require_dist(), 1);
33635
+ var import_yaml2 = __toESM(require_dist(), 1);
33079
33636
  var FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
33080
- function parseFrontmatter(text) {
33081
- const m = text.match(FRONTMATTER);
33082
- if (!m) return { meta: {}, body: text };
33637
+ function parseFrontmatter(text2) {
33638
+ const m = text2.match(FRONTMATTER);
33639
+ if (!m) return { meta: {}, body: text2 };
33083
33640
  let meta = {};
33084
33641
  try {
33085
- const parsed = import_yaml.default.parse(m[1]);
33642
+ const parsed = import_yaml2.default.parse(m[1]);
33086
33643
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
33087
33644
  meta = parsed;
33088
33645
  }
@@ -33093,7 +33650,7 @@ function parseFrontmatter(text) {
33093
33650
  }
33094
33651
 
33095
33652
  // ../crew/policy.ts
33096
- var import_yaml2 = __toESM(require_dist(), 1);
33653
+ var import_yaml3 = __toESM(require_dist(), 1);
33097
33654
  var LEVELS = ["allow", "ask", "owner", "deny"];
33098
33655
  var UNATTENDED = ["deny", "park", "allow"];
33099
33656
  function asLevel(v) {
@@ -33123,11 +33680,11 @@ function coercePermissions(v) {
33123
33680
  }
33124
33681
  return out;
33125
33682
  }
33126
- function parsePolicyYaml(text, agentName) {
33683
+ function parsePolicyYaml(text2, agentName) {
33127
33684
  let raw = {};
33128
- if (text.trim()) {
33685
+ if (text2.trim()) {
33129
33686
  try {
33130
- const parsed = import_yaml2.default.parse(text);
33687
+ const parsed = import_yaml3.default.parse(text2);
33131
33688
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
33132
33689
  raw = parsed;
33133
33690
  }
@@ -33144,6 +33701,7 @@ function parsePolicyYaml(text, agentName) {
33144
33701
  const rawPush = raw.pushWaitMs;
33145
33702
  const pushWaitMs = typeof rawPush === "number" && Number.isFinite(rawPush) && rawPush > 0 ? rawPush : void 0;
33146
33703
  const skills = Array.isArray(raw.skills) ? raw.skills.filter((s) => typeof s === "string" && s.trim() !== "").map((s) => s.trim()) : void 0;
33704
+ const workflows = Array.isArray(raw.workflows) ? raw.workflows.filter((s) => typeof s === "string" && s.trim() !== "").map((s) => s.trim()) : void 0;
33147
33705
  const donts = asDonts(raw.donts);
33148
33706
  const dontsModel = typeof raw.donts_model === "string" && raw.donts_model.trim() ? raw.donts_model.trim() : void 0;
33149
33707
  const policy = {
@@ -33174,6 +33732,7 @@ function parsePolicyYaml(text, agentName) {
33174
33732
  parkTimeoutMs,
33175
33733
  ...pushWaitMs !== void 0 ? { pushWaitMs } : {},
33176
33734
  ...skills && skills.length ? { skills } : {},
33735
+ ...workflows && workflows.length ? { workflows } : {},
33177
33736
  ...donts ? { donts } : {},
33178
33737
  ...dontsModel ? { donts_model: dontsModel } : {}
33179
33738
  };
@@ -33183,6 +33742,23 @@ function parsePolicyYaml(text, agentName) {
33183
33742
  return policy;
33184
33743
  }
33185
33744
 
33745
+ // ../crew/packagePolicy.ts
33746
+ var import_yaml4 = __toESM(require_dist(), 1);
33747
+ import { validateModelEgress } from "@corenel/protocol";
33748
+ function packagePolicyModels(text2) {
33749
+ let raw;
33750
+ try {
33751
+ raw = text2.trim() ? import_yaml4.default.parse(text2) : null;
33752
+ } catch {
33753
+ return { ok: false, error: "POLICY.yaml is not valid YAML" };
33754
+ }
33755
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return { ok: true, value: null };
33756
+ const models = raw.models;
33757
+ if (models === void 0) return { ok: true, value: null };
33758
+ const checked = validateModelEgress(models);
33759
+ return checked.ok ? { ok: true, value: checked.value } : { ok: false, error: checked.error };
33760
+ }
33761
+
33186
33762
  // ../crew/donts.ts
33187
33763
  import { DONTS_MAX, DONT_MAX_CHARS, hasControlChars } from "@corenel/protocol";
33188
33764
  var DONT_BLANK = "A don't cannot be blank.";
@@ -33338,8 +33914,8 @@ function allowedAutonomy(def) {
33338
33914
  function tightenAutonomy(def, requested) {
33339
33915
  if (!isAutonomyPreset(requested)) return { ok: false, reason: "Unknown autonomy level." };
33340
33916
  if (!fits(def, requested)) {
33341
- const current = readAutonomy(def);
33342
- const name = current === "custom" ? "a custom policy" : LABEL[current];
33917
+ const current2 = readAutonomy(def);
33918
+ const name = current2 === "custom" ? "a custom policy" : LABEL[current2];
33343
33919
  return { ok: false, reason: `This orchestrator is set to ${name}; a task cannot run as ${LABEL[requested]}. Change it on the agent.` };
33344
33920
  }
33345
33921
  const want = PRESET_LEVEL[requested];
@@ -33356,8 +33932,90 @@ function tightenAutonomy(def, requested) {
33356
33932
  }
33357
33933
 
33358
33934
  // ../crew/store.ts
33359
- var import_yaml3 = __toESM(require_dist(), 1);
33360
- import { flattenFiles as flattenFiles3 } from "@corenel/protocol";
33935
+ var import_yaml5 = __toESM(require_dist(), 1);
33936
+ init_dist();
33937
+ import {
33938
+ flattenFiles as flattenFiles3,
33939
+ PACKAGE_REF_FILE as PACKAGE_REF_FILE2,
33940
+ packageInstallDir,
33941
+ parentDir,
33942
+ parsePackageRef as parsePackageRef2
33943
+ } from "@corenel/protocol";
33944
+
33945
+ // ../crew/notFound.ts
33946
+ function isNotFound(e) {
33947
+ if (!e || typeof e !== "object") return false;
33948
+ const o = e;
33949
+ if (o.code === "ENOENT" || o.code === "ENOTDIR" || o.name === "NotFoundError") return true;
33950
+ return typeof o.message === "string" && /^(not found|no such file( or directory)?)(:|$)/i.test(o.message);
33951
+ }
33952
+
33953
+ // ../crew/managed.ts
33954
+ import { PACKAGE_REF_FILE, parsePackageRef } from "@corenel/protocol";
33955
+ var MANAGED_UNTRUSTED = "managed by a deployment this node does not hold";
33956
+ var MANAGED_LOCKED = "is managed by the fleet; its definition and settings cannot be changed, copied or deleted on this machine";
33957
+ 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";
33958
+ var trust = null;
33959
+ function setManagedTrust(check) {
33960
+ trust = check;
33961
+ }
33962
+ function managedTrusted(name, managed) {
33963
+ if (!trust) return false;
33964
+ try {
33965
+ return trust(name, managed) === true;
33966
+ } catch {
33967
+ return false;
33968
+ }
33969
+ }
33970
+ function isManaged(x) {
33971
+ return x.source?.managed !== void 0;
33972
+ }
33973
+ async function readManagedRef(files, root, name) {
33974
+ const path = `${root}/${name}/${PACKAGE_REF_FILE}`;
33975
+ try {
33976
+ const st = await files.stat(path);
33977
+ if (st === null) return null;
33978
+ } catch (e) {
33979
+ return isNotFound(e) ? null : "unknown";
33980
+ }
33981
+ let text2;
33982
+ try {
33983
+ text2 = await files.read(path);
33984
+ } catch {
33985
+ return "unknown";
33986
+ }
33987
+ return managedClaimOf(text2);
33988
+ }
33989
+ function managedClaimOf(text2) {
33990
+ let ref;
33991
+ try {
33992
+ ref = parsePackageRef(text2);
33993
+ } catch {
33994
+ return "unknown";
33995
+ }
33996
+ return ref.managed ? { ...ref, managed: ref.managed } : null;
33997
+ }
33998
+ async function readManagedEntry(files, root, name) {
33999
+ const ref = await readManagedRef(files, root, name);
34000
+ return ref === null || ref === "unknown" ? ref : ref.managed;
34001
+ }
34002
+ async function managedLockReason(files, root, name) {
34003
+ const m = await readManagedEntry(files, root, name);
34004
+ if (m === null) return null;
34005
+ return m === "unknown" ? MANAGED_UNREADABLE : MANAGED_LOCKED;
34006
+ }
34007
+ async function isManagedOnDisk(files, root, name) {
34008
+ return await readManagedEntry(files, root, name) !== null;
34009
+ }
34010
+
34011
+ // ../crew/definitionFilter.ts
34012
+ var current = null;
34013
+ function setDefinitionFilter(f) {
34014
+ current = f;
34015
+ }
34016
+ function filterDefinition(def, at) {
34017
+ return current ? current(def, at) : def;
34018
+ }
33361
34019
 
33362
34020
  // ../crew/sessionBinding.ts
33363
34021
  var SESSION_NAME_RE = /^[a-z0-9_-]{1,32}$/;
@@ -33414,6 +34072,73 @@ async function readOr(files, path, fallback = "") {
33414
34072
  return fallback;
33415
34073
  }
33416
34074
  }
34075
+ var DEFINITION_FILES = ["AGENT.md", "SOUL.md", "PERSONA.md", "POLICY.yaml"];
34076
+ var textDecoder3 = new TextDecoder();
34077
+ async function isFile(files, path) {
34078
+ try {
34079
+ return (await files.stat(path))?.kind === "file";
34080
+ } catch (e) {
34081
+ if (isNotFound(e)) return false;
34082
+ throw e;
34083
+ }
34084
+ }
34085
+ var CREW_DEFINITION_MARKERS = ["AGENT.md", PACKAGE_REF_FILE2];
34086
+ async function crewAgentPresent(files, root, name) {
34087
+ if (!isValidAgentName(name)) return false;
34088
+ for (const f of CREW_DEFINITION_MARKERS) {
34089
+ if (await isFile(files, `${root}/${name}/${f}`)) return true;
34090
+ }
34091
+ return false;
34092
+ }
34093
+ async function definitionSource(files, root, name) {
34094
+ const dir = `${root}/${name}`;
34095
+ if (!await isFile(files, `${dir}/${PACKAGE_REF_FILE2}`)) {
34096
+ return { read: (f) => readOr(files, `${dir}/${f}`) };
34097
+ }
34098
+ for (const f of DEFINITION_FILES) {
34099
+ if (await isFile(files, `${dir}/${f}`)) {
34100
+ throw new Error(`crew agent ${name}: the folder holds both ${PACKAGE_REF_FILE2} and definition files (${f}); remove one`);
34101
+ }
34102
+ }
34103
+ let ref;
34104
+ try {
34105
+ ref = parsePackageRef2(await files.read(`${dir}/${PACKAGE_REF_FILE2}`));
34106
+ } catch (e) {
34107
+ throw new Error(`crew agent ${name}: ${e.message}`);
34108
+ }
34109
+ if (ref.managed && !managedTrusted(name, ref.managed)) {
34110
+ throw new Error(`crew agent ${name}: ${MANAGED_UNTRUSTED}`);
34111
+ }
34112
+ const label = `${ref.package}@${ref.version} (${ref.digest})`;
34113
+ const readBytes = files.readBytes?.bind(files);
34114
+ if (!readBytes) {
34115
+ 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)`);
34116
+ }
34117
+ const installDir = packageInstallDir(parentDir(root), "agent", ref);
34118
+ let pkg;
34119
+ try {
34120
+ pkg = await verifyInstalled(async (rel) => {
34121
+ try {
34122
+ return await readBytes(`${installDir}/${rel}`);
34123
+ } catch {
34124
+ return null;
34125
+ }
34126
+ }, ref.digest, { name: ref.package, range: ref.version });
34127
+ } catch (e) {
34128
+ if (isPackageVerificationError(e) && e.code === "FILE_MISSING" && e.path === ARCHIVE_COPY) {
34129
+ throw new Error(`crew agent ${name}: package ${label} is not installed`);
34130
+ }
34131
+ throw new Error(`crew agent ${name}: package ${ref.package}@${ref.version} failed verification: ${e.message}`);
34132
+ }
34133
+ const source = { kind: "package", package: ref.package, version: ref.version, digest: ref.digest, ...ref.managed ? { managed: ref.managed } : {} };
34134
+ return {
34135
+ read: async (f) => {
34136
+ const b = pkg.files.get(f);
34137
+ return b ? textDecoder3.decode(b) : "";
34138
+ },
34139
+ source
34140
+ };
34141
+ }
33417
34142
  function parseTriggers(meta) {
33418
34143
  const raw = meta.triggers;
33419
34144
  if (!Array.isArray(raw)) return [];
@@ -33480,13 +34205,16 @@ function parseWorkRoots(raw) {
33480
34205
  }
33481
34206
  return Object.keys(out).length ? out : void 0;
33482
34207
  }
33483
- function parseSettings(text) {
34208
+ function parseSettings(text2) {
33484
34209
  try {
33485
- const raw = JSON.parse(text);
34210
+ const raw = JSON.parse(text2);
33486
34211
  if (raw && typeof raw === "object" && !Array.isArray(raw)) {
33487
34212
  const o = raw;
33488
34213
  return {
33489
34214
  model: typeof o.model === "string" ? o.model : void 0,
34215
+ /* Meaningful only for a package agent (its AGENT.md is immutable); a
34216
+ * local agent's switch lives in AGENT.md and this is ignored for it. */
34217
+ enabled: typeof o.enabled === "boolean" ? o.enabled : void 0,
33490
34218
  temperature: typeof o.temperature === "number" ? o.temperature : void 0,
33491
34219
  /* Carried through as-is. Validation belongs to the daemon, which is the
33492
34220
  * only side that knows its own approved roots -- checking here would be
@@ -33500,45 +34228,60 @@ function parseSettings(text) {
33500
34228
  }
33501
34229
  return {};
33502
34230
  }
34231
+ function packageModelsOf(policyText) {
34232
+ const m = packagePolicyModels(policyText);
34233
+ if (!m.ok) return { packageModels: { allow: [] } };
34234
+ return m.value === null ? {} : { packageModels: m.value };
34235
+ }
33503
34236
  async function loadCrewAgentAt(files, root, name, scope = "workspace") {
33504
34237
  if (!isValidAgentName(name)) throw new Error(`invalid crew agent name: ${name}`);
33505
34238
  const dir = `${root}/${name}`;
33506
- const { meta, body } = parseFrontmatter(await readOr(files, `${dir}/AGENT.md`));
34239
+ const src = await definitionSource(files, root, name);
34240
+ const { meta, body } = parseFrontmatter(await src.read("AGENT.md"));
34241
+ const settings = parseSettings(await readOr(files, `${dir}/settings.json`, "{}"));
34242
+ if (!src.source) delete settings.enabled;
33507
34243
  const session = parseSessionBinding(meta);
33508
34244
  const orchestration = parseOrchestration(meta);
33509
34245
  const tags = (0, tags_exports.parseTags)(meta);
33510
- return {
34246
+ const policyText = await src.read("POLICY.yaml");
34247
+ return filterDefinition({
33511
34248
  name,
33512
34249
  jobTitle: typeof meta.jobTitle === "string" ? meta.jobTitle : "",
33513
34250
  description: typeof meta.description === "string" ? meta.description : "",
33514
34251
  ...tags ? { tags } : {},
33515
34252
  scope,
33516
- enabled: meta.enabled !== false,
33517
- // absent/anything-but-false -> enabled
34253
+ // absent/anything-but-false -> enabled; a package agent's switch is in settings.json
34254
+ enabled: src.source ? settings.enabled !== false : meta.enabled !== false,
33518
34255
  triggers: parseTriggers(meta),
33519
34256
  instructions: body,
33520
- soul: await readOr(files, `${dir}/SOUL.md`),
33521
- persona: await readOr(files, `${dir}/PERSONA.md`),
33522
- policy: parsePolicyYaml(await readOr(files, `${dir}/POLICY.yaml`), name),
33523
- settings: parseSettings(await readOr(files, `${dir}/settings.json`, "{}")),
34257
+ soul: await src.read("SOUL.md"),
34258
+ persona: await src.read("PERSONA.md"),
34259
+ policy: parsePolicyYaml(policyText, name),
34260
+ settings,
33524
34261
  budget: parseBudget(meta),
33525
34262
  canCall: parseCanCall(meta),
33526
34263
  canCallAll: meta.canCallAll === true,
33527
34264
  ...orchestration !== void 0 ? { orchestration } : {},
33528
34265
  ...session.kind === "binding" ? { session: session.binding } : {},
33529
- ...session.kind === "malformed" ? { sessionError: session.reason } : {}
33530
- };
34266
+ ...session.kind === "malformed" ? { sessionError: session.reason } : {},
34267
+ ...src.source ? { source: src.source } : {},
34268
+ ...src.source ? packageModelsOf(policyText) : {}
34269
+ }, { files, root });
33531
34270
  }
33532
34271
  async function loadCrewAgentAtIfExists(files, root, name, scope = "workspace") {
33533
34272
  if (!isValidAgentName(name)) return null;
33534
34273
  try {
33535
- const st = await files.stat(`${root}/${name}/AGENT.md`);
33536
- if (st?.kind !== "file") return null;
34274
+ if (!await crewAgentPresent(files, root, name)) return null;
33537
34275
  return await loadCrewAgentAt(files, root, name, scope);
33538
34276
  } catch {
33539
34277
  return null;
33540
34278
  }
33541
34279
  }
34280
+ async function loadCrewAgentAtIfPresent(files, root, name, scope = "workspace") {
34281
+ if (!isValidAgentName(name)) return null;
34282
+ if (!await crewAgentPresent(files, root, name)) return null;
34283
+ return loadCrewAgentAt(files, root, name, scope);
34284
+ }
33542
34285
  async function listCrewAgentsAt(files, root, opts = {}) {
33543
34286
  let nodes;
33544
34287
  try {
@@ -33567,6 +34310,7 @@ function serializePolicy(policy) {
33567
34310
  if (policy.mutatingDefault) ordered.mutatingDefault = policy.mutatingDefault;
33568
34311
  if (policy.permissions && Object.keys(policy.permissions).length) ordered.permissions = policy.permissions;
33569
34312
  if (policy.skills && policy.skills.length) ordered.skills = policy.skills;
34313
+ if (policy.workflows && policy.workflows.length) ordered.workflows = policy.workflows;
33570
34314
  if (policy.donts && policy.donts.length) ordered.donts = policy.donts;
33571
34315
  if (policy.donts_model) ordered.donts_model = policy.donts_model;
33572
34316
  if (policy.tools) ordered.tools = policy.tools;
@@ -33575,7 +34319,7 @@ function serializePolicy(policy) {
33575
34319
  if (policy.unattended) ordered.unattended = policy.unattended;
33576
34320
  if (typeof policy.parkTimeoutMs === "number") ordered.parkTimeoutMs = policy.parkTimeoutMs;
33577
34321
  if (typeof policy.pushWaitMs === "number") ordered.pushWaitMs = policy.pushWaitMs;
33578
- return import_yaml3.default.stringify(ordered, { lineWidth: 0 });
34322
+ return import_yaml5.default.stringify(ordered, { lineWidth: 0 });
33579
34323
  }
33580
34324
  function serializeAgentMd(def) {
33581
34325
  const meta = { name: def.name };
@@ -33601,13 +34345,15 @@ function serializeAgentMd(def) {
33601
34345
  meta.session = def.session.createIfMissing ? { name: def.session.name } : { name: def.session.name, createIfMissing: false };
33602
34346
  }
33603
34347
  return `---
33604
- ${import_yaml3.default.stringify(meta, { lineWidth: 0 })}---
34348
+ ${import_yaml5.default.stringify(meta, { lineWidth: 0 })}---
33605
34349
  ${def.instructions.replace(/\n+$/, "")}
33606
34350
  `;
33607
34351
  }
33608
34352
  async function loadCrewSummaryAt(files, root, name, scope = "workspace") {
33609
34353
  if (!isValidAgentName(name)) throw new Error(`invalid crew agent name: ${name}`);
33610
- const { meta } = parseFrontmatter(await readOr(files, `${root}/${name}/AGENT.md`));
34354
+ const src = await definitionSource(files, root, name);
34355
+ const { meta } = parseFrontmatter(await src.read("AGENT.md"));
34356
+ const enabled = src.source ? parseSettings(await readOr(files, `${root}/${name}/settings.json`, "{}")).enabled !== false : meta.enabled !== false;
33611
34357
  const tags = (0, tags_exports.parseTags)(meta);
33612
34358
  return {
33613
34359
  name,
@@ -33615,20 +34361,30 @@ async function loadCrewSummaryAt(files, root, name, scope = "workspace") {
33615
34361
  description: typeof meta.description === "string" ? meta.description : "",
33616
34362
  ...tags ? { tags } : {},
33617
34363
  triggers: parseTriggers(meta).map((t) => t.type),
33618
- enabled: meta.enabled !== false,
34364
+ enabled,
33619
34365
  scope,
33620
34366
  delegates: Array.isArray(meta.canCall) && meta.canCall.length > 0 || meta.canCallAll === true,
33621
- orchestrator: orchestrationBlock(meta) !== void 0
34367
+ orchestrator: orchestrationBlock(meta) !== void 0,
34368
+ ...src.source ? { source: src.source } : {}
33622
34369
  };
33623
34370
  }
34371
+ async function referencedSource(files, dir) {
34372
+ try {
34373
+ const ref = parsePackageRef2(await files.read(`${dir}/${PACKAGE_REF_FILE2}`));
34374
+ return { kind: "package", package: ref.package, version: ref.version, digest: ref.digest, ...ref.managed ? { managed: ref.managed } : {} };
34375
+ } catch {
34376
+ return void 0;
34377
+ }
34378
+ }
33624
34379
  async function listCrewSummariesAt(files, root, scope = "workspace", opts = {}) {
33625
34380
  const names = await listCrewAgentsAt(files, root, opts);
33626
34381
  const out = [];
33627
34382
  for (const name of names.sort()) {
33628
34383
  try {
33629
34384
  out.push(await loadCrewSummaryAt(files, root, name, scope));
33630
- } catch {
33631
- out.push({ name, description: "", enabled: true, scope, delegates: false, orchestrator: false });
34385
+ } catch (e) {
34386
+ const source = await referencedSource(files, `${root}/${name}`);
34387
+ out.push({ name, description: "", enabled: false, scope, delegates: false, orchestrator: false, ...source ? { source } : {}, loadError: e.message });
33632
34388
  }
33633
34389
  }
33634
34390
  return out;
@@ -33642,22 +34398,37 @@ async function put(files, path, content) {
33642
34398
  }
33643
34399
  function stripWorkRoots(settings) {
33644
34400
  const { workRoots: _workRoots, ...rest } = settings;
34401
+ for (const k of Object.keys(rest)) {
34402
+ if (rest[k] === void 0) delete rest[k];
34403
+ }
33645
34404
  return rest;
33646
34405
  }
33647
34406
  async function dontsUnchanged(files, dir, def) {
33648
- let text;
34407
+ let text2;
33649
34408
  try {
33650
- text = await files.read(`${dir}/POLICY.yaml`);
34409
+ text2 = await files.read(`${dir}/POLICY.yaml`);
33651
34410
  } catch {
33652
34411
  return false;
33653
34412
  }
33654
- const stored = parsePolicyYaml(text, def.name).donts ?? [];
34413
+ const stored = parsePolicyYaml(text2, def.name).donts ?? [];
33655
34414
  const next = (def.policy.donts ?? []).map((d) => d.trim());
33656
34415
  return stored.length === next.length && stored.every((d, i) => d === next[i]);
33657
34416
  }
33658
34417
  async function writeCrewAgentAt(files, root, def) {
33659
34418
  if (!isValidAgentName(def.name)) throw new Error(`invalid crew agent name: ${def.name}`);
33660
34419
  const dir = `${root}/${def.name}`;
34420
+ if (await isFile(files, `${dir}/${PACKAGE_REF_FILE2}`)) {
34421
+ const locked2 = await managedLockReason(files, root, def.name);
34422
+ if (locked2) throw new Error(`crew agent ${def.name} ${locked2}`);
34423
+ await put(files, `${dir}/settings.json`, `${JSON.stringify(stripWorkRoots({ ...def.settings, enabled: def.enabled }), null, 2)}
34424
+ `);
34425
+ return;
34426
+ }
34427
+ if (def.source) {
34428
+ 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`);
34429
+ }
34430
+ const localSettings = { ...def.settings };
34431
+ delete localSettings.enabled;
33661
34432
  if (!await dontsUnchanged(files, dir, def)) {
33662
34433
  const problems = dontsProblems(def.policy);
33663
34434
  if (problems.length) throw new Error(problems.join(" "));
@@ -33666,11 +34437,26 @@ async function writeCrewAgentAt(files, root, def) {
33666
34437
  await put(files, `${dir}/SOUL.md`, def.soul);
33667
34438
  await put(files, `${dir}/PERSONA.md`, def.persona);
33668
34439
  await put(files, `${dir}/POLICY.yaml`, serializePolicy(def.policy));
33669
- await put(files, `${dir}/settings.json`, `${JSON.stringify(stripWorkRoots(def.settings), null, 2)}
34440
+ await put(files, `${dir}/settings.json`, `${JSON.stringify(stripWorkRoots(localSettings), null, 2)}
33670
34441
  `);
33671
34442
  }
34443
+ async function copyCrewAgentAt(files, root, from, to) {
34444
+ if (!isValidAgentName(to)) throw new Error(`invalid crew agent name: ${to}`);
34445
+ if (await crewAgentPresent(files, root, to)) throw new Error(`crew agent ${to} already exists`);
34446
+ if (!await crewAgentPresent(files, root, from)) throw new Error(`crew agent ${from} is no longer here`);
34447
+ const def = await loadCrewAgentAt(files, root, from);
34448
+ const locked2 = isManaged(def) ? MANAGED_LOCKED : await managedLockReason(files, root, from);
34449
+ if (locked2) throw new Error(`crew agent ${from} ${locked2}`);
34450
+ const copy = { ...def, name: to, settings: { ...def.settings } };
34451
+ delete copy.source;
34452
+ delete copy.settings.enabled;
34453
+ await writeCrewAgentAt(files, root, copy);
34454
+ return copy;
34455
+ }
33672
34456
  async function deleteCrewAgentAt(files, root, name) {
33673
34457
  if (!isValidAgentName(name)) throw new Error(`invalid crew agent name: ${name}`);
34458
+ const locked2 = await managedLockReason(files, root, name);
34459
+ if (locked2) throw new Error(`crew agent ${name} ${locked2}`);
33674
34460
  await files.remove(`${root}/${name}`);
33675
34461
  }
33676
34462
 
@@ -33716,6 +34502,7 @@ import { saveCustomPolicy } from "@corenel/harness/guardrail";
33716
34502
  import { allTools } from "@corenel/harness/tools/builtins";
33717
34503
  import { registerSyncConfig, readConfigSyncRendered } from "@corenel/harness/prompts/syncConfig";
33718
34504
  import { promptHost } from "@corenel/harness/prompts/host";
34505
+ import { FIT_THE_PROJECT } from "@corenel/harness/prompts/fitProject";
33719
34506
  import { makeOrchestrationTools } from "@corenel/harness/tools/orchestrationSet";
33720
34507
 
33721
34508
  // ../crew/delegates.ts
@@ -33804,7 +34591,8 @@ function identityBlock() {
33804
34591
  You are a ${app} agent, one member of a crew of specialized agents serving the user. What follows defines your role in that crew.`;
33805
34592
  }
33806
34593
  function buildSystemExtra(def, memoryLocation) {
33807
- const parts = [identityBlock()];
34594
+ const parts = [identityBlock(), `--- Working in a project ---
34595
+ ${FIT_THE_PROJECT}`];
33808
34596
  if (def.jobTitle?.trim()) parts.push(`--- Role ---
33809
34597
  ${def.jobTitle.trim()}`);
33810
34598
  if (def.soul.trim()) parts.push(`--- Soul ---
@@ -33948,10 +34736,10 @@ function normalizeRunStatus(raw) {
33948
34736
  return RUN_STATUS_BY_RAW.get((raw ?? "").trim()) ?? "error";
33949
34737
  }
33950
34738
  function splitRunStatus(raw) {
33951
- const text = (raw ?? "").trim();
33952
- const stopReason = normalizeRunStatus(text);
33953
- if (stopReason !== "error" || text === "error" || !text) return { stopReason };
33954
- return { stopReason, message: text };
34739
+ const text2 = (raw ?? "").trim();
34740
+ const stopReason = normalizeRunStatus(text2);
34741
+ if (stopReason !== "error" || text2 === "error" || !text2) return { stopReason };
34742
+ return { stopReason, message: text2 };
33955
34743
  }
33956
34744
  function matchRunComplete(config, completion) {
33957
34745
  const after = stringArray(config.after);
@@ -33985,11 +34773,11 @@ function emptyDeployment() {
33985
34773
  function deploymentKey(name, wsId) {
33986
34774
  return wsId ? `workspaces/${wsId}/crew/${name}` : `crew/${name}`;
33987
34775
  }
33988
- function parseDeployment(text) {
34776
+ function parseDeployment(text2) {
33989
34777
  const out = emptyDeployment();
33990
34778
  let raw;
33991
34779
  try {
33992
- raw = JSON.parse(text);
34780
+ raw = JSON.parse(text2);
33993
34781
  } catch {
33994
34782
  return out;
33995
34783
  }
@@ -34140,11 +34928,12 @@ function nextCronAfter(f, from) {
34140
34928
  }
34141
34929
 
34142
34930
  // ../crew/offerGrants.ts
34143
- import { policyNamesTool, toolGateCovers } from "@corenel/harness/guardrail";
34931
+ import { matchesAnyGlob as matchesAnyGlob2, policyNamesTool, toolGateCovers } from "@corenel/harness/guardrail";
34144
34932
  import { toolAddress as toolAddress2 } from "@corenel/harness/tools/namespaces";
34145
- function grantOfferedTools(policy, offered) {
34933
+ function grantOfferedTools(policy, offered, cap = null) {
34146
34934
  const missing = offered.filter((name) => {
34147
34935
  const subject = { name, address: toolAddress2({ name }) };
34936
+ if (cap !== null && !matchesAnyGlob2(subject.name, cap) && !matchesAnyGlob2(subject.address, cap)) return false;
34148
34937
  return !policyNamesTool(policy, subject) && !toolGateCovers(policy, subject);
34149
34938
  });
34150
34939
  if (!missing.length) return policy;
@@ -34152,6 +34941,93 @@ function grantOfferedTools(policy, offered) {
34152
34941
  for (const name of missing) permissions[name] = "allow";
34153
34942
  return { ...policy, permissions };
34154
34943
  }
34944
+ function managedCap(def) {
34945
+ if (!def.source?.managed) return null;
34946
+ const allow = def.policy.tools?.allow ?? [];
34947
+ return allow.length ? [...allow] : null;
34948
+ }
34949
+
34950
+ // ../crew/acl.ts
34951
+ import {
34952
+ intersectModelEgress,
34953
+ toolsWider
34954
+ } from "@corenel/protocol";
34955
+ var NO_TOOL_SENTINEL = "__none__";
34956
+ var MCP_DENY_ALL = "mcp:**";
34957
+ var MANAGED_IN_SESSION_REFUSED = "managed agents run only on this machine's daemon, never in a session";
34958
+ function uniq(xs) {
34959
+ return [...new Set(xs)];
34960
+ }
34961
+ function intersectAllowList(pkg, acl) {
34962
+ const p = pkg ?? [];
34963
+ const entries = uniq(acl);
34964
+ const widened = toolsWider(entries, p);
34965
+ return { allow: entries.filter((e) => !widened.includes(e)), widened };
34966
+ }
34967
+ function egressIsEmpty(e) {
34968
+ if (e === "any") return false;
34969
+ return e.allow.every((ep) => ep.models !== "*" && ep.models.length === 0);
34970
+ }
34971
+ function accessAllows(level, userId, adminId) {
34972
+ if (level === void 0 || level === "members") return true;
34973
+ return !!userId && !!adminId && userId === adminId;
34974
+ }
34975
+ function lower(a, b) {
34976
+ if (a === void 0) return b;
34977
+ if (b === void 0) return a;
34978
+ return Math.min(a, b);
34979
+ }
34980
+ function narrowDefinition(def, acl, nodePolicy) {
34981
+ let refused;
34982
+ const refuse = (why) => {
34983
+ if (refused === void 0) refused = why;
34984
+ };
34985
+ if (def.session !== void 0 || def.sessionError !== void 0) refuse(MANAGED_IN_SESSION_REFUSED);
34986
+ const pkgAllow = def.policy.tools?.allow ?? [];
34987
+ let allow = [...pkgAllow];
34988
+ if (acl.tools) {
34989
+ const r = intersectAllowList(pkgAllow, acl.tools.allow);
34990
+ if (r.widened.length) refuse(`tools would widen the package: ${r.widened.join(", ")}`);
34991
+ allow = r.allow.length ? r.allow : [NO_TOOL_SENTINEL];
34992
+ }
34993
+ const deny = [...def.policy.tools?.deny ?? []];
34994
+ if (allow.length === 0 && !deny.includes(MCP_DENY_ALL)) deny.push(MCP_DENY_ALL);
34995
+ const tools = allow.length || deny.length ? { ...allow.length ? { allow } : {}, ...deny.length ? { deny } : {} } : void 0;
34996
+ let skills = def.policy.skills;
34997
+ const aclSkills = acl.tools?.skills;
34998
+ if (aclSkills) {
34999
+ const pkgSkills = def.policy.skills ?? [];
35000
+ const kept = pkgSkills.filter((s) => aclSkills.includes(s));
35001
+ const widened = aclSkills.filter((s) => !pkgSkills.includes(s));
35002
+ if (widened.length) refuse(`skills would widen the package: ${widened.join(", ")}`);
35003
+ skills = kept.length ? kept : [NO_TOOL_SENTINEL];
35004
+ }
35005
+ const { tools: _tools, skills: _skills, ...policyRest } = def.policy;
35006
+ const policy = { ...policyRest, ...tools ? { tools } : {}, ...skills ? { skills } : {} };
35007
+ const allowedTriggers = acl.triggers?.allow;
35008
+ const triggers = allowedTriggers ? def.triggers.filter((t) => allowedTriggers.includes(t.type)) : [...def.triggers];
35009
+ const budget = { ...def.budget ?? {} };
35010
+ if (acl.budget) {
35011
+ const usd = lower(budget.maxUsd, acl.budget.perRunUsd);
35012
+ const tok = lower(budget.maxTokens, acl.budget.perRunTokens);
35013
+ if (usd !== void 0) budget.maxUsd = usd;
35014
+ if (tok !== void 0) budget.maxTokens = tok;
35015
+ }
35016
+ const effectiveModels = intersectModelEgress(
35017
+ intersectModelEgress(nodePolicy.models, def.packageModels ?? "any"),
35018
+ acl.models ?? "any"
35019
+ );
35020
+ if (egressIsEmpty(effectiveModels)) refuse("no allowed model");
35021
+ const out = {
35022
+ ...def,
35023
+ policy,
35024
+ triggers,
35025
+ budget,
35026
+ egress: effectiveModels,
35027
+ ...acl.access ? { aclAccess: { run: acl.access.run } } : {}
35028
+ };
35029
+ return refused === void 0 ? { def: out, effectiveModels } : { def: out, effectiveModels, refused };
35030
+ }
34155
35031
 
34156
35032
  // ../crew/memory.ts
34157
35033
  import { MEMORY_USERS_DIR } from "@corenel/protocol";
@@ -34304,9 +35180,9 @@ var ROOM_KIND = "room";
34304
35180
  function encodeRoomLine(line) {
34305
35181
  return JSON.stringify(line) + "\n";
34306
35182
  }
34307
- function roomLines(text) {
35183
+ function roomLines(text2) {
34308
35184
  const out = [];
34309
- for (const raw of text.split("\n")) {
35185
+ for (const raw of text2.split("\n")) {
34310
35186
  const s = raw.trim();
34311
35187
  if (!s) continue;
34312
35188
  let line;
@@ -34319,14 +35195,14 @@ function roomLines(text) {
34319
35195
  }
34320
35196
  return out;
34321
35197
  }
34322
- function openLineOf(text) {
34323
- for (const line of roomLines(text)) if (line.op === "open") return line;
35198
+ function openLineOf(text2) {
35199
+ for (const line of roomLines(text2)) if (line.op === "open") return line;
34324
35200
  return null;
34325
35201
  }
34326
- function foldRoom(text) {
35202
+ function foldRoom(text2) {
34327
35203
  let state = null;
34328
35204
  let lastAt;
34329
- for (const line of roomLines(text)) {
35205
+ for (const line of roomLines(text2)) {
34330
35206
  if (typeof line.at === "number" && (lastAt === void 0 || line.at > lastAt)) lastAt = line.at;
34331
35207
  if (line.op === "open") {
34332
35208
  if (state) continue;
@@ -34376,9 +35252,9 @@ function foldRoom(text) {
34376
35252
  if (state && lastAt !== void 0) state = { ...state, lastAt };
34377
35253
  return state;
34378
35254
  }
34379
- function pendingParticipant(text) {
35255
+ function pendingParticipant(text2) {
34380
35256
  let pending = null;
34381
- for (const line of roomLines(text)) {
35257
+ for (const line of roomLines(text2)) {
34382
35258
  if (line.op === "pending") {
34383
35259
  if (typeof line.participant === "string") pending = line.participant;
34384
35260
  } else if (line.op === "floor" || line.op === "close") {
@@ -34387,9 +35263,9 @@ function pendingParticipant(text) {
34387
35263
  }
34388
35264
  return pending;
34389
35265
  }
34390
- function pendingReason(text) {
35266
+ function pendingReason(text2) {
34391
35267
  let reason = null;
34392
- for (const line of roomLines(text)) {
35268
+ for (const line of roomLines(text2)) {
34393
35269
  if (line.op === "pending") {
34394
35270
  reason = typeof line.reason === "string" ? line.reason : null;
34395
35271
  } else if (line.op === "floor" || line.op === "close") {
@@ -34398,10 +35274,10 @@ function pendingReason(text) {
34398
35274
  }
34399
35275
  return reason;
34400
35276
  }
34401
- function turnCosts(text) {
35277
+ function turnCosts(text2) {
34402
35278
  const out = [];
34403
35279
  let opened = false;
34404
- for (const line of roomLines(text)) {
35280
+ for (const line of roomLines(text2)) {
34405
35281
  if (line.op === "open") {
34406
35282
  if (typeof line.roomId === "string" && Array.isArray(line.participants) && typeof line.maxTurns === "number") opened = true;
34407
35283
  continue;
@@ -34500,8 +35376,8 @@ var RoomStore = class {
34500
35376
  * reader wants a document either way. A file that exists but cannot be read
34501
35377
  * throws (see `textAt`). */
34502
35378
  async readFindings(roomId) {
34503
- const text = await this.textAt(findingsPath(this.getRoot(), roomId));
34504
- return text == null ? [] : foldFindings(text);
35379
+ const text2 = await this.textAt(findingsPath(this.getRoot(), roomId));
35380
+ return text2 == null ? [] : foldFindings(text2);
34505
35381
  }
34506
35382
  /** Append one finding op. A genuine read-then-concat append, exactly as
34507
35383
  * `append` does for the room fold, because the engine and a human's edit both
@@ -34513,8 +35389,8 @@ var RoomStore = class {
34513
35389
  await files.write(path, prior + encodeFindingLine(line));
34514
35390
  }
34515
35391
  async read(roomId) {
34516
- const text = await this.text(roomId);
34517
- return text == null ? null : foldRoom(text);
35392
+ const text2 = await this.text(roomId);
35393
+ return text2 == null ? null : foldRoom(text2);
34518
35394
  }
34519
35395
  /** Every room this store can find on disk, folded to its current state.
34520
35396
  * Mirrors `JsonlSessionStore.list()` (packages/harness/sessions/
@@ -34530,38 +35406,38 @@ var RoomStore = class {
34530
35406
  const roomFiles = flattenFiles4(nodes).filter((f) => f.name === "SESSION.jsonl" && f.path.startsWith(`${root}/`));
34531
35407
  const out = [];
34532
35408
  for (const f of roomFiles) {
34533
- const text = await files.read(f.path).catch(() => null);
34534
- const state = text != null ? foldRoom(text) : null;
35409
+ const text2 = await files.read(f.path).catch(() => null);
35410
+ const state = text2 != null ? foldRoom(text2) : null;
34535
35411
  if (state) out.push(state);
34536
35412
  }
34537
35413
  return out;
34538
35414
  }
34539
35415
  async readSession(roomId) {
34540
- const text = await this.text(roomId);
34541
- return text == null ? null : foldSession(text);
35416
+ const text2 = await this.text(roomId);
35417
+ return text2 == null ? null : foldSession(text2);
34542
35418
  }
34543
35419
  /** The participant the room is currently parked on, or null. Lets a caller
34544
35420
  * that re-polls a parked room (`runRoom`) tell "still parked on the same
34545
35421
  * person" from "needs a fresh `{op:'pending'}` line" without appending one
34546
35422
  * just to find out. */
34547
35423
  async pendingParticipant(roomId) {
34548
- const text = await this.text(roomId);
34549
- return text == null ? null : pendingParticipant(text);
35424
+ const text2 = await this.text(roomId);
35425
+ return text2 == null ? null : pendingParticipant(text2);
34550
35426
  }
34551
35427
  /** Why the room is parked, when the park was not simply someone's turn (see
34552
35428
  * `pendingReason` in lines.ts). Null for an ordinary human turn, and for a
34553
35429
  * room that is not parked. */
34554
35430
  async pendingReason(roomId) {
34555
- const text = await this.text(roomId);
34556
- return text == null ? null : pendingReason(text);
35431
+ const text2 = await this.text(roomId);
35432
+ return text2 == null ? null : pendingReason(text2);
34557
35433
  }
34558
35434
  /** What each of this room's turns cost, in order (see `turnCosts` in
34559
35435
  * lines.ts). Empty for a room that has taken no turn, and for a room that
34560
35436
  * does not exist -- a reader of a transcript wants an array it can index by
34561
35437
  * turn, and "no room" and "no turns yet" annotate that transcript alike. */
34562
35438
  async turnCosts(roomId) {
34563
- const text = await this.text(roomId);
34564
- return text == null ? [] : turnCosts(text);
35439
+ const text2 = await this.text(roomId);
35440
+ return text2 == null ? [] : turnCosts(text2);
34565
35441
  }
34566
35442
  };
34567
35443
 
@@ -34770,7 +35646,7 @@ function makeCrewTurnRuntime(opts) {
34770
35646
  const { def, participants, meId, deps } = opts;
34771
35647
  const findings = opts.findings ?? [];
34772
35648
  const refs = participants.map((p) => ({ id: p.id, name: p.name }));
34773
- const policy = grantOfferedTools(def.policy, [...ROOM_TOOL_NAMES]);
35649
+ const policy = grantOfferedTools(def.policy, [...ROOM_TOOL_NAMES], managedCap(def));
34774
35650
  const permission = new PermissionService2({
34775
35651
  policy,
34776
35652
  ...deps.prompt ? { prompt: deps.prompt } : {},
@@ -34992,7 +35868,7 @@ async function runRoom(roomId, deps) {
34992
35868
  }
34993
35869
  }
34994
35870
  }
34995
- async function answerHumanTurn(roomId, participantId, text, deps, addressed) {
35871
+ async function answerHumanTurn(roomId, participantId, text2, deps, addressed) {
34996
35872
  const state = await deps.store.read(roomId);
34997
35873
  if (!state) throw new Error(`No room "${roomId}".`);
34998
35874
  if (state.closed) {
@@ -35029,7 +35905,7 @@ async function answerHumanTurn(roomId, participantId, text, deps, addressed) {
35029
35905
  }
35030
35906
  target = res.id;
35031
35907
  }
35032
- const message = stampAuthor({ role: "user", content: text }, participantId);
35908
+ const message = stampAuthor({ role: "user", content: text2 }, participantId);
35033
35909
  await appendMessages(deps.store, roomId, [message], deps.now());
35034
35910
  let next = advance(state, target);
35035
35911
  if (next.closed) {
@@ -35060,14 +35936,14 @@ function requireHuman(roomId, state, participantId) {
35060
35936
  }
35061
35937
  return found;
35062
35938
  }
35063
- async function interjectHuman(roomId, participantId, text, deps) {
35939
+ async function interjectHuman(roomId, participantId, text2, deps) {
35064
35940
  const state = await deps.store.read(roomId);
35065
35941
  if (!state) throw new Error(`No room "${roomId}".`);
35066
35942
  if (state.closed) {
35067
35943
  throw new Error(`Room "${roomId}" is closed (${state.closed.reason}), so nothing further can be said in it.`);
35068
35944
  }
35069
35945
  const speaker = requireHuman(roomId, state, participantId);
35070
- const body = text.trim();
35946
+ const body = text2.trim();
35071
35947
  if (!body) {
35072
35948
  throw new Error(`${speaker.name} said nothing: an empty interjection is not appended.`);
35073
35949
  }
@@ -35205,6 +36081,7 @@ async function resolveCliApiBase(explicit, opts = {}) {
35205
36081
 
35206
36082
  // src/runAgent.ts
35207
36083
  import { allTools as allTools2 } from "@corenel/harness/tools/builtins";
36084
+ import { splitByTier } from "@corenel/harness/tools/toolSearch";
35208
36085
  import { registerGuard } from "@corenel/harness/guards";
35209
36086
  import { composeAgentSystem } from "@corenel/harness/prompts";
35210
36087
  init_tools_node();
@@ -35314,7 +36191,8 @@ ${extra}` : base;
35314
36191
  model: opts.model ?? def.settings.model ?? "gpt-4o-mini",
35315
36192
  system,
35316
36193
  messages: [{ role: "user", content: opts.input }],
35317
- tools,
36194
+ // Loaded tools ride every request; Listed and MCP tools are found with tool_search.
36195
+ ...splitByTier(tools),
35318
36196
  skills,
35319
36197
  permission,
35320
36198
  // Cause-aware refusal text -- see cli.ts's `run()` for why the kernel's
@@ -35384,6 +36262,15 @@ var EXTENSIONS = [
35384
36262
  ...SIDECAR,
35385
36263
  summary: "deploy, undeploy, pause and resume crew agents on this machine",
35386
36264
  argv: (rest) => ["crew", ...rest]
36265
+ },
36266
+ {
36267
+ command: "fleet",
36268
+ pkg: "@corenel/fleet",
36269
+ entry: "dist/server/main.js",
36270
+ summary: "run a fleet control plane (enroll, lease and revoke sidecars)",
36271
+ monorepoOnly: true,
36272
+ // 'corenel fleet start --data d' reads naturally; the server takes flags directly.
36273
+ argv: (rest) => rest[0] === "start" ? rest.slice(1) : rest
35387
36274
  }
35388
36275
  ];
35389
36276
  function findExtension(command) {
@@ -35391,6 +36278,13 @@ function findExtension(command) {
35391
36278
  }
35392
36279
  var EXTENSION_COMMANDS = EXTENSIONS.map((e) => e.command);
35393
36280
  function missingMessage(e) {
36281
+ if (e.monorepoOnly) {
36282
+ return [
36283
+ `${e.command} needs ${e.pkg}, which is not published yet and only runs from a checkout of the monorepo.`,
36284
+ "",
36285
+ " pnpm fleet:start"
36286
+ ].join("\n");
36287
+ }
35394
36288
  return [
35395
36289
  `${e.command} needs ${e.pkg}, which is not installed.`,
35396
36290
  "",
@@ -35489,6 +36383,7 @@ var COMMANDS = [
35489
36383
  { name: "acp", args: "<agent> [flags]", summary: "proxy an external coding agent under Corenel policy" },
35490
36384
  { name: "sandboxes", args: "[list|show|create|run|pause|resume|destroy]", summary: "create, list and run in local sandboxes" },
35491
36385
  { name: "crew", args: "deployments | deploy|undeploy|resume <agent> | pause <agent> --reason R", summary: "deploy, undeploy, pause and resume crew agents on this machine" },
36386
+ { name: "fleet", args: "[start] --data <dir> [flags] | keys new", summary: "run a fleet control plane (enroll, lease and revoke sidecars)" },
35492
36387
  { name: "login", args: "[--base URL]", summary: "sign in through your browser (device flow)" },
35493
36388
  { name: "auth", summary: "show whether you are signed in, and as what" },
35494
36389
  { name: "logout", summary: "forget the stored token" },
@@ -35506,16 +36401,16 @@ function isVersionFlag(a) {
35506
36401
  return a === "--version" || a === "-v" || a === "version";
35507
36402
  }
35508
36403
  function helpText(version2) {
35509
- const shown = COMMANDS.filter((c) => c.name);
36404
+ const shown2 = COMMANDS.filter((c) => c.name);
35510
36405
  const left = (c) => `corenel ${c.name}${c.args ? ` ${c.args}` : ""}`;
35511
- const width = Math.max(...shown.map((c) => left(c).length));
36406
+ const width = Math.max(...shown2.map((c) => left(c).length));
35512
36407
  const bare = COMMANDS.find((c) => !c.name);
35513
36408
  return [
35514
36409
  `corenel ${version2} \u2014 the harness, in node.`,
35515
36410
  "",
35516
36411
  "Usage:",
35517
36412
  ` corenel${" ".repeat(Math.max(1, width - 7))} ${bare ? bare.summary : ""}`,
35518
- ...shown.map((c) => ` ${left(c).padEnd(width)} ${c.summary}`),
36413
+ ...shown2.map((c) => ` ${left(c).padEnd(width)} ${c.summary}`),
35519
36414
  "",
35520
36415
  "Common flags:",
35521
36416
  " --model <id> model for this turn (default gpt-4o-mini)",
@@ -35542,6 +36437,7 @@ function helpText(version2) {
35542
36437
  "",
35543
36438
  "sidecar, acp, sandboxes and crew are provided by @corenel/sidecar, installed separately.",
35544
36439
  "Each takes its own flags: `corenel sidecar --help`.",
36440
+ "fleet is provided by @corenel/fleet, installed separately: `corenel fleet --help`.",
35545
36441
  "",
35546
36442
  "Exit codes (corenel run, corenel run-agent):",
35547
36443
  " 0 the turn completed with an answer",
@@ -35721,7 +36617,9 @@ var KNOWN_KEYS = [
35721
36617
  "speech",
35722
36618
  "speechModel",
35723
36619
  "peerCallTimeoutMs",
35724
- "peers"
36620
+ "peers",
36621
+ "models",
36622
+ "providers"
35725
36623
  ];
35726
36624
  function daemonConfigPath(stateDir) {
35727
36625
  return join8(stateDir, "daemon.json");
@@ -36066,8 +36964,8 @@ function isQuit(line) {
36066
36964
  const t = line.trim().toLowerCase();
36067
36965
  return t === "/exit" || t === "/quit" || t === "exit" || t === "quit";
36068
36966
  }
36069
- function nextShownCursor(itemsLength, shown) {
36070
- return itemsLength < shown ? 0 : shown;
36967
+ function nextShownCursor(itemsLength, shown2) {
36968
+ return itemsLength < shown2 ? 0 : shown2;
36071
36969
  }
36072
36970
  function formatWriteDiff(diff) {
36073
36971
  if (diff.noop) return " (no change -- new content is identical to what's on disk)\n";
@@ -36202,12 +37100,12 @@ async function runRepl(deps) {
36202
37100
  ...deps.policy ? { policy: deps.policy } : {},
36203
37101
  ...deps.policySource ? { policySource: deps.policySource } : {}
36204
37102
  });
36205
- let shown = 0;
37103
+ let shown2 = 0;
36206
37104
  session.subscribe(() => {
36207
37105
  const items = session.getSnapshot().committed;
36208
- shown = nextShownCursor(items.length, shown);
36209
- for (; shown < items.length; shown++) {
36210
- const it = items[shown];
37106
+ shown2 = nextShownCursor(items.length, shown2);
37107
+ for (; shown2 < items.length; shown2++) {
37108
+ const it = items[shown2];
36211
37109
  if (it.kind !== "note") continue;
36212
37110
  writeLine(` ${it.level === "info" ? "" : "! "}${it.text}
36213
37111
  `);
@@ -36319,11 +37217,11 @@ async function runRepl(deps) {
36319
37217
  for (; ; ) {
36320
37218
  const line = await ask("\u203A ");
36321
37219
  if (line === null) break;
36322
- const text = line.trim();
36323
- if (!text) continue;
36324
- if (isQuit(text)) break;
37220
+ const text2 = line.trim();
37221
+ if (!text2) continue;
37222
+ if (isQuit(text2)) break;
36325
37223
  turnActive = true;
36326
- await session.submit(text);
37224
+ await session.submit(text2);
36327
37225
  turnActive = false;
36328
37226
  await askSuggestions();
36329
37227
  if (session.wantsExit) break;
@@ -36475,9 +37373,9 @@ ${rules(r.workspace)}`);
36475
37373
  return 0;
36476
37374
  }
36477
37375
  if (sub === "set") {
36478
- let current;
37376
+ let current2;
36479
37377
  try {
36480
- current = await svc.settingsStrict();
37378
+ current2 = await svc.settingsStrict();
36481
37379
  } catch (e) {
36482
37380
  deps.err(`could not read settings: ${e instanceof Error ? e.message : String(e)}
36483
37381
  `);
@@ -36485,13 +37383,13 @@ ${rules(r.workspace)}`);
36485
37383
  }
36486
37384
  if (arg === "threshold") {
36487
37385
  const threshold = Number(value);
36488
- await svc.saveSettings({ ...current, threshold });
37386
+ await svc.saveSettings({ ...current2, threshold });
36489
37387
  deps.out(threshold === 0 ? "suggestions off\n" : `suggest after ${threshold} approvals
36490
37388
  `);
36491
37389
  return 0;
36492
37390
  }
36493
37391
  const raw = value.toLowerCase();
36494
- await svc.saveSettings({ ...current, captureRawArgs: raw === "on" });
37392
+ await svc.saveSettings({ ...current2, captureRawArgs: raw === "on" });
36495
37393
  deps.out(`raw argument capture ${raw}
36496
37394
  `);
36497
37395
  return 0;
@@ -36654,7 +37552,7 @@ import { procTools } from "@corenel/harness/tools/procs";
36654
37552
 
36655
37553
  // src/sidecarConnect.ts
36656
37554
  import { stateDirName as stateDirName4 } from "@corenel/protocol";
36657
- import { SidecarHost, isSidecarKeyMismatch, isSidecarAccountRefusal } from "@corenel/harness/sidecar/host";
37555
+ import { SidecarHost, isSidecarKeyMismatch, isSidecarAccountRefusal, isFleetLoginsRefusal } from "@corenel/harness/sidecar/host";
36658
37556
 
36659
37557
  // ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/wrapper.mjs
36660
37558
  var import_stream = __toESM(require_stream2(), 1);
@@ -36796,8 +37694,8 @@ function hostBackedProcs(host, seed = []) {
36796
37694
  if (!e) return { chunks: [], truncated: false };
36797
37695
  return { chunks: e.chunks.filter((c) => c.seq > sinceSeq), truncated: e.truncated };
36798
37696
  },
36799
- write: (procId, text) => {
36800
- void host.procInput(procId, text).catch(() => {
37697
+ write: (procId, text2) => {
37698
+ void host.procInput(procId, text2).catch(() => {
36801
37699
  });
36802
37700
  },
36803
37701
  kill: (procId) => {
@@ -36832,10 +37730,10 @@ function isCliDevice(v) {
36832
37730
  const k = r.privateJwk;
36833
37731
  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);
36834
37732
  }
36835
- function parse2(text) {
37733
+ function parse3(text2) {
36836
37734
  let raw;
36837
37735
  try {
36838
- raw = JSON.parse(text);
37736
+ raw = JSON.parse(text2);
36839
37737
  } catch {
36840
37738
  return null;
36841
37739
  }
@@ -36854,8 +37752,8 @@ function cliDeviceStore(path = cliDevicesPath()) {
36854
37752
  const file = fileTextStore(path);
36855
37753
  const dir = join10(path, "..");
36856
37754
  const load = async () => {
36857
- const text = await file.read();
36858
- return text === null ? { version: 1, devices: /* @__PURE__ */ Object.create(null) } : parse2(text);
37755
+ const text2 = await file.read();
37756
+ return text2 === null ? { version: 1, devices: /* @__PURE__ */ Object.create(null) } : parse3(text2);
36859
37757
  };
36860
37758
  const change = async (edit) => {
36861
37759
  const f = await load();
@@ -36994,6 +37892,11 @@ async function reportHandshakeFailure(e, url, usedDevice, store, identity2, fall
36994
37892
  return;
36995
37893
  }
36996
37894
  if (isSidecarAccountRefusal(e)) {
37895
+ if (isFleetLoginsRefusal(e)) {
37896
+ 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}
37897
+ `);
37898
+ return;
37899
+ }
36997
37900
  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).";
36998
37901
  process.stderr.write(`corenel: the sidecar at ${url} did not accept this CLI: ${problem} -- ${fallback}
36999
37902
  `);
@@ -37253,10 +38156,9 @@ function isFailedTurn(outcome) {
37253
38156
  import { stateReadDirs } from "@corenel/protocol";
37254
38157
  import { loadModes, loadPersonas } from "@corenel/harness/prompts/config";
37255
38158
  import { composeAgentSystem as composeAgentSystem2 } from "@corenel/harness/prompts";
37256
- import { listSkills, stripFrontmatter } from "@corenel/harness/skills";
37257
- import { configWorkspace } from "@corenel/harness/prompts/host";
38159
+ import { listSkills, readSkillInstructions, stripFrontmatter } from "@corenel/harness/skills";
37258
38160
  function createIdentityState() {
37259
- return { mode: "auto", persona: "" };
38161
+ return { mode: "auto", persona: "senior-dev" };
37260
38162
  }
37261
38163
  function makeSystemSource(state, tools) {
37262
38164
  return async () => {
@@ -37288,7 +38190,8 @@ async function armSkillById(id) {
37288
38190
  const found = skills.find((s) => s.name === id && s.instructions !== null);
37289
38191
  if (!found || !found.instructions) return null;
37290
38192
  try {
37291
- const raw = await configWorkspace().read(found.instructions);
38193
+ const raw = await readSkillInstructions(found.name);
38194
+ if (raw === null) return null;
37292
38195
  return { id: found.name, label: found.name, instructions: stripFrontmatter(raw) };
37293
38196
  } catch {
37294
38197
  return null;
@@ -37373,9 +38276,9 @@ function isErrnoException(e) {
37373
38276
  return e instanceof Error && "code" in e;
37374
38277
  }
37375
38278
  async function loadRequiredPolicyFile(path, notFoundMessage) {
37376
- let text;
38279
+ let text2;
37377
38280
  try {
37378
- text = await readFile2(path, "utf8");
38281
+ text2 = await readFile2(path, "utf8");
37379
38282
  } catch (e) {
37380
38283
  if (isErrnoException(e) && e.code === "ENOENT") {
37381
38284
  throw new PolicyResolutionError(notFoundMessage);
@@ -37384,22 +38287,22 @@ async function loadRequiredPolicyFile(path, notFoundMessage) {
37384
38287
  `corenel: could not read policy file "${path}": ${e instanceof Error ? e.message : String(e)}`
37385
38288
  );
37386
38289
  }
37387
- return validateOrThrow(text, path);
38290
+ return validateOrThrow(text2, path);
37388
38291
  }
37389
38292
  async function loadDiscoveredPolicyFile(path) {
37390
- let text;
38293
+ let text2;
37391
38294
  try {
37392
- text = await readFile2(path, "utf8");
38295
+ text2 = await readFile2(path, "utf8");
37393
38296
  } catch (e) {
37394
38297
  if (isErrnoException(e) && e.code === "ENOENT") return void 0;
37395
38298
  throw new PolicyResolutionError(
37396
38299
  `corenel: could not read policy file "${path}": ${e instanceof Error ? e.message : String(e)}`
37397
38300
  );
37398
38301
  }
37399
- return validateOrThrow(text, path);
38302
+ return validateOrThrow(text2, path);
37400
38303
  }
37401
- function validateOrThrow(text, path) {
37402
- const result = policyFromYaml(text);
38304
+ function validateOrThrow(text2, path) {
38305
+ const result = policyFromYaml(text2);
37403
38306
  if (!result.ok || !result.policy) {
37404
38307
  throw new PolicyResolutionError(`corenel: policy file "${path}" is not a valid policy document.`, result.errors);
37405
38308
  }
@@ -37477,14 +38380,14 @@ var McpHttpClient = class {
37477
38380
  }
37478
38381
  async listTools() {
37479
38382
  const result = await this.send("tools/list", {});
37480
- const tools = isRecord(result) ? result.tools : void 0;
38383
+ const tools = isRecord2(result) ? result.tools : void 0;
37481
38384
  if (!Array.isArray(tools)) return [];
37482
38385
  return tools.filter(isMcpTool);
37483
38386
  }
37484
38387
  async callTool(name, args) {
37485
38388
  const result = await this.send("tools/call", { name, arguments: args });
37486
- const record = isRecord(result) ? result : {};
37487
- return { content: record.content, isError: record.isError === true };
38389
+ const record2 = isRecord2(result) ? result : {};
38390
+ return { content: record2.content, isError: record2.isError === true };
37488
38391
  }
37489
38392
  /** Send one JSON-RPC request, retrying exactly once on a 401 that the
37490
38393
  * AuthProvider says it recovered from. `isRetry` prevents a second retry
@@ -37534,12 +38437,12 @@ var McpHttpClient = class {
37534
38437
  throw new Error(`MCP server "${this.server.name}" closed the stream without a response`);
37535
38438
  }
37536
38439
  const reader = res.body.getReader();
37537
- const decoder = new TextDecoder();
38440
+ const decoder3 = new TextDecoder();
37538
38441
  let buffer = "";
37539
38442
  try {
37540
38443
  for (; ; ) {
37541
38444
  const { done, value } = await reader.read();
37542
- if (value) buffer += decoder.decode(value, { stream: true });
38445
+ if (value) buffer += decoder3.decode(value, { stream: true });
37543
38446
  buffer = buffer.replace(/\r\n/g, "\n");
37544
38447
  let boundary = buffer.indexOf("\n\n");
37545
38448
  while (boundary !== -1) {
@@ -37570,7 +38473,7 @@ var McpHttpClient = class {
37570
38473
  } catch {
37571
38474
  return null;
37572
38475
  }
37573
- if (!isRecord(parsed) || parsed.id !== id) return null;
38476
+ if (!isRecord2(parsed) || parsed.id !== id) return null;
37574
38477
  if (!("result" in parsed) && !("error" in parsed)) return null;
37575
38478
  return parsed;
37576
38479
  }
@@ -37604,11 +38507,11 @@ var McpHttpClient = class {
37604
38507
  return headers;
37605
38508
  }
37606
38509
  };
37607
- function isRecord(value) {
38510
+ function isRecord2(value) {
37608
38511
  return typeof value === "object" && value !== null;
37609
38512
  }
37610
38513
  function isMcpTool(value) {
37611
- return isRecord(value) && typeof value.name === "string" && "inputSchema" in value;
38514
+ return isRecord2(value) && typeof value.name === "string" && "inputSchema" in value;
37612
38515
  }
37613
38516
 
37614
38517
  // ../mcp/src/config.ts
@@ -38372,7 +39275,7 @@ var McpRegistry = class {
38372
39275
  const inflight = this.slotConnecting.get(key);
38373
39276
  if (inflight) return inflight;
38374
39277
  const self2 = {};
38375
- const current = () => self2.attempt !== void 0 && this.slotConnecting.get(key) === self2.attempt;
39278
+ const current2 = () => self2.attempt !== void 0 && this.slotConnecting.get(key) === self2.attempt;
38376
39279
  const attempt = (async () => {
38377
39280
  const def = (await readMcpServers(this.stateDir, this.configEnv)).find((s) => s.name === server);
38378
39281
  if (!def) throw new Error(`MCP server "${server}" is not configured on this daemon`);
@@ -38381,10 +39284,10 @@ var McpRegistry = class {
38381
39284
  await client.initialize();
38382
39285
  return { client, tools: await client.listTools() };
38383
39286
  })(), SERVER_CONNECT_TIMEOUT_MS, `MCP server "${server}" timed out after ${SERVER_CONNECT_TIMEOUT_MS / 1e3}s`);
38384
- if (current()) this.slotted.set(key, entry);
39287
+ if (current2()) this.slotted.set(key, entry);
38385
39288
  return entry;
38386
39289
  })().finally(() => {
38387
- if (current()) this.slotConnecting.delete(key);
39290
+ if (current2()) this.slotConnecting.delete(key);
38388
39291
  });
38389
39292
  self2.attempt = attempt;
38390
39293
  this.slotConnecting.set(key, attempt);
@@ -38405,10 +39308,10 @@ var McpRegistry = class {
38405
39308
  };
38406
39309
 
38407
39310
  // ../mcp/src/policy.ts
38408
- import { PermissionService as PermissionService5, matchesAnyGlob as matchesAnyGlob2 } from "@corenel/harness/guardrail";
39311
+ import { PermissionService as PermissionService5, matchesAnyGlob as matchesAnyGlob3 } from "@corenel/harness/guardrail";
38409
39312
  function mcpCallAllowed(address, policy) {
38410
39313
  const allow = policy.tools?.allow ?? [];
38411
- if (!matchesAnyGlob2(address, allow)) {
39314
+ if (!matchesAnyGlob3(address, allow)) {
38412
39315
  return { ok: false, reason: `${address} is not allowed - add it with: corenel config add mcpAllow ${address}` };
38413
39316
  }
38414
39317
  const service = new PermissionService5({
@@ -38430,7 +39333,7 @@ function mcpCallAllowed(address, policy) {
38430
39333
  import {
38431
39334
  mcpToolAddress,
38432
39335
  parseMcpToolAddress,
38433
- mcpWireName,
39336
+ mcpWireName as mcpWireName2,
38434
39337
  parseMcpWireName,
38435
39338
  canEncodeMcpWireName,
38436
39339
  looksLikeMcpWireName
@@ -38470,7 +39373,7 @@ function asAgentTools(registry) {
38470
39373
  return out;
38471
39374
  }
38472
39375
  function toAgentTool(registry, server, tool) {
38473
- const name = mcpWireName(server, tool.name);
39376
+ const name = mcpWireName2(server, tool.name);
38474
39377
  const address = mcpToolAddress(server, tool.name);
38475
39378
  return {
38476
39379
  name,
@@ -38480,14 +39383,14 @@ function toAgentTool(registry, server, tool) {
38480
39383
  mutates: true,
38481
39384
  async run(args) {
38482
39385
  const result = await registry.call(server, tool.name, args);
38483
- const text = formatContent(result.content);
38484
- return result.isError ? `Error: ${text}` : text;
39386
+ const text2 = formatContent(result.content);
39387
+ return result.isError ? `Error: ${text2}` : text2;
38485
39388
  }
38486
39389
  };
38487
39390
  }
38488
39391
 
38489
39392
  // ../mcp/src/portTools.ts
38490
- import { MCP_CALL_FAILED, canEncodeMcpWireName as canEncodeMcpWireName2, mcpWireName as mcpWireName2, parseMcpToolAddress as parseMcpToolAddress2 } from "@corenel/protocol";
39393
+ import { MCP_CALL_FAILED, canEncodeMcpWireName as canEncodeMcpWireName2, mcpWireName as mcpWireName3, parseMcpToolAddress as parseMcpToolAddress2 } from "@corenel/protocol";
38491
39394
  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.`;
38492
39395
 
38493
39396
  // ../mcp/src/gatedAgentTools.ts
@@ -38497,7 +39400,7 @@ function gatedAgentTools(registry, policy) {
38497
39400
  const wrapped = [];
38498
39401
  for (const { server, tool } of registry.tools()) {
38499
39402
  if (!canEncodeMcpWireName(server, tool.name)) continue;
38500
- const name = mcpWireName(server, tool.name);
39403
+ const name = mcpWireName2(server, tool.name);
38501
39404
  const original = byWireName.get(name);
38502
39405
  if (!original) continue;
38503
39406
  const address = mcpToolAddress(server, tool.name);
@@ -38640,12 +39543,12 @@ async function registerClient(meta, redirectUri, fetchImpl) {
38640
39543
  if (typeof body !== "object" || body === null || Array.isArray(body)) {
38641
39544
  throw new Error(`Client registration at ${meta.registrationEndpoint} returned a malformed response`);
38642
39545
  }
38643
- const record = body;
38644
- const clientId = record.client_id;
39546
+ const record2 = body;
39547
+ const clientId = record2.client_id;
38645
39548
  if (typeof clientId !== "string" || clientId.length === 0) {
38646
39549
  throw new Error(`Client registration at ${meta.registrationEndpoint} did not return a client_id`);
38647
39550
  }
38648
- const clientSecret = typeof record.client_secret === "string" ? record.client_secret : void 0;
39551
+ const clientSecret = typeof record2.client_secret === "string" ? record2.client_secret : void 0;
38649
39552
  return { clientId, clientSecret };
38650
39553
  }
38651
39554
 
@@ -39125,7 +40028,8 @@ async function run(argv) {
39125
40028
  model,
39126
40029
  system,
39127
40030
  messages: [{ role: "user", content: prompt }],
39128
- tools,
40031
+ // Loaded tools ride every request; Listed and MCP tools are found with tool_search.
40032
+ ...splitByTier2(tools),
39129
40033
  skills,
39130
40034
  permission,
39131
40035
  // Cause-aware refusal text: nobody was asked, so "denied by the user" would
@@ -39427,7 +40331,8 @@ async function main() {
39427
40331
  case "sidecar":
39428
40332
  case "acp":
39429
40333
  case "sandboxes":
39430
- case "crew": {
40334
+ case "crew":
40335
+ case "fleet": {
39431
40336
  const ext = findExtension(cmd);
39432
40337
  process.exitCode = ext ? await runExtension(ext, rest) : 2;
39433
40338
  break;