@corenel/cli 0.3.0 → 0.3.2

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 (3) hide show
  1. package/README.md +28 -2
  2. package/dist/cli.js +913 -147
  3. package/package.json +15 -15
package/dist/cli.js CHANGED
@@ -324,13 +324,13 @@ var require_directives = __commonJS({
324
324
  onError(0, "%YAML directive should contain exactly one part");
325
325
  return false;
326
326
  }
327
- const [version] = parts;
328
- if (version === "1.1" || version === "1.2") {
329
- this.yaml.version = version;
327
+ const [version2] = parts;
328
+ if (version2 === "1.1" || version2 === "1.2") {
329
+ this.yaml.version = version2;
330
330
  return true;
331
331
  } else {
332
- const isValid = /^\d+\.\d+$/.test(version);
333
- onError(6, `Unsupported YAML version ${version}`, isValid);
332
+ const isValid = /^\d+\.\d+$/.test(version2);
333
+ onError(6, `Unsupported YAML version ${version2}`, isValid);
334
334
  return false;
335
335
  }
336
336
  }
@@ -3430,14 +3430,14 @@ var require_Document = __commonJS({
3430
3430
  version: "1.2"
3431
3431
  }, options);
3432
3432
  this.options = opt;
3433
- let { version } = opt;
3433
+ let { version: version2 } = opt;
3434
3434
  if (options?._directives) {
3435
3435
  this.directives = options._directives.atDocument();
3436
3436
  if (this.directives.yaml.explicit)
3437
- version = this.directives.yaml.version;
3437
+ version2 = this.directives.yaml.version;
3438
3438
  } else
3439
- this.directives = new directives.Directives({ version });
3440
- this.setSchema(version, options);
3439
+ this.directives = new directives.Directives({ version: version2 });
3440
+ this.setSchema(version2, options);
3441
3441
  this.contents = value === void 0 ? null : this.createNode(value, _replacer, options);
3442
3442
  }
3443
3443
  /**
@@ -3617,11 +3617,11 @@ var require_Document = __commonJS({
3617
3617
  *
3618
3618
  * Overrides all previously set schema options.
3619
3619
  */
3620
- setSchema(version, options = {}) {
3621
- if (typeof version === "number")
3622
- version = String(version);
3620
+ setSchema(version2, options = {}) {
3621
+ if (typeof version2 === "number")
3622
+ version2 = String(version2);
3623
3623
  let opt;
3624
- switch (version) {
3624
+ switch (version2) {
3625
3625
  case "1.1":
3626
3626
  if (this.directives)
3627
3627
  this.directives.yaml.version = "1.1";
@@ -3632,9 +3632,9 @@ var require_Document = __commonJS({
3632
3632
  case "1.2":
3633
3633
  case "next":
3634
3634
  if (this.directives)
3635
- this.directives.yaml.version = version;
3635
+ this.directives.yaml.version = version2;
3636
3636
  else
3637
- this.directives = new directives.Directives({ version });
3637
+ this.directives = new directives.Directives({ version: version2 });
3638
3638
  opt = { resolveKnownTags: true, schema: "core" };
3639
3639
  break;
3640
3640
  case null:
@@ -3643,7 +3643,7 @@ var require_Document = __commonJS({
3643
3643
  opt = null;
3644
3644
  break;
3645
3645
  default: {
3646
- const sv = JSON.stringify(version);
3646
+ const sv = JSON.stringify(version2);
3647
3647
  throw new Error(`Expected '1.1', '1.2' or null as first argument, but found: ${sv}`);
3648
3648
  }
3649
3649
  }
@@ -7541,31 +7541,31 @@ var require_semver = __commonJS({
7541
7541
  return true;
7542
7542
  };
7543
7543
  var SemVer = class _SemVer {
7544
- constructor(version, options) {
7544
+ constructor(version2, options) {
7545
7545
  options = parseOptions(options);
7546
- if (version instanceof _SemVer) {
7547
- if (version.loose === !!options.loose && version.includePrerelease === !!options.includePrerelease) {
7548
- return version;
7546
+ if (version2 instanceof _SemVer) {
7547
+ if (version2.loose === !!options.loose && version2.includePrerelease === !!options.includePrerelease) {
7548
+ return version2;
7549
7549
  } else {
7550
- version = version.version;
7550
+ version2 = version2.version;
7551
7551
  }
7552
- } else if (typeof version !== "string") {
7553
- throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`);
7552
+ } else if (typeof version2 !== "string") {
7553
+ throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version2}".`);
7554
7554
  }
7555
- if (version.length > MAX_LENGTH) {
7555
+ if (version2.length > MAX_LENGTH) {
7556
7556
  throw new TypeError(
7557
7557
  `version is longer than ${MAX_LENGTH} characters`
7558
7558
  );
7559
7559
  }
7560
- debug("SemVer", version, options);
7560
+ debug("SemVer", version2, options);
7561
7561
  this.options = options;
7562
7562
  this.loose = !!options.loose;
7563
7563
  this.includePrerelease = !!options.includePrerelease;
7564
- const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]);
7564
+ const m = version2.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]);
7565
7565
  if (!m) {
7566
- throw new TypeError(`Invalid Version: ${version}`);
7566
+ throw new TypeError(`Invalid Version: ${version2}`);
7567
7567
  }
7568
- this.raw = version;
7568
+ this.raw = version2;
7569
7569
  this.major = +m[1];
7570
7570
  this.minor = +m[2];
7571
7571
  this.patch = +m[3];
@@ -7812,12 +7812,12 @@ var require_parse = __commonJS({
7812
7812
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/parse.js"(exports, module) {
7813
7813
  "use strict";
7814
7814
  var SemVer = require_semver();
7815
- var parse3 = (version, options, throwErrors = false) => {
7816
- if (version instanceof SemVer) {
7817
- return version;
7815
+ var parse3 = (version2, options, throwErrors = false) => {
7816
+ if (version2 instanceof SemVer) {
7817
+ return version2;
7818
7818
  }
7819
7819
  try {
7820
- return new SemVer(version, options);
7820
+ return new SemVer(version2, options);
7821
7821
  } catch (er) {
7822
7822
  if (!throwErrors) {
7823
7823
  return null;
@@ -7834,8 +7834,8 @@ var require_valid = __commonJS({
7834
7834
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/valid.js"(exports, module) {
7835
7835
  "use strict";
7836
7836
  var parse3 = require_parse();
7837
- var valid = (version, options) => {
7838
- const v = parse3(version, options);
7837
+ var valid = (version2, options) => {
7838
+ const v = parse3(version2, options);
7839
7839
  return v ? v.version : null;
7840
7840
  };
7841
7841
  module.exports = valid;
@@ -7847,8 +7847,8 @@ var require_clean = __commonJS({
7847
7847
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/clean.js"(exports, module) {
7848
7848
  "use strict";
7849
7849
  var parse3 = require_parse();
7850
- var clean = (version, options) => {
7851
- const s = parse3(version.trim().replace(/^[=v]+/, ""), options);
7850
+ var clean = (version2, options) => {
7851
+ const s = parse3(version2.trim().replace(/^[=v]+/, ""), options);
7852
7852
  return s ? s.version : null;
7853
7853
  };
7854
7854
  module.exports = clean;
@@ -7860,7 +7860,7 @@ var require_inc = __commonJS({
7860
7860
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/inc.js"(exports, module) {
7861
7861
  "use strict";
7862
7862
  var SemVer = require_semver();
7863
- var inc = (version, release, options, identifier, identifierBase) => {
7863
+ var inc = (version2, release, options, identifier, identifierBase) => {
7864
7864
  if (typeof options === "string") {
7865
7865
  identifierBase = identifier;
7866
7866
  identifier = options;
@@ -7868,7 +7868,7 @@ var require_inc = __commonJS({
7868
7868
  }
7869
7869
  try {
7870
7870
  return new SemVer(
7871
- version instanceof SemVer ? version.version : version,
7871
+ version2 instanceof SemVer ? version2.version : version2,
7872
7872
  options
7873
7873
  ).inc(release, identifier, identifierBase).version;
7874
7874
  } catch (er) {
@@ -7958,8 +7958,8 @@ var require_prerelease = __commonJS({
7958
7958
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/prerelease.js"(exports, module) {
7959
7959
  "use strict";
7960
7960
  var parse3 = require_parse();
7961
- var prerelease = (version, options) => {
7962
- const parsed = parse3(version, options);
7961
+ var prerelease = (version2, options) => {
7962
+ const parsed = parse3(version2, options);
7963
7963
  return parsed && parsed.prerelease.length ? parsed.prerelease : null;
7964
7964
  };
7965
7965
  module.exports = prerelease;
@@ -8147,24 +8147,24 @@ var require_coerce = __commonJS({
8147
8147
  var SemVer = require_semver();
8148
8148
  var parse3 = require_parse();
8149
8149
  var { safeRe: re, t } = require_re();
8150
- var coerce = (version, options) => {
8151
- if (version instanceof SemVer) {
8152
- return version;
8150
+ var coerce = (version2, options) => {
8151
+ if (version2 instanceof SemVer) {
8152
+ return version2;
8153
8153
  }
8154
- if (typeof version === "number") {
8155
- version = String(version);
8154
+ if (typeof version2 === "number") {
8155
+ version2 = String(version2);
8156
8156
  }
8157
- if (typeof version !== "string") {
8157
+ if (typeof version2 !== "string") {
8158
8158
  return null;
8159
8159
  }
8160
8160
  options = options || {};
8161
8161
  let match = null;
8162
8162
  if (!options.rtl) {
8163
- match = version.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]);
8163
+ match = version2.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]);
8164
8164
  } else {
8165
8165
  const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL];
8166
8166
  let next;
8167
- while ((next = coerceRtlRegex.exec(version)) && (!match || match.index + match[0].length !== version.length)) {
8167
+ while ((next = coerceRtlRegex.exec(version2)) && (!match || match.index + match[0].length !== version2.length)) {
8168
8168
  if (!match || next.index + next[0].length !== match.index + match[0].length) {
8169
8169
  match = next;
8170
8170
  }
@@ -8193,37 +8193,37 @@ var require_truncate = __commonJS({
8193
8193
  var parse3 = require_parse();
8194
8194
  var constants = require_constants();
8195
8195
  var SemVer = require_semver();
8196
- var truncate = (version, truncation, options) => {
8196
+ var truncate2 = (version2, truncation, options) => {
8197
8197
  if (!constants.RELEASE_TYPES.includes(truncation)) {
8198
8198
  return null;
8199
8199
  }
8200
- const clonedVersion = cloneInputVersion(version, options);
8200
+ const clonedVersion = cloneInputVersion(version2, options);
8201
8201
  return clonedVersion && doTruncation(clonedVersion, truncation);
8202
8202
  };
8203
- var cloneInputVersion = (version, options) => {
8204
- const versionStringToParse = version instanceof SemVer ? version.version : version;
8203
+ var cloneInputVersion = (version2, options) => {
8204
+ const versionStringToParse = version2 instanceof SemVer ? version2.version : version2;
8205
8205
  return parse3(versionStringToParse, options);
8206
8206
  };
8207
- var doTruncation = (version, truncation) => {
8207
+ var doTruncation = (version2, truncation) => {
8208
8208
  if (isPrerelease(truncation)) {
8209
- return version.version;
8209
+ return version2.version;
8210
8210
  }
8211
- version.prerelease = [];
8211
+ version2.prerelease = [];
8212
8212
  switch (truncation) {
8213
8213
  case "major":
8214
- version.minor = 0;
8215
- version.patch = 0;
8214
+ version2.minor = 0;
8215
+ version2.patch = 0;
8216
8216
  break;
8217
8217
  case "minor":
8218
- version.patch = 0;
8218
+ version2.patch = 0;
8219
8219
  break;
8220
8220
  }
8221
- return version.format();
8221
+ return version2.format();
8222
8222
  };
8223
8223
  var isPrerelease = (type) => {
8224
8224
  return type.startsWith("pre");
8225
8225
  };
8226
- module.exports = truncate;
8226
+ module.exports = truncate2;
8227
8227
  }
8228
8228
  });
8229
8229
 
@@ -8390,19 +8390,19 @@ var require_range = __commonJS({
8390
8390
  });
8391
8391
  }
8392
8392
  // if ANY of the sets match ALL of its comparators, then pass
8393
- test(version) {
8394
- if (!version) {
8393
+ test(version2) {
8394
+ if (!version2) {
8395
8395
  return false;
8396
8396
  }
8397
- if (typeof version === "string") {
8397
+ if (typeof version2 === "string") {
8398
8398
  try {
8399
- version = new SemVer(version, this.options);
8399
+ version2 = new SemVer(version2, this.options);
8400
8400
  } catch (er) {
8401
8401
  return false;
8402
8402
  }
8403
8403
  }
8404
8404
  for (let i = 0; i < this.set.length; i++) {
8405
- if (testSet(this.set[i], version, this.options)) {
8405
+ if (testSet(this.set[i], version2, this.options)) {
8406
8406
  return true;
8407
8407
  }
8408
8408
  }
@@ -8624,13 +8624,13 @@ var require_range = __commonJS({
8624
8624
  }
8625
8625
  return `${from} ${to}`.trim();
8626
8626
  };
8627
- var testSet = (set, version, options) => {
8627
+ var testSet = (set, version2, options) => {
8628
8628
  for (let i = 0; i < set.length; i++) {
8629
- if (!set[i].test(version)) {
8629
+ if (!set[i].test(version2)) {
8630
8630
  return false;
8631
8631
  }
8632
8632
  }
8633
- if (version.prerelease.length && !options.includePrerelease) {
8633
+ if (version2.prerelease.length && !options.includePrerelease) {
8634
8634
  for (let i = 0; i < set.length; i++) {
8635
8635
  debug(set[i].semver);
8636
8636
  if (set[i].semver === Comparator.ANY) {
@@ -8638,7 +8638,7 @@ var require_range = __commonJS({
8638
8638
  }
8639
8639
  if (set[i].semver.prerelease.length > 0) {
8640
8640
  const allowed = set[i].semver;
8641
- if (allowed.major === version.major && allowed.minor === version.minor && allowed.patch === version.patch) {
8641
+ if (allowed.major === version2.major && allowed.minor === version2.minor && allowed.patch === version2.patch) {
8642
8642
  return true;
8643
8643
  }
8644
8644
  }
@@ -8699,19 +8699,19 @@ var require_comparator = __commonJS({
8699
8699
  toString() {
8700
8700
  return this.value;
8701
8701
  }
8702
- test(version) {
8703
- debug("Comparator.test", version, this.options.loose);
8704
- if (this.semver === ANY || version === ANY) {
8702
+ test(version2) {
8703
+ debug("Comparator.test", version2, this.options.loose);
8704
+ if (this.semver === ANY || version2 === ANY) {
8705
8705
  return true;
8706
8706
  }
8707
- if (typeof version === "string") {
8707
+ if (typeof version2 === "string") {
8708
8708
  try {
8709
- version = new SemVer(version, this.options);
8709
+ version2 = new SemVer(version2, this.options);
8710
8710
  } catch (er) {
8711
8711
  return false;
8712
8712
  }
8713
8713
  }
8714
- return cmp(version, this.operator, this.semver, this.options);
8714
+ return cmp(version2, this.operator, this.semver, this.options);
8715
8715
  }
8716
8716
  intersects(comp, options) {
8717
8717
  if (!(comp instanceof _Comparator)) {
@@ -8768,13 +8768,13 @@ var require_satisfies = __commonJS({
8768
8768
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/satisfies.js"(exports, module) {
8769
8769
  "use strict";
8770
8770
  var Range = require_range();
8771
- var satisfies = (version, range, options) => {
8771
+ var satisfies = (version2, range, options) => {
8772
8772
  try {
8773
8773
  range = new Range(range, options);
8774
8774
  } catch (er) {
8775
8775
  return false;
8776
8776
  }
8777
- return range.test(version);
8777
+ return range.test(version2);
8778
8778
  };
8779
8779
  module.exports = satisfies;
8780
8780
  }
@@ -8934,8 +8934,8 @@ var require_outside = __commonJS({
8934
8934
  var lt = require_lt();
8935
8935
  var lte = require_lte();
8936
8936
  var gte = require_gte();
8937
- var outside = (version, range, hilo, options) => {
8938
- version = new SemVer(version, options);
8937
+ var outside = (version2, range, hilo, options) => {
8938
+ version2 = new SemVer(version2, options);
8939
8939
  range = new Range(range, options);
8940
8940
  let gtfn, ltefn, ltfn, comp, ecomp;
8941
8941
  switch (hilo) {
@@ -8956,7 +8956,7 @@ var require_outside = __commonJS({
8956
8956
  default:
8957
8957
  throw new TypeError('Must provide a hilo val of "<" or ">"');
8958
8958
  }
8959
- if (satisfies(version, range, options)) {
8959
+ if (satisfies(version2, range, options)) {
8960
8960
  return false;
8961
8961
  }
8962
8962
  for (let i = 0; i < range.set.length; ++i) {
@@ -8978,9 +8978,9 @@ var require_outside = __commonJS({
8978
8978
  if (high.operator === comp || high.operator === ecomp) {
8979
8979
  return false;
8980
8980
  }
8981
- if ((!low.operator || low.operator === comp) && ltefn(version, low.semver)) {
8981
+ if ((!low.operator || low.operator === comp) && ltefn(version2, low.semver)) {
8982
8982
  return false;
8983
- } else if (low.operator === ecomp && ltfn(version, low.semver)) {
8983
+ } else if (low.operator === ecomp && ltfn(version2, low.semver)) {
8984
8984
  return false;
8985
8985
  }
8986
8986
  }
@@ -8995,7 +8995,7 @@ var require_gtr = __commonJS({
8995
8995
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/ranges/gtr.js"(exports, module) {
8996
8996
  "use strict";
8997
8997
  var outside = require_outside();
8998
- var gtr = (version, range, options) => outside(version, range, ">", options);
8998
+ var gtr = (version2, range, options) => outside(version2, range, ">", options);
8999
8999
  module.exports = gtr;
9000
9000
  }
9001
9001
  });
@@ -9005,7 +9005,7 @@ var require_ltr = __commonJS({
9005
9005
  "../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/ranges/ltr.js"(exports, module) {
9006
9006
  "use strict";
9007
9007
  var outside = require_outside();
9008
- var ltr = (version, range, options) => outside(version, range, "<", options);
9008
+ var ltr = (version2, range, options) => outside(version2, range, "<", options);
9009
9009
  module.exports = ltr;
9010
9010
  }
9011
9011
  });
@@ -9035,12 +9035,12 @@ var require_simplify = __commonJS({
9035
9035
  let first = null;
9036
9036
  let prev = null;
9037
9037
  const v = versions.sort((a, b) => compare(a, b, options));
9038
- for (const version of v) {
9039
- const included = satisfies(version, range, options);
9038
+ for (const version2 of v) {
9039
+ const included = satisfies(version2, range, options);
9040
9040
  if (included) {
9041
- prev = version;
9041
+ prev = version2;
9042
9042
  if (!first) {
9043
- first = version;
9043
+ first = version2;
9044
9044
  }
9045
9045
  } else {
9046
9046
  if (prev) {
@@ -9267,7 +9267,7 @@ var require_semver2 = __commonJS({
9267
9267
  var lte = require_lte();
9268
9268
  var cmp = require_cmp();
9269
9269
  var coerce = require_coerce();
9270
- var truncate = require_truncate();
9270
+ var truncate2 = require_truncate();
9271
9271
  var Comparator = require_comparator();
9272
9272
  var Range = require_range();
9273
9273
  var satisfies = require_satisfies();
@@ -9306,7 +9306,7 @@ var require_semver2 = __commonJS({
9306
9306
  lte,
9307
9307
  cmp,
9308
9308
  coerce,
9309
- truncate,
9309
+ truncate: truncate2,
9310
9310
  Comparator,
9311
9311
  Range,
9312
9312
  satisfies,
@@ -13261,7 +13261,7 @@ var require_filters = __commonJS({
13261
13261
  return r.copySafeness(str5, res);
13262
13262
  }
13263
13263
  _exports.indent = indent;
13264
- function join5(arr, del, attr) {
13264
+ function join6(arr, del, attr) {
13265
13265
  del = del || "";
13266
13266
  if (attr) {
13267
13267
  arr = lib.map(arr, function(v) {
@@ -13270,7 +13270,7 @@ var require_filters = __commonJS({
13270
13270
  }
13271
13271
  return arr.join(del);
13272
13272
  }
13273
- _exports.join = join5;
13273
+ _exports.join = join6;
13274
13274
  function last(arr) {
13275
13275
  return arr[arr.length - 1];
13276
13276
  }
@@ -13511,7 +13511,7 @@ var require_filters = __commonJS({
13511
13511
  return r.copySafeness(str5, str5.replace(/^\s*|\s*$/g, ""));
13512
13512
  }
13513
13513
  _exports.trim = trim;
13514
- function truncate(input, length, killwords, end) {
13514
+ function truncate2(input, length, killwords, end) {
13515
13515
  var orig = input;
13516
13516
  input = normalize(input, "");
13517
13517
  length = length || 255;
@@ -13530,7 +13530,7 @@ var require_filters = __commonJS({
13530
13530
  input += end !== void 0 && end !== null ? end : "...";
13531
13531
  return r.copySafeness(orig, input);
13532
13532
  }
13533
- _exports.truncate = truncate;
13533
+ _exports.truncate = truncate2;
13534
13534
  function upper(str5) {
13535
13535
  str5 = normalize(str5, "");
13536
13536
  return str5.toUpperCase();
@@ -15039,7 +15039,7 @@ import OpenAI from "openai";
15039
15039
  var enabled = true;
15040
15040
  function setAgentLogging(on) {
15041
15041
  enabled = on;
15042
- console.log(`[agent] logging ${on ? "enabled" : "disabled"}`);
15042
+ if (on) console.log("[agent] logging enabled");
15043
15043
  }
15044
15044
  function alog(...args) {
15045
15045
  if (enabled) console.debug("[agent]", ...args);
@@ -15708,7 +15708,7 @@ function reconcileDanglingToolCalls(messages) {
15708
15708
  }
15709
15709
 
15710
15710
  // src/cli.ts
15711
- import { join as join4 } from "node:path";
15711
+ import { join as join5 } from "node:path";
15712
15712
 
15713
15713
  // ../harness/tools/registry.ts
15714
15714
  var registry = /* @__PURE__ */ new Map();
@@ -16436,14 +16436,14 @@ var spawnAgentsTool = {
16436
16436
  },
16437
16437
  async run(args, ctx) {
16438
16438
  if (!ctx.spawn) return "Sub-agents are not available here (depth limit reached or unsupported context).";
16439
- const spawn2 = ctx.spawn;
16439
+ const spawn3 = ctx.spawn;
16440
16440
  const raw = Array.isArray(args.tasks) ? args.tasks : [];
16441
16441
  const reqs = raw.map((t) => spawnReq(t && typeof t === "object" ? t : {})).filter((r) => r !== null);
16442
16442
  if (!reqs.length) return "Error: `tasks` must contain at least one task with a non-empty `task` string.";
16443
16443
  const results = await Promise.all(
16444
16444
  reqs.map(async (req, i) => {
16445
16445
  try {
16446
- const r = await spawn2(req);
16446
+ const r = await spawn3(req);
16447
16447
  return `### Sub-agent ${i + 1}
16448
16448
  ${r.text}${spawnFooter(r)}`;
16449
16449
  } catch (e) {
@@ -17297,6 +17297,12 @@ async function readAuthToken() {
17297
17297
  return null;
17298
17298
  }
17299
17299
  }
17300
+ async function clearAuthToken() {
17301
+ try {
17302
+ await fs2.rm(authTokenPath(), { force: true });
17303
+ } catch {
17304
+ }
17305
+ }
17300
17306
  function nodeAuthToken() {
17301
17307
  return { getToken: async () => await readAuthToken() ?? process.env.CORENEL_TOKEN ?? null };
17302
17308
  }
@@ -17429,9 +17435,9 @@ var PrompdParser = class {
17429
17435
  }
17430
17436
  return issues;
17431
17437
  }
17432
- isValidSemver(version) {
17438
+ isValidSemver(version2) {
17433
17439
  const semverRegex = /^(\d+)\.(\d+)\.(\d+)$/;
17434
- return semverRegex.test(version);
17440
+ return semverRegex.test(version2);
17435
17441
  }
17436
17442
  };
17437
17443
  var PACKAGE_TYPE_DIRS = {
@@ -17613,17 +17619,17 @@ function parsePackageReference(packageRef) {
17613
17619
  }
17614
17620
  const name = match[1];
17615
17621
  const rawVersion = match[2] || "latest";
17616
- const version = import_semver.default.valid(rawVersion) || rawVersion;
17622
+ const version2 = import_semver.default.valid(rawVersion) || rawVersion;
17617
17623
  const scopeMatch = name.match(/^(@[\w.-]+)\//);
17618
17624
  const scope = scopeMatch ? scopeMatch[1] : void 0;
17619
- return { name, version, scope };
17625
+ return { name, version: version2, scope };
17620
17626
  }
17621
17627
  function parsePackageReferenceWithPath(packageRef) {
17622
- const { name, version, scope } = parsePackageReference(packageRef);
17628
+ const { name, version: version2, scope } = parsePackageReference(packageRef);
17623
17629
  const stripped = stripFilePath(packageRef);
17624
17630
  const remainder = packageRef.slice(stripped.length);
17625
17631
  const filePath = remainder.length > 1 ? remainder.slice(1) : void 0;
17626
- return { name, version, scope, filePath };
17632
+ return { name, version: version2, scope, filePath };
17627
17633
  }
17628
17634
  function resolvePackageFile(packagePath, filePath) {
17629
17635
  const normalized = posixNormalize(filePath.replace(/\\/g, "/"));
@@ -20123,8 +20129,8 @@ var MemoryFileSystem = class {
20123
20129
  return joinPosix2(...pathSegments);
20124
20130
  }
20125
20131
  /** Get the virtual file system path for a package. */
20126
- getPackagePath(packageName, version) {
20127
- return `/packages/${packageName}@${version}`;
20132
+ getPackagePath(packageName, version2) {
20133
+ return `/packages/${packageName}@${version2}`;
20128
20134
  }
20129
20135
  /** Get all files under an optional base path. */
20130
20136
  getAllFiles(basePath) {
@@ -20350,6 +20356,7 @@ function nodeToolCtx(signal, opts = {}) {
20350
20356
  kv: inMemoryKv(),
20351
20357
  search: nullSearch,
20352
20358
  confirm: async () => true,
20359
+ ...opts.ask ? { ask: opts.ask } : {},
20353
20360
  ...opts.files ? { files: opts.files, fileMeta: { kind: opts.files.kind, label: opts.files.label, isLocalDisk: opts.files.isLocalDisk, writable: opts.files.writable } } : {}
20354
20361
  };
20355
20362
  }
@@ -20420,6 +20427,12 @@ async function deviceLogin(opts) {
20420
20427
  }
20421
20428
  }
20422
20429
 
20430
+ // src/apiBase.ts
20431
+ var DEFAULT_API_BASE = "https://api.corenel.ai/api";
20432
+ function apiBase2(explicit) {
20433
+ return explicit || process.env.CORENEL_API_BASE || DEFAULT_API_BASE;
20434
+ }
20435
+
20423
20436
  // ../crew/frontmatter.ts
20424
20437
  var import_yaml = __toESM(require_dist(), 1);
20425
20438
  var FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
@@ -20605,6 +20618,90 @@ async function loadCrewAgentAtIfExists(files, root, name, scope = "workspace") {
20605
20618
  }
20606
20619
  }
20607
20620
 
20621
+ // ../harness/guardrail/permission-service.ts
20622
+ var LEVEL_RANK = { allow: 0, ask: 1, deny: 2 };
20623
+ function subjectMatches(tool, glob) {
20624
+ if (tool.address && matchesAnyGlob(tool.address, [glob])) return true;
20625
+ return matchesAnyGlob(tool.name, [glob]);
20626
+ }
20627
+ function specificity(glob) {
20628
+ const literal = glob.replace(/\*/g, "").length;
20629
+ return (glob.includes("*") ? 0 : 1e4) + literal;
20630
+ }
20631
+ function matchLevel(tool, rules) {
20632
+ let best;
20633
+ let bestScore = -1;
20634
+ for (const [glob, level] of Object.entries(rules)) {
20635
+ if (!subjectMatches(tool, glob)) continue;
20636
+ const score = specificity(glob);
20637
+ if (score > bestScore) {
20638
+ bestScore = score;
20639
+ best = level;
20640
+ }
20641
+ }
20642
+ return best;
20643
+ }
20644
+ function mostRestrictive(a, b) {
20645
+ return LEVEL_RANK[a] >= LEVEL_RANK[b] ? a : b;
20646
+ }
20647
+ var PermissionService = class {
20648
+ policy;
20649
+ prompt;
20650
+ defaultForReadOnly;
20651
+ defaultForMutating;
20652
+ ceiling;
20653
+ sessionAllow = /* @__PURE__ */ new Set();
20654
+ constructor(opts) {
20655
+ this.policy = opts.policy;
20656
+ if (opts.prompt) this.prompt = opts.prompt;
20657
+ this.defaultForReadOnly = opts.defaultForReadOnly ?? "allow";
20658
+ this.defaultForMutating = opts.defaultForMutating ?? "ask";
20659
+ if (opts.ceiling) this.ceiling = opts.ceiling;
20660
+ }
20661
+ /** Pre-approve a tool-name glob for the rest of the session (an "ask" becomes "allow"). */
20662
+ preApprove(toolGlob) {
20663
+ this.sessionAllow.add(toolGlob);
20664
+ }
20665
+ reset() {
20666
+ this.sessionAllow.clear();
20667
+ }
20668
+ async check(tool, input) {
20669
+ const level = this.resolveLevel(tool);
20670
+ return this.decide(level, tool.name, input);
20671
+ }
20672
+ /**
20673
+ * Resolve the effective level. Base precedence (highest first):
20674
+ * policy.permissions glob > tool.permission > mutates heuristic > policy.defaultPermission.
20675
+ * Then the ceiling clamps to the more restrictive of base and ceiling.
20676
+ */
20677
+ resolveLevel(tool) {
20678
+ return mostRestrictive(this.resolveBaseLevel(tool), this.resolveCeilingLevel(tool));
20679
+ }
20680
+ resolveBaseLevel(tool) {
20681
+ const matched = this.policy.permissions && matchLevel(tool, this.policy.permissions);
20682
+ if (matched) return matched;
20683
+ if (tool.mutates && this.policy.mutatingDefault) return this.policy.mutatingDefault;
20684
+ if (tool.permission) return tool.permission;
20685
+ if (this.policy.defaultPermission) return this.policy.defaultPermission;
20686
+ if (tool.mutates) return this.defaultForMutating;
20687
+ return this.defaultForReadOnly;
20688
+ }
20689
+ resolveCeilingLevel(tool) {
20690
+ const c = this.ceiling;
20691
+ if (!c) return "allow";
20692
+ const matched = c.overrides && matchLevel(tool, c.overrides);
20693
+ if (matched) return matched;
20694
+ return c.defaultLevel ?? "allow";
20695
+ }
20696
+ async decide(level, name, input) {
20697
+ if (level === "allow") return "allow";
20698
+ if (level === "deny") return "deny";
20699
+ if (this.sessionAllow.size && matchesAnyGlob(name, [...this.sessionAllow])) return "allow";
20700
+ if (!this.prompt) return "deny";
20701
+ return this.prompt.ask({ tool: name, input });
20702
+ }
20703
+ };
20704
+
20608
20705
  // ../harness/guardrail/serialize.ts
20609
20706
  var import_yaml4 = __toESM(require_dist(), 1);
20610
20707
 
@@ -20647,7 +20744,7 @@ async function runCrewAgentCli(opts) {
20647
20744
  opts.warn(`agent "${opts.agent}" is disabled; enable it before running`);
20648
20745
  return 2;
20649
20746
  }
20650
- setGatewayBase(opts.base ?? process.env.CORENEL_API_BASE ?? "https://api.corenel.ai/api");
20747
+ setGatewayBase(apiBase2(opts.base));
20651
20748
  const token = await nodeAuthToken().getToken();
20652
20749
  if (!token) {
20653
20750
  opts.warn("not signed in: set CORENEL_TOKEN, or run `corenel login` on this machine");
@@ -20704,20 +20801,76 @@ import { createRequire } from "node:module";
20704
20801
  import { existsSync, readFileSync } from "node:fs";
20705
20802
  import { dirname as dirname2, join as join3 } from "node:path";
20706
20803
  import { fileURLToPath } from "node:url";
20707
- function sidecarArgs(rest) {
20708
- return rest[0] === "start" ? rest.slice(1) : rest;
20804
+
20805
+ // src/extensions.ts
20806
+ var SIDECAR = { pkg: "@corenel/sidecar", entry: "dist/cli.js" };
20807
+ var EXTENSIONS = [
20808
+ {
20809
+ command: "sidecar",
20810
+ ...SIDECAR,
20811
+ summary: "run the sidecar on this machine",
20812
+ // Everything after the verb is the sidecar's business -- no flag parsing
20813
+ // here, so a flag added there needs no change in this package. A leading
20814
+ // `start` is absorbed because it reads naturally and the sidecar has no
20815
+ // such verb; its real subcommands must pass through untouched.
20816
+ argv: (rest) => rest[0] === "start" ? rest.slice(1) : rest
20817
+ },
20818
+ {
20819
+ command: "acp",
20820
+ ...SIDECAR,
20821
+ summary: "proxy an external coding agent under Corenel policy",
20822
+ /* `corenel acp claude-code --acp-policy read-only` -> the sidecar's own flags.
20823
+ *
20824
+ * ONLY a bare first word is promoted to the target. Anything already spelled
20825
+ * as a flag passes through untouched, because the sidecar is the authority
20826
+ * on its own options -- and because injecting `--acp` in front of `--help`
20827
+ * made the sidecar read "--help" as the name of an agent to proxy. With no
20828
+ * arguments at all there is nothing to run, so show the flags instead of
20829
+ * failing on a missing value. */
20830
+ argv: (rest) => {
20831
+ if (!rest.length) return ["--help"];
20832
+ if (rest[0].startsWith("-")) return rest;
20833
+ return ["--acp", rest[0], ...rest.slice(1)];
20834
+ }
20835
+ },
20836
+ {
20837
+ command: "sessions",
20838
+ ...SIDECAR,
20839
+ summary: "list and inspect local sandbox sessions",
20840
+ argv: (rest) => ["sessions", ...rest]
20841
+ }
20842
+ ];
20843
+ function findExtension(command) {
20844
+ return EXTENSIONS.find((e) => e.command === command);
20845
+ }
20846
+ var EXTENSION_COMMANDS = EXTENSIONS.map((e) => e.command);
20847
+ function missingMessage(e) {
20848
+ return [
20849
+ `${e.command} needs ${e.pkg}, which is not installed.`,
20850
+ "",
20851
+ ` npm install -g ${e.pkg}`,
20852
+ ` pnpm add -g ${e.pkg}`,
20853
+ "",
20854
+ "It ships separately because it is a server with its own release line."
20855
+ ].join("\n");
20709
20856
  }
20857
+
20858
+ // src/sidecar.ts
20710
20859
  function findSidecarEntry(look = {}) {
20860
+ return findExtensionEntry("@corenel/sidecar", "dist/cli.js", look);
20861
+ }
20862
+ function findExtensionEntry(pkg, entry, look = {}) {
20711
20863
  const exists = look.exists ?? existsSync;
20712
20864
  const req = look.resolve ?? createRequire(import.meta.url).resolve;
20713
20865
  try {
20714
- const direct = req("@corenel/sidecar/dist/cli.js");
20866
+ const direct = req(`${pkg}/${entry}`);
20715
20867
  if (exists(direct)) return direct;
20716
20868
  } catch {
20717
20869
  }
20718
20870
  let dir = look.fromDir ?? dirname2(fileURLToPath(import.meta.url));
20871
+ const parts = [...pkg.split("/"), ...entry.split("/")];
20719
20872
  for (let up = 0; up < 8; up++) {
20720
- const candidate = join3(dir, "node_modules", "@corenel", "sidecar", "dist", "cli.js");
20873
+ const candidate = join3(dir, "node_modules", ...parts);
20721
20874
  if (exists(candidate)) return candidate;
20722
20875
  const parent = dirname2(dir);
20723
20876
  if (parent === dir) break;
@@ -20746,20 +20899,20 @@ var SIDECAR_MISSING = [
20746
20899
  "It ships separately because it is a server with its own release line.",
20747
20900
  "Once installed, `corenel sidecar \u2026` and `corenel-sidecar \u2026` are the same thing."
20748
20901
  ].join("\n");
20749
- async function proxyToSidecar(rest, look = {}) {
20750
- const entry = findSidecarEntry(look);
20902
+ async function runExtension(ext, rest, look = {}) {
20903
+ const entry = findExtensionEntry(ext.pkg, ext.entry, look);
20751
20904
  if (!entry) {
20752
- process.stderr.write(`corenel: ${SIDECAR_MISSING}
20905
+ process.stderr.write(`corenel: ${missingMessage(ext)}
20753
20906
  `);
20754
20907
  return 127;
20755
20908
  }
20756
- process.stderr.write(`corenel: sidecar ${versionAt(entry)} (${entry})
20909
+ process.stderr.write(`corenel: ${ext.pkg.replace("@corenel/", "")} ${versionAt(entry)} (${entry})
20757
20910
  `);
20758
- const child = spawn(process.execPath, [entry, ...sidecarArgs(rest)], {
20911
+ const child = spawn(process.execPath, [entry, ...ext.argv(rest)], {
20759
20912
  stdio: "inherit",
20760
- // So `corenel sidecar --help` prints `corenel sidecar …` in its usage rather
20761
- // than the standalone name the user did not type.
20762
- env: { ...process.env, CORENEL_ARGV0: "corenel sidecar" }
20913
+ // So the extension's own --help prints the command the user actually typed
20914
+ // rather than its standalone name.
20915
+ env: { ...process.env, CORENEL_ARGV0: `corenel ${ext.command}` }
20763
20916
  });
20764
20917
  const forward = (sig) => () => {
20765
20918
  if (!child.killed) child.kill(sig);
@@ -20781,6 +20934,539 @@ async function proxyToSidecar(rest, look = {}) {
20781
20934
  }
20782
20935
  }
20783
20936
 
20937
+ // src/commands.ts
20938
+ var COMMANDS = [
20939
+ { name: "", args: "", summary: "with no command: an interactive agent in this directory" },
20940
+ { name: "run", args: '"<prompt>" [--session ID]', summary: "one-shot turn, then exit (--session runs it inside a sandbox)" },
20941
+ { name: "run-agent", args: '<name> --input "<text>"', summary: "run a crew agent; events as JSON Lines on stdout" },
20942
+ { name: "sidecar", args: "[start] [flags]", summary: "run the sidecar on this machine" },
20943
+ { name: "acp", args: "<agent> [flags]", summary: "proxy an external coding agent under Corenel policy" },
20944
+ { name: "sessions", args: "[list|show|create|run]", summary: "create, list and run in local sandbox sessions" },
20945
+ { name: "login", args: "[--base URL]", summary: "sign in through your browser (device flow)" },
20946
+ { name: "auth", summary: "show whether you are signed in, and as what" },
20947
+ { name: "logout", summary: "forget the stored token" },
20948
+ { name: "doctor", summary: "check the things that usually turn out to be wrong" }
20949
+ ];
20950
+ var COMMAND_NAMES = COMMANDS.map((c) => c.name).filter(Boolean);
20951
+ function isCommand(name) {
20952
+ return COMMAND_NAMES.includes(name);
20953
+ }
20954
+ function isHelpFlag(a) {
20955
+ return a === "--help" || a === "-h" || a === "help";
20956
+ }
20957
+ function isVersionFlag(a) {
20958
+ return a === "--version" || a === "-v" || a === "version";
20959
+ }
20960
+ function helpText(version2) {
20961
+ const shown = COMMANDS.filter((c) => c.name);
20962
+ const left = (c) => `corenel ${c.name}${c.args ? ` ${c.args}` : ""}`;
20963
+ const width = Math.max(...shown.map((c) => left(c).length));
20964
+ const bare = COMMANDS.find((c) => !c.name);
20965
+ return [
20966
+ `corenel ${version2} \u2014 the harness, in node.`,
20967
+ "",
20968
+ "Usage:",
20969
+ ` corenel${" ".repeat(Math.max(1, width - 7))} ${bare ? bare.summary : ""}`,
20970
+ ...shown.map((c) => ` ${left(c).padEnd(width)} ${c.summary}`),
20971
+ "",
20972
+ "Common flags:",
20973
+ " --model <id> model for this turn (default gpt-4o-mini)",
20974
+ " --base <url> API base (default https://api.corenel.ai/api, or CORENEL_API_BASE)",
20975
+ " --allow-shell run commands without asking each time",
20976
+ " --no-tui plain line-by-line mode (automatic when output is piped)",
20977
+ " --tui force the full terminal face, and fail if it cannot start",
20978
+ " --resume [id] reopen the last conversation, or the one named",
20979
+ " --debug trace every agent step (also CORENEL_DEBUG=1)",
20980
+ " --version, -v print the version",
20981
+ " --help, -h print this",
20982
+ "",
20983
+ "--resume reopens a CONVERSATION (this face's own chat log, saved under",
20984
+ ".corenel/sessions/) -- not the same thing as `run --session ID` or the",
20985
+ "`sessions` command below, which forward into a sandbox on the sidecar.",
20986
+ "Same word, two different nouns.",
20987
+ "",
20988
+ "sidecar, acp and sessions are provided by @corenel/sidecar, installed separately.",
20989
+ "Each takes its own flags: `corenel sidecar --help`.",
20990
+ ""
20991
+ ].join("\n");
20992
+ }
20993
+
20994
+ // src/version.ts
20995
+ import { createRequire as createRequire2 } from "node:module";
20996
+ import { readFileSync as readFileSync2 } from "node:fs";
20997
+ import { dirname as dirname3, join as join4 } from "node:path";
20998
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
20999
+ function selfPath() {
21000
+ try {
21001
+ return fileURLToPath2(import.meta.url);
21002
+ } catch {
21003
+ return process.argv[1] ?? "(unknown)";
21004
+ }
21005
+ }
21006
+ function version(read = (p) => readFileSync2(p, "utf8")) {
21007
+ let dir = dirname3(selfPath());
21008
+ for (let up = 0; up < 4; up++) {
21009
+ try {
21010
+ const parsed = JSON.parse(read(join4(dir, "package.json")));
21011
+ const v = parsed;
21012
+ if (v.name === "@corenel/cli" && typeof v.version === "string") return v.version;
21013
+ } catch {
21014
+ }
21015
+ const parent = dirname3(dir);
21016
+ if (parent === dir) break;
21017
+ dir = parent;
21018
+ }
21019
+ try {
21020
+ const req = createRequire2(import.meta.url);
21021
+ const parsed = JSON.parse(read(req.resolve("@corenel/cli/package.json")));
21022
+ const v = parsed.version;
21023
+ if (typeof v === "string") return v;
21024
+ } catch {
21025
+ }
21026
+ return "(unknown)";
21027
+ }
21028
+
21029
+ // src/auth.ts
21030
+ function hintOf(token) {
21031
+ const t = token.trim();
21032
+ if (t.length <= 8) return "****";
21033
+ return `${t.slice(0, 4)}\u2026${t.slice(-2)} (${t.length} chars)`;
21034
+ }
21035
+ async function authState(read = readAuthToken, env = process.env) {
21036
+ const path = authTokenPath();
21037
+ const stored = await read();
21038
+ if (stored) return { source: "file", path, hint: hintOf(stored) };
21039
+ if (env.CORENEL_TOKEN) return { source: "env", path, hint: hintOf(env.CORENEL_TOKEN) };
21040
+ return { source: "none", path };
21041
+ }
21042
+ function describeAuth(s, base) {
21043
+ if (s.source === "none") {
21044
+ return [
21045
+ "Not signed in.",
21046
+ ` Run \`corenel login\`, or set CORENEL_TOKEN=<token>.`,
21047
+ ` Token would be stored at ${s.path}`
21048
+ ].join("\n");
21049
+ }
21050
+ return [
21051
+ `Signed in (${s.source === "env" ? "CORENEL_TOKEN environment variable" : s.path}).`,
21052
+ ` token ${s.hint}`,
21053
+ ` api ${base}`,
21054
+ s.source === "env" ? " NOTE: the environment wins over any stored token, so `corenel logout` will not change this." : null
21055
+ ].filter(Boolean).join("\n");
21056
+ }
21057
+ async function runAuth(out = (s) => process.stdout.write(s)) {
21058
+ out(`${describeAuth(await authState(), apiBase2())}
21059
+ `);
21060
+ }
21061
+ async function runLogout(out = (s) => process.stdout.write(s)) {
21062
+ const before = await authState();
21063
+ await clearAuthToken();
21064
+ if (before.source === "file") out(`Signed out. Removed ${before.path}
21065
+ `);
21066
+ else out("Nothing to forget \u2014 no stored token.\n");
21067
+ if (process.env.CORENEL_TOKEN) {
21068
+ out(" NOTE: CORENEL_TOKEN is still set in this environment, so you are still authenticated.\n");
21069
+ }
21070
+ }
21071
+
21072
+ // src/doctor.ts
21073
+ var MARK = { ok: " ok ", warn: " warn ", fail: " FAIL " };
21074
+ function formatChecks(checks) {
21075
+ return checks.map((c) => `[${MARK[c.status]}] ${c.name.padEnd(12)} ${c.detail}`).join("\n");
21076
+ }
21077
+ async function checkToken(base, token, f = fetch) {
21078
+ if (!token) return { name: "token", status: "warn", detail: "no credential \u2014 run `corenel login`" };
21079
+ let res;
21080
+ try {
21081
+ res = await f(`${base}/v1/chat/completions`, {
21082
+ method: "POST",
21083
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
21084
+ body: JSON.stringify({ model: "gpt-4o-mini", messages: [] })
21085
+ });
21086
+ } catch (e) {
21087
+ return { name: "token", status: "fail", detail: `could not reach ${base} (${e instanceof Error ? e.message : String(e)})` };
21088
+ }
21089
+ if (res.status === 401 || res.status === 403) {
21090
+ return { name: "token", status: "fail", detail: `rejected by ${base} (${res.status}) \u2014 run \`corenel login\` again` };
21091
+ }
21092
+ if (res.status === 404) {
21093
+ return { name: "token", status: "fail", detail: `${base}/v1/chat/completions is 404 \u2014 the base is wrong (it usually needs /api)` };
21094
+ }
21095
+ const ct = res.headers.get("content-type") ?? "";
21096
+ if (!ct.includes("json")) {
21097
+ return { name: "token", status: "fail", detail: `${base} answered ${res.status} ${ct || "no content-type"} \u2014 that is not the API` };
21098
+ }
21099
+ return { name: "token", status: "ok", detail: `accepted by ${base} (${res.status})` };
21100
+ }
21101
+ async function collectChecks(f = fetch) {
21102
+ const base = apiBase2();
21103
+ const checks = [
21104
+ { name: "binary", status: "ok", detail: selfPath() },
21105
+ { name: "version", status: "ok", detail: `@corenel/cli ${version()}` },
21106
+ { name: "node", status: "ok", detail: process.version },
21107
+ {
21108
+ name: "api",
21109
+ status: "ok",
21110
+ detail: base === DEFAULT_API_BASE ? base : `${base} (overridden; default is ${DEFAULT_API_BASE})`
21111
+ }
21112
+ ];
21113
+ try {
21114
+ const u = new URL(base);
21115
+ if (u.pathname === "" || u.pathname === "/") {
21116
+ checks.push({ name: "api path", status: "warn", detail: "base has no path \u2014 the API is mounted under /api" });
21117
+ }
21118
+ } catch {
21119
+ checks.push({ name: "api", status: "fail", detail: `${base} is not a URL` });
21120
+ }
21121
+ const auth = await authState();
21122
+ checks.push({
21123
+ name: "signed in",
21124
+ status: auth.source === "none" ? "warn" : "ok",
21125
+ detail: auth.source === "none" ? "no" : `yes, from ${auth.source === "env" ? "CORENEL_TOKEN" : auth.path} (${auth.hint})`
21126
+ });
21127
+ checks.push(await checkToken(base, await readAuthToken() ?? process.env.CORENEL_TOKEN ?? null, f));
21128
+ const sidecar = findSidecarEntry();
21129
+ checks.push({
21130
+ name: "sidecar",
21131
+ status: sidecar ? "ok" : "warn",
21132
+ detail: sidecar ? `${versionAt(sidecar)} at ${sidecar}` : "not installed \u2014 `npm i -g @corenel/sidecar`"
21133
+ });
21134
+ return checks;
21135
+ }
21136
+ async function runDoctor(out = (s) => process.stdout.write(s), f = fetch) {
21137
+ const checks = await collectChecks(f);
21138
+ out(`${formatChecks(checks)}
21139
+ `);
21140
+ const failed = checks.filter((c) => c.status === "fail");
21141
+ if (failed.length) {
21142
+ out(`
21143
+ ${failed.length} problem${failed.length > 1 ? "s" : ""} above.
21144
+ `);
21145
+ return 1;
21146
+ }
21147
+ return 0;
21148
+ }
21149
+
21150
+ // src/repl.ts
21151
+ import { createInterface } from "node:readline";
21152
+ import { TermSession } from "@corenel/term/session";
21153
+ import { describeToolCall } from "@corenel/term/describe";
21154
+ function isQuit(line) {
21155
+ const t = line.trim().toLowerCase();
21156
+ return t === "/exit" || t === "/quit" || t === "exit" || t === "quit";
21157
+ }
21158
+ function nextShownCursor(itemsLength, shown) {
21159
+ return itemsLength < shown ? 0 : shown;
21160
+ }
21161
+ function formatQuestion(q) {
21162
+ const lines = [` ${q.header} ${q.question}`];
21163
+ q.options.forEach((o, i) => {
21164
+ lines.push(` ${i + 1}) ${o.label}`);
21165
+ });
21166
+ return `${lines.join("\n")}
21167
+ `;
21168
+ }
21169
+ function parseQuestionAnswer(q, line) {
21170
+ if (line === null) return null;
21171
+ const t = line.trim();
21172
+ if (!t) return null;
21173
+ if (/^\d+$/.test(t)) {
21174
+ const n = Number(t);
21175
+ if (n >= 1 && n <= q.options.length) return { [q.header]: [q.options[n - 1].label] };
21176
+ }
21177
+ return { [q.header]: [t] };
21178
+ }
21179
+ var REPL_BANNER = (model, cwd) => [
21180
+ `corenel \u2014 ${model}, working in ${cwd}`,
21181
+ "Type a request. /clear forgets the conversation, /exit leaves, Ctrl-C stops a turn.",
21182
+ ""
21183
+ ].join("\n");
21184
+ function makeEventRenderer(write) {
21185
+ let streaming = false;
21186
+ const endStream = () => {
21187
+ if (streaming) {
21188
+ write("\n");
21189
+ streaming = false;
21190
+ }
21191
+ };
21192
+ return (e) => {
21193
+ switch (e.type) {
21194
+ case "assistant-delta":
21195
+ streaming = true;
21196
+ write(e.delta);
21197
+ break;
21198
+ case "tool-call": {
21199
+ endStream();
21200
+ const subject = describeToolCall(e.name, e.args);
21201
+ write(` \xB7 ${e.name}${subject ? ` ${subject}` : ""}
21202
+ `);
21203
+ break;
21204
+ }
21205
+ case "tool-result":
21206
+ if (e.isError) write(` ! ${e.name} failed
21207
+ `);
21208
+ break;
21209
+ case "done":
21210
+ endStream();
21211
+ break;
21212
+ default:
21213
+ break;
21214
+ }
21215
+ };
21216
+ }
21217
+ async function runRepl(deps) {
21218
+ const input = deps.input ?? process.stdin;
21219
+ const output = deps.output ?? process.stdout;
21220
+ let atLineStart = true;
21221
+ const write = (s) => {
21222
+ output.write(s);
21223
+ if (s.length > 0) atLineStart = s.endsWith("\n");
21224
+ };
21225
+ const writeLine = (s) => {
21226
+ if (!atLineStart) write("\n");
21227
+ write(s);
21228
+ };
21229
+ write(REPL_BANNER(deps.model, deps.cwd));
21230
+ const render = makeEventRenderer(write);
21231
+ const session = new TermSession({
21232
+ cwd: deps.cwd,
21233
+ model: deps.model,
21234
+ system: deps.system,
21235
+ client: deps.client,
21236
+ tools: deps.tools,
21237
+ toolCtx: (signal, askUser) => deps.toolCtx(signal, askUser),
21238
+ onEvent: render,
21239
+ ...deps.runner ? { runner: deps.runner } : {},
21240
+ ...deps.approveAll ? { approveAll: true } : {},
21241
+ ...deps.persistence ? { persistence: deps.persistence } : {}
21242
+ });
21243
+ let shown = 0;
21244
+ session.subscribe(() => {
21245
+ const items = session.getSnapshot().committed;
21246
+ shown = nextShownCursor(items.length, shown);
21247
+ for (; shown < items.length; shown++) {
21248
+ const it = items[shown];
21249
+ if (it.kind !== "note") continue;
21250
+ writeLine(` ${it.level === "info" ? "" : "! "}${it.text}
21251
+ `);
21252
+ if (it.detail) write(`${it.detail}
21253
+ `);
21254
+ }
21255
+ });
21256
+ if (deps.resume) {
21257
+ await session.resume(deps.resume.id);
21258
+ const restored = session.getSnapshot();
21259
+ if (restored.session) {
21260
+ writeLine(` resumed ${restored.session.id} - ${restored.committed.length} messages
21261
+ `);
21262
+ }
21263
+ }
21264
+ const rl = createInterface({ input, output });
21265
+ let closed = false;
21266
+ rl.on("close", () => {
21267
+ closed = true;
21268
+ });
21269
+ const ask = (q) => closed ? Promise.resolve(null) : new Promise((resolve2) => {
21270
+ const onClose = () => resolve2(null);
21271
+ rl.once("close", onClose);
21272
+ rl.question(q, (answer) => {
21273
+ rl.off("close", onClose);
21274
+ resolve2(answer);
21275
+ });
21276
+ });
21277
+ let turnActive = false;
21278
+ const onSigint = () => {
21279
+ if (turnActive) session.abort();
21280
+ else {
21281
+ write("\n");
21282
+ rl.close();
21283
+ }
21284
+ };
21285
+ rl.on("SIGINT", onSigint);
21286
+ const permission = new PermissionService({
21287
+ policy: STANDARD_POLICY,
21288
+ prompt: {
21289
+ ask: async (req) => {
21290
+ if (deps.approveAll) return "allow";
21291
+ const detail = req.input?.command;
21292
+ write(`
21293
+ ${req.tool}${typeof detail === "string" ? `: ${detail}` : ""}
21294
+ `);
21295
+ const answer = await ask(" run it? [y/N] ");
21296
+ return answer !== null && /^y(es)?$/i.test(answer.trim()) ? "allow" : "deny";
21297
+ }
21298
+ }
21299
+ });
21300
+ session.attachPermission(permission);
21301
+ let questionOpen = false;
21302
+ session.subscribe(() => {
21303
+ const modal = session.getSnapshot().modal;
21304
+ if (!modal || modal.kind !== "user") {
21305
+ questionOpen = false;
21306
+ return;
21307
+ }
21308
+ if (questionOpen) return;
21309
+ questionOpen = true;
21310
+ const q = modal.questions[0];
21311
+ if (!q) {
21312
+ session.answer(null);
21313
+ return;
21314
+ }
21315
+ writeLine(formatQuestion(q));
21316
+ void ask(" answer (number, text, or empty to skip): ").then((line) => {
21317
+ if (session.getSnapshot().modal?.kind !== "user") return;
21318
+ session.answer(parseQuestionAnswer(q, line));
21319
+ });
21320
+ });
21321
+ for (; ; ) {
21322
+ const line = await ask("\u203A ");
21323
+ if (line === null) break;
21324
+ const text = line.trim();
21325
+ if (!text) continue;
21326
+ if (isQuit(text)) break;
21327
+ turnActive = true;
21328
+ await session.submit(text);
21329
+ turnActive = false;
21330
+ if (session.wantsExit) break;
21331
+ }
21332
+ rl.off("SIGINT", onSigint);
21333
+ rl.close();
21334
+ return 0;
21335
+ }
21336
+
21337
+ // src/cli.ts
21338
+ import { createSessionPersistence } from "@corenel/term/persist";
21339
+
21340
+ // src/shellTool.ts
21341
+ import { spawn as spawn2 } from "node:child_process";
21342
+ var MAX_OUTPUT = 3e4;
21343
+ var DEFAULT_TIMEOUT_MS = 12e4;
21344
+ function truncate(s, max = MAX_OUTPUT) {
21345
+ if (s.length <= max) return s;
21346
+ const kept = s.slice(0, max);
21347
+ return `${kept}
21348
+ \u2026 [${s.length - max} more characters truncated]`;
21349
+ }
21350
+ function formatResult(r) {
21351
+ const parts = [r.timedOut ? "timed out" : `exit ${r.code ?? "unknown"}`];
21352
+ if (r.stdout.trim()) parts.push(`stdout:
21353
+ ${truncate(r.stdout)}`);
21354
+ if (r.stderr.trim()) parts.push(`stderr:
21355
+ ${truncate(r.stderr)}`);
21356
+ if (!r.stdout.trim() && !r.stderr.trim()) parts.push("(no output)");
21357
+ return parts.join("\n");
21358
+ }
21359
+ function killTree(child) {
21360
+ const pid = child.pid;
21361
+ if (pid === void 0) {
21362
+ child.kill("SIGKILL");
21363
+ return;
21364
+ }
21365
+ if (process.platform === "win32") {
21366
+ spawn2("taskkill", ["/pid", String(pid), "/T", "/F"], { stdio: "ignore" }).on("error", () => {
21367
+ child.kill("SIGKILL");
21368
+ });
21369
+ return;
21370
+ }
21371
+ try {
21372
+ process.kill(-pid, "SIGKILL");
21373
+ } catch {
21374
+ child.kill("SIGKILL");
21375
+ }
21376
+ }
21377
+ function execute(command, opts) {
21378
+ return new Promise((resolve2) => {
21379
+ const child = spawn2(command, {
21380
+ cwd: opts.cwd,
21381
+ shell: true,
21382
+ // Its own process group on POSIX, so killTree can signal the group rather
21383
+ // than the shell alone. On Windows this is a no-op; taskkill /T does it.
21384
+ detached: process.platform !== "win32",
21385
+ // A child inheriting this process's stdin would compete with the REPL's
21386
+ // readline for keystrokes; an interactive command gets EOF instead of
21387
+ // silently eating the next thing typed.
21388
+ stdio: ["ignore", "pipe", "pipe"]
21389
+ });
21390
+ let stdout = "";
21391
+ let stderr = "";
21392
+ let timedOut = false;
21393
+ child.stdout?.on("data", (d) => {
21394
+ stdout += d.toString();
21395
+ });
21396
+ child.stderr?.on("data", (d) => {
21397
+ stderr += d.toString();
21398
+ });
21399
+ const timer = setTimeout(() => {
21400
+ timedOut = true;
21401
+ killTree(child);
21402
+ }, opts.timeoutMs ?? DEFAULT_TIMEOUT_MS);
21403
+ const onAbort = () => {
21404
+ killTree(child);
21405
+ };
21406
+ opts.signal?.addEventListener("abort", onAbort, { once: true });
21407
+ const finish = (code) => {
21408
+ clearTimeout(timer);
21409
+ opts.signal?.removeEventListener("abort", onAbort);
21410
+ resolve2({ code, stdout, stderr, timedOut });
21411
+ };
21412
+ child.on("error", (e) => {
21413
+ stderr += String(e);
21414
+ finish(null);
21415
+ });
21416
+ child.on("close", (code) => finish(code));
21417
+ });
21418
+ }
21419
+ function shellTool(cwd) {
21420
+ return {
21421
+ name: "shell",
21422
+ description: "Run a shell command in the working directory and return its exit code and output. Use for build, test, install, git and any other command the user asks you to run. Commands run one at a time; chain with && if order matters.",
21423
+ namespace: "shell",
21424
+ mutates: true,
21425
+ // Shown beside the permission prompt: a rule named `shell` only answers
21426
+ // "what can it do to me" if you already know the catalogue.
21427
+ means: "run any command on this machine, as you",
21428
+ parameters: {
21429
+ type: "object",
21430
+ properties: {
21431
+ command: { type: "string", description: "The command line to run, exactly as typed in a terminal." }
21432
+ },
21433
+ required: ["command"]
21434
+ },
21435
+ async run(args, ctx) {
21436
+ const command = args.command;
21437
+ if (typeof command !== "string" || !command.trim()) return "error: no command given";
21438
+ const opts = { cwd };
21439
+ if (ctx.signal) opts.signal = ctx.signal;
21440
+ return formatResult(await execute(command, opts));
21441
+ }
21442
+ };
21443
+ }
21444
+
21445
+ // src/tuiChoice.ts
21446
+ function chooseFace(env) {
21447
+ if (env.argv.includes("--no-tui")) return "readline";
21448
+ if (env.argv.includes("--tui")) return "tui";
21449
+ if (!env.stdinTty || !env.stdoutTty) return "readline";
21450
+ if (env.term === "dumb") return "readline";
21451
+ if (env.ci) return "readline";
21452
+ return "tui";
21453
+ }
21454
+ var TuiUnavailableError = class extends Error {
21455
+ constructor(cause) {
21456
+ super(`the terminal face could not start: ${cause instanceof Error ? cause.message : String(cause)}`);
21457
+ this.name = "TuiUnavailableError";
21458
+ }
21459
+ };
21460
+ function currentFaceEnv(argv) {
21461
+ return {
21462
+ stdinTty: process.stdin.isTTY === true,
21463
+ stdoutTty: process.stdout.isTTY === true,
21464
+ term: process.env.TERM,
21465
+ ci: Boolean(process.env.CI),
21466
+ argv
21467
+ };
21468
+ }
21469
+
20784
21470
  // src/cli.ts
20785
21471
  function flag(argv, name, fallback) {
20786
21472
  const i = argv.indexOf(`--${name}`);
@@ -20808,31 +21494,45 @@ function promptOf(argv) {
20808
21494
  }
20809
21495
  return parts.join(" ").trim();
20810
21496
  }
20811
- async function run(argv) {
20812
- const prompt = promptOf(argv);
20813
- if (!prompt) {
20814
- process.stderr.write('usage: corenel run "<prompt>" [--model M] [--base URL]\n');
20815
- process.exit(2);
20816
- }
20817
- setGatewayBase(flag(argv, "base", process.env.CORENEL_API_BASE || "https://api.prompd.app/api"));
21497
+ async function agentSetup(argv) {
21498
+ setGatewayBase(apiBase2(flag(argv, "base", "")));
20818
21499
  const token = await nodeAuthToken().getToken();
20819
21500
  if (!token) {
20820
21501
  process.stderr.write("corenel: not signed in.\n Run `corenel login`, or set CORENEL_TOKEN=<token> (a gateway bearer token), then try again.\n");
20821
21502
  process.exit(2);
20822
21503
  }
20823
21504
  registerGuard(tokenGuard(() => token));
20824
- const client = createChatClient({ getToken: async () => token });
20825
- const tools = allTools();
20826
- setPromptHost(nodePromptHost(new NodeFileService(join4(corenelDir(), "config"))));
21505
+ const tools = [...allTools(), shellTool(process.cwd())];
21506
+ setPromptHost(nodePromptHost(new NodeFileService(join5(corenelDir(), "config"))));
20827
21507
  let system = "You are corenel, a concise CLI assistant.";
20828
21508
  try {
20829
21509
  system = await composeAgentSystem({ mode: "auto", tools: tools.map((t) => ({ name: t.name, description: t.description })) });
20830
21510
  } catch {
20831
21511
  }
21512
+ return {
21513
+ client: createChatClient({ getToken: async () => token }),
21514
+ model: flag(argv, "model", "gpt-4o-mini"),
21515
+ system,
21516
+ tools
21517
+ };
21518
+ }
21519
+ async function run(argv) {
21520
+ const prompt = promptOf(argv);
21521
+ if (!prompt) {
21522
+ process.stderr.write('usage: corenel run "<prompt>" [--model M] [--base URL] [--session ID]\n');
21523
+ process.exit(2);
21524
+ }
21525
+ const session = flag(argv, "session", "");
21526
+ if (session) {
21527
+ const ext = findExtension("sessions");
21528
+ process.exitCode = ext ? await runExtension(ext, ["run", session, prompt]) : 2;
21529
+ return;
21530
+ }
21531
+ const { client, model, system, tools } = await agentSetup(argv);
20832
21532
  const ac = new AbortController();
20833
21533
  const result = await runAgent({
20834
21534
  client,
20835
- model: flag(argv, "model", "gpt-4o-mini"),
21535
+ model,
20836
21536
  system,
20837
21537
  messages: [{ role: "user", content: prompt }],
20838
21538
  tools,
@@ -20841,8 +21541,71 @@ async function run(argv) {
20841
21541
  });
20842
21542
  process.stdout.write(result.text + "\n");
20843
21543
  }
21544
+ async function interactive(argv) {
21545
+ const { client, model, system, tools } = await agentSetup(argv);
21546
+ const approveAll = argv.includes("--allow-shell");
21547
+ const cwd = process.cwd();
21548
+ const files = new NodeFileService(cwd);
21549
+ const persistence = createSessionPersistence(files);
21550
+ const resumeAt = argv.indexOf("--resume");
21551
+ const resumeId = resumeAt >= 0 && argv[resumeAt + 1] && !argv[resumeAt + 1].startsWith("--") ? argv[resumeAt + 1] : void 0;
21552
+ const resume = resumeAt >= 0 ? { id: resumeId } : void 0;
21553
+ if (chooseFace(currentFaceEnv(argv)) === "tui") {
21554
+ try {
21555
+ const { runTui } = await import("@corenel/term/ink");
21556
+ process.exitCode = await runTui({
21557
+ cwd,
21558
+ model,
21559
+ system,
21560
+ client,
21561
+ tools,
21562
+ version: version(),
21563
+ toolCtx: (signal, ask) => nodeToolCtx(signal, { files, ask }),
21564
+ ...approveAll ? { approveAll: true } : {},
21565
+ persistence,
21566
+ ...resume ? { resume } : {}
21567
+ });
21568
+ return;
21569
+ } catch (e) {
21570
+ if (argv.includes("--tui")) throw new TuiUnavailableError(e);
21571
+ process.stderr.write(`corenel: terminal face unavailable, falling back (${e instanceof Error ? e.message : String(e)})
21572
+ `);
21573
+ }
21574
+ }
21575
+ process.exitCode = await runRepl({
21576
+ client,
21577
+ model,
21578
+ system,
21579
+ tools,
21580
+ toolCtx: (signal, ask) => nodeToolCtx(signal, { files, ...ask ? { ask } : {} }),
21581
+ cwd,
21582
+ // --allow-shell skips the per-command prompt. Named after the sidecar's
21583
+ // flag, which grants the same thing.
21584
+ approveAll,
21585
+ persistence,
21586
+ ...resume ? { resume } : {}
21587
+ });
21588
+ }
20844
21589
  async function main() {
20845
21590
  const [cmd, ...rest] = process.argv.slice(2);
21591
+ setAgentLogging(process.argv.includes("--debug") || process.env.CORENEL_DEBUG === "1");
21592
+ if (cmd !== void 0 && isVersionFlag(cmd)) {
21593
+ process.stdout.write(`${version()}
21594
+ `);
21595
+ return;
21596
+ }
21597
+ if (cmd !== void 0 && isHelpFlag(cmd)) {
21598
+ process.stdout.write(helpText(version()));
21599
+ return;
21600
+ }
21601
+ if (cmd === void 0) {
21602
+ await interactive([]);
21603
+ return;
21604
+ }
21605
+ if (!isCommand(cmd) && cmd.startsWith("-")) {
21606
+ await interactive([cmd, ...rest]);
21607
+ return;
21608
+ }
20846
21609
  switch (cmd) {
20847
21610
  case "run":
20848
21611
  await run(rest);
@@ -20867,33 +21630,36 @@ async function main() {
20867
21630
  process.exitCode = code;
20868
21631
  break;
20869
21632
  }
20870
- case "sidecar": {
20871
- process.exitCode = await proxyToSidecar(rest);
21633
+ case "sidecar":
21634
+ case "acp":
21635
+ case "sessions": {
21636
+ const ext = findExtension(cmd);
21637
+ process.exitCode = ext ? await runExtension(ext, rest) : 2;
20872
21638
  break;
20873
21639
  }
20874
21640
  case "login": {
20875
- const base = flag(rest, "base", process.env.CORENEL_API_BASE || "https://api.corenel.ai/api");
21641
+ const base = apiBase2(flag(rest, "base", ""));
20876
21642
  await deviceLogin({ base, store: writeAuthToken });
20877
21643
  process.stdout.write(`
20878
21644
  Logged in. Token saved to ${authTokenPath()}
20879
21645
  `);
20880
21646
  break;
20881
21647
  }
21648
+ case "auth":
21649
+ await runAuth();
21650
+ break;
21651
+ case "logout":
21652
+ await runLogout();
21653
+ break;
21654
+ case "doctor":
21655
+ process.exitCode = await runDoctor();
21656
+ break;
20882
21657
  default:
20883
- process.stdout.write([
20884
- "corenel \u2014 the harness, in node.",
20885
- "",
20886
- " corenel login [--base URL] OAuth device flow -> ~/.corenel/token",
20887
- ' corenel run "<prompt>" [--model M] [--base URL] one-shot turn (needs a login or CORENEL_TOKEN)',
20888
- ' corenel run-agent <name> --input "<text>" run a crew agent; events as JSON Lines on stdout',
20889
- " corenel sidecar [start] [flags] run the sidecar on this machine (needs @corenel/sidecar)",
20890
- "",
20891
- " `corenel sidecar --help` lists its flags. It is also installed standalone",
20892
- " as `corenel-sidecar`, for machines that run only the sidecar.",
20893
- "",
20894
- " (ask/chat to follow.)",
20895
- ""
20896
- ].join("\n"));
21658
+ process.stderr.write(`corenel: unknown command "${cmd}"
21659
+
21660
+ `);
21661
+ process.stderr.write(helpText(version()));
21662
+ process.exitCode = 2;
20897
21663
  }
20898
21664
  }
20899
21665
  function friendlyError(msg) {