@learnrudi/cli 1.2.0 → 1.4.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/index.cjs +538 -283
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -199,6 +199,16 @@ __export(src_exports, {
199
199
  searchPackages: () => searchPackages,
200
200
  verifyHash: () => verifyHash
201
201
  });
202
+ function getLocalRegistryPaths() {
203
+ if (process.env.USE_LOCAL_REGISTRY !== "true") {
204
+ return [];
205
+ }
206
+ return [
207
+ import_path2.default.join(process.cwd(), "registry", "index.json"),
208
+ import_path2.default.join(process.cwd(), "..", "registry", "index.json"),
209
+ "/Users/hoff/dev/RUDI/registry/index.json"
210
+ ];
211
+ }
202
212
  async function fetchIndex(options = {}) {
203
213
  const { url = DEFAULT_REGISTRY_URL, force = false } = options;
204
214
  const localResult = getLocalIndex();
@@ -276,7 +286,7 @@ function getCacheMtime() {
276
286
  }
277
287
  }
278
288
  function getLocalIndex() {
279
- for (const localPath of LOCAL_REGISTRY_PATHS) {
289
+ for (const localPath of getLocalRegistryPaths()) {
280
290
  if (import_fs2.default.existsSync(localPath)) {
281
291
  try {
282
292
  const index = JSON.parse(import_fs2.default.readFileSync(localPath, "utf-8"));
@@ -367,7 +377,7 @@ function getPackageKinds() {
367
377
  async function downloadPackage(pkg, destPath, options = {}) {
368
378
  const { onProgress } = options;
369
379
  const registryPath = pkg.path;
370
- for (const basePath of LOCAL_REGISTRY_PATHS) {
380
+ for (const basePath of getLocalRegistryPaths()) {
371
381
  const registryDir = import_path2.default.dirname(basePath);
372
382
  const pkgSourcePath = import_path2.default.join(registryDir, registryPath);
373
383
  if (import_fs2.default.existsSync(pkgSourcePath)) {
@@ -415,8 +425,8 @@ async function downloadRuntime(runtime, version, destPath, options = {}) {
415
425
  import_fs2.default.rmSync(destPath, { recursive: true });
416
426
  }
417
427
  import_fs2.default.mkdirSync(destPath, { recursive: true });
418
- const { execSync: execSync4 } = await import("child_process");
419
- execSync4(`tar -xzf "${tempFile}" -C "${destPath}" --strip-components=1`, {
428
+ const { execSync: execSync5 } = await import("child_process");
429
+ execSync5(`tar -xzf "${tempFile}" -C "${destPath}" --strip-components=1`, {
420
430
  stdio: "pipe"
421
431
  });
422
432
  import_fs2.default.unlinkSync(tempFile);
@@ -454,7 +464,7 @@ async function downloadTool(toolName, destPath, options = {}) {
454
464
  import_fs2.default.rmSync(destPath, { recursive: true });
455
465
  }
456
466
  import_fs2.default.mkdirSync(destPath, { recursive: true });
457
- const { execSync: execSync4 } = await import("child_process");
467
+ const { execSync: execSync5 } = await import("child_process");
458
468
  const downloads = toolManifest.downloads?.[platformArch];
459
469
  if (downloads && Array.isArray(downloads)) {
460
470
  const downloadedUrls = /* @__PURE__ */ new Set();
@@ -483,11 +493,11 @@ async function downloadTool(toolName, destPath, options = {}) {
483
493
  onProgress?.({ phase: "extracting", tool: toolName, binary: import_path2.default.basename(binary) });
484
494
  const archiveType = type || guessArchiveType(urlFilename);
485
495
  if (archiveType === "zip") {
486
- execSync4(`unzip -o "${tempFile}" -d "${destPath}"`, { stdio: "pipe" });
496
+ execSync5(`unzip -o "${tempFile}" -d "${destPath}"`, { stdio: "pipe" });
487
497
  } else if (archiveType === "tar.xz") {
488
- execSync4(`tar -xJf "${tempFile}" -C "${destPath}"`, { stdio: "pipe" });
498
+ execSync5(`tar -xJf "${tempFile}" -C "${destPath}"`, { stdio: "pipe" });
489
499
  } else if (archiveType === "tar.gz" || archiveType === "tgz") {
490
- execSync4(`tar -xzf "${tempFile}" -C "${destPath}"`, { stdio: "pipe" });
500
+ execSync5(`tar -xzf "${tempFile}" -C "${destPath}"`, { stdio: "pipe" });
491
501
  } else {
492
502
  throw new Error(`Unsupported archive type: ${archiveType}`);
493
503
  }
@@ -534,11 +544,11 @@ async function downloadTool(toolName, destPath, options = {}) {
534
544
  onProgress?.({ phase: "extracting", tool: toolName });
535
545
  const archiveType = extractConfig.type || guessArchiveType(urlFilename);
536
546
  if (archiveType === "zip") {
537
- execSync4(`unzip -o "${tempFile}" -d "${destPath}"`, { stdio: "pipe" });
547
+ execSync5(`unzip -o "${tempFile}" -d "${destPath}"`, { stdio: "pipe" });
538
548
  } else if (archiveType === "tar.xz") {
539
- execSync4(`tar -xJf "${tempFile}" -C "${destPath}"`, { stdio: "pipe" });
549
+ execSync5(`tar -xJf "${tempFile}" -C "${destPath}"`, { stdio: "pipe" });
540
550
  } else if (archiveType === "tar.gz" || archiveType === "tgz") {
541
- execSync4(`tar -xzf "${tempFile}" -C "${destPath}"`, { stdio: "pipe" });
551
+ execSync5(`tar -xzf "${tempFile}" -C "${destPath}"`, { stdio: "pipe" });
542
552
  } else {
543
553
  throw new Error(`Unsupported archive type: ${archiveType}`);
544
554
  }
@@ -608,7 +618,7 @@ async function extractBinaryFromPath(extractedPath, binaryPattern, destPath) {
608
618
  }
609
619
  }
610
620
  async function loadToolManifest(toolName) {
611
- for (const basePath of LOCAL_REGISTRY_PATHS) {
621
+ for (const basePath of getLocalRegistryPaths()) {
612
622
  const registryDir = import_path2.default.dirname(basePath);
613
623
  const manifestPath = import_path2.default.join(registryDir, "catalog", "binaries", `${toolName}.json`);
614
624
  if (import_fs2.default.existsSync(manifestPath)) {
@@ -676,7 +686,7 @@ async function copyDirectory(src, dest) {
676
686
  }
677
687
  }
678
688
  }
679
- var import_fs2, import_path2, import_crypto, DEFAULT_REGISTRY_URL, RUNTIMES_DOWNLOAD_BASE, CACHE_TTL, LOCAL_REGISTRY_PATHS, PACKAGE_KINDS2, KIND_PLURALS, RUNTIMES_RELEASE_VERSION;
689
+ var import_fs2, import_path2, import_crypto, DEFAULT_REGISTRY_URL, RUNTIMES_DOWNLOAD_BASE, CACHE_TTL, PACKAGE_KINDS2, KIND_PLURALS, RUNTIMES_RELEASE_VERSION;
680
690
  var init_src2 = __esm({
681
691
  "../packages/registry-client/src/index.js"() {
682
692
  import_fs2 = __toESM(require("fs"), 1);
@@ -686,11 +696,6 @@ var init_src2 = __esm({
686
696
  DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/learn-rudi/registry/main/index.json";
687
697
  RUNTIMES_DOWNLOAD_BASE = "https://github.com/learn-rudi/registry/releases/download";
688
698
  CACHE_TTL = 24 * 60 * 60 * 1e3;
689
- LOCAL_REGISTRY_PATHS = process.env.USE_LOCAL_REGISTRY === "true" ? [
690
- import_path2.default.join(process.cwd(), "registry", "index.json"),
691
- import_path2.default.join(process.cwd(), "..", "registry", "index.json"),
692
- "/Users/hoff/dev/RUDI/registry/index.json"
693
- ] : [];
694
699
  PACKAGE_KINDS2 = ["stack", "prompt", "runtime", "binary", "agent"];
695
700
  KIND_PLURALS = {
696
701
  binary: "binaries"
@@ -776,17 +781,17 @@ var require_visit = __commonJS({
776
781
  visit.BREAK = BREAK;
777
782
  visit.SKIP = SKIP;
778
783
  visit.REMOVE = REMOVE;
779
- function visit_(key, node, visitor, path16) {
780
- const ctrl = callVisitor(key, node, visitor, path16);
784
+ function visit_(key, node, visitor, path17) {
785
+ const ctrl = callVisitor(key, node, visitor, path17);
781
786
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
782
- replaceNode(key, path16, ctrl);
783
- return visit_(key, ctrl, visitor, path16);
787
+ replaceNode(key, path17, ctrl);
788
+ return visit_(key, ctrl, visitor, path17);
784
789
  }
785
790
  if (typeof ctrl !== "symbol") {
786
791
  if (identity.isCollection(node)) {
787
- path16 = Object.freeze(path16.concat(node));
792
+ path17 = Object.freeze(path17.concat(node));
788
793
  for (let i = 0; i < node.items.length; ++i) {
789
- const ci = visit_(i, node.items[i], visitor, path16);
794
+ const ci = visit_(i, node.items[i], visitor, path17);
790
795
  if (typeof ci === "number")
791
796
  i = ci - 1;
792
797
  else if (ci === BREAK)
@@ -797,13 +802,13 @@ var require_visit = __commonJS({
797
802
  }
798
803
  }
799
804
  } else if (identity.isPair(node)) {
800
- path16 = Object.freeze(path16.concat(node));
801
- const ck = visit_("key", node.key, visitor, path16);
805
+ path17 = Object.freeze(path17.concat(node));
806
+ const ck = visit_("key", node.key, visitor, path17);
802
807
  if (ck === BREAK)
803
808
  return BREAK;
804
809
  else if (ck === REMOVE)
805
810
  node.key = null;
806
- const cv = visit_("value", node.value, visitor, path16);
811
+ const cv = visit_("value", node.value, visitor, path17);
807
812
  if (cv === BREAK)
808
813
  return BREAK;
809
814
  else if (cv === REMOVE)
@@ -824,17 +829,17 @@ var require_visit = __commonJS({
824
829
  visitAsync.BREAK = BREAK;
825
830
  visitAsync.SKIP = SKIP;
826
831
  visitAsync.REMOVE = REMOVE;
827
- async function visitAsync_(key, node, visitor, path16) {
828
- const ctrl = await callVisitor(key, node, visitor, path16);
832
+ async function visitAsync_(key, node, visitor, path17) {
833
+ const ctrl = await callVisitor(key, node, visitor, path17);
829
834
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
830
- replaceNode(key, path16, ctrl);
831
- return visitAsync_(key, ctrl, visitor, path16);
835
+ replaceNode(key, path17, ctrl);
836
+ return visitAsync_(key, ctrl, visitor, path17);
832
837
  }
833
838
  if (typeof ctrl !== "symbol") {
834
839
  if (identity.isCollection(node)) {
835
- path16 = Object.freeze(path16.concat(node));
840
+ path17 = Object.freeze(path17.concat(node));
836
841
  for (let i = 0; i < node.items.length; ++i) {
837
- const ci = await visitAsync_(i, node.items[i], visitor, path16);
842
+ const ci = await visitAsync_(i, node.items[i], visitor, path17);
838
843
  if (typeof ci === "number")
839
844
  i = ci - 1;
840
845
  else if (ci === BREAK)
@@ -845,13 +850,13 @@ var require_visit = __commonJS({
845
850
  }
846
851
  }
847
852
  } else if (identity.isPair(node)) {
848
- path16 = Object.freeze(path16.concat(node));
849
- const ck = await visitAsync_("key", node.key, visitor, path16);
853
+ path17 = Object.freeze(path17.concat(node));
854
+ const ck = await visitAsync_("key", node.key, visitor, path17);
850
855
  if (ck === BREAK)
851
856
  return BREAK;
852
857
  else if (ck === REMOVE)
853
858
  node.key = null;
854
- const cv = await visitAsync_("value", node.value, visitor, path16);
859
+ const cv = await visitAsync_("value", node.value, visitor, path17);
855
860
  if (cv === BREAK)
856
861
  return BREAK;
857
862
  else if (cv === REMOVE)
@@ -878,23 +883,23 @@ var require_visit = __commonJS({
878
883
  }
879
884
  return visitor;
880
885
  }
881
- function callVisitor(key, node, visitor, path16) {
886
+ function callVisitor(key, node, visitor, path17) {
882
887
  if (typeof visitor === "function")
883
- return visitor(key, node, path16);
888
+ return visitor(key, node, path17);
884
889
  if (identity.isMap(node))
885
- return visitor.Map?.(key, node, path16);
890
+ return visitor.Map?.(key, node, path17);
886
891
  if (identity.isSeq(node))
887
- return visitor.Seq?.(key, node, path16);
892
+ return visitor.Seq?.(key, node, path17);
888
893
  if (identity.isPair(node))
889
- return visitor.Pair?.(key, node, path16);
894
+ return visitor.Pair?.(key, node, path17);
890
895
  if (identity.isScalar(node))
891
- return visitor.Scalar?.(key, node, path16);
896
+ return visitor.Scalar?.(key, node, path17);
892
897
  if (identity.isAlias(node))
893
- return visitor.Alias?.(key, node, path16);
898
+ return visitor.Alias?.(key, node, path17);
894
899
  return void 0;
895
900
  }
896
- function replaceNode(key, path16, node) {
897
- const parent = path16[path16.length - 1];
901
+ function replaceNode(key, path17, node) {
902
+ const parent = path17[path17.length - 1];
898
903
  if (identity.isCollection(parent)) {
899
904
  parent.items[key] = node;
900
905
  } else if (identity.isPair(parent)) {
@@ -1502,10 +1507,10 @@ var require_Collection = __commonJS({
1502
1507
  var createNode = require_createNode();
1503
1508
  var identity = require_identity();
1504
1509
  var Node = require_Node();
1505
- function collectionFromPath(schema, path16, value) {
1510
+ function collectionFromPath(schema, path17, value) {
1506
1511
  let v = value;
1507
- for (let i = path16.length - 1; i >= 0; --i) {
1508
- const k = path16[i];
1512
+ for (let i = path17.length - 1; i >= 0; --i) {
1513
+ const k = path17[i];
1509
1514
  if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
1510
1515
  const a = [];
1511
1516
  a[k] = v;
@@ -1524,7 +1529,7 @@ var require_Collection = __commonJS({
1524
1529
  sourceObjects: /* @__PURE__ */ new Map()
1525
1530
  });
1526
1531
  }
1527
- var isEmptyPath = (path16) => path16 == null || typeof path16 === "object" && !!path16[Symbol.iterator]().next().done;
1532
+ var isEmptyPath = (path17) => path17 == null || typeof path17 === "object" && !!path17[Symbol.iterator]().next().done;
1528
1533
  var Collection = class extends Node.NodeBase {
1529
1534
  constructor(type, schema) {
1530
1535
  super(type);
@@ -1554,11 +1559,11 @@ var require_Collection = __commonJS({
1554
1559
  * be a Pair instance or a `{ key, value }` object, which may not have a key
1555
1560
  * that already exists in the map.
1556
1561
  */
1557
- addIn(path16, value) {
1558
- if (isEmptyPath(path16))
1562
+ addIn(path17, value) {
1563
+ if (isEmptyPath(path17))
1559
1564
  this.add(value);
1560
1565
  else {
1561
- const [key, ...rest] = path16;
1566
+ const [key, ...rest] = path17;
1562
1567
  const node = this.get(key, true);
1563
1568
  if (identity.isCollection(node))
1564
1569
  node.addIn(rest, value);
@@ -1572,8 +1577,8 @@ var require_Collection = __commonJS({
1572
1577
  * Removes a value from the collection.
1573
1578
  * @returns `true` if the item was found and removed.
1574
1579
  */
1575
- deleteIn(path16) {
1576
- const [key, ...rest] = path16;
1580
+ deleteIn(path17) {
1581
+ const [key, ...rest] = path17;
1577
1582
  if (rest.length === 0)
1578
1583
  return this.delete(key);
1579
1584
  const node = this.get(key, true);
@@ -1587,8 +1592,8 @@ var require_Collection = __commonJS({
1587
1592
  * scalar values from their surrounding node; to disable set `keepScalar` to
1588
1593
  * `true` (collections are always returned intact).
1589
1594
  */
1590
- getIn(path16, keepScalar) {
1591
- const [key, ...rest] = path16;
1595
+ getIn(path17, keepScalar) {
1596
+ const [key, ...rest] = path17;
1592
1597
  const node = this.get(key, true);
1593
1598
  if (rest.length === 0)
1594
1599
  return !keepScalar && identity.isScalar(node) ? node.value : node;
@@ -1606,8 +1611,8 @@ var require_Collection = __commonJS({
1606
1611
  /**
1607
1612
  * Checks if the collection includes a value with the key `key`.
1608
1613
  */
1609
- hasIn(path16) {
1610
- const [key, ...rest] = path16;
1614
+ hasIn(path17) {
1615
+ const [key, ...rest] = path17;
1611
1616
  if (rest.length === 0)
1612
1617
  return this.has(key);
1613
1618
  const node = this.get(key, true);
@@ -1617,8 +1622,8 @@ var require_Collection = __commonJS({
1617
1622
  * Sets a value in this collection. For `!!set`, `value` needs to be a
1618
1623
  * boolean to add/remove the item from the set.
1619
1624
  */
1620
- setIn(path16, value) {
1621
- const [key, ...rest] = path16;
1625
+ setIn(path17, value) {
1626
+ const [key, ...rest] = path17;
1622
1627
  if (rest.length === 0) {
1623
1628
  this.set(key, value);
1624
1629
  } else {
@@ -4122,9 +4127,9 @@ var require_Document = __commonJS({
4122
4127
  this.contents.add(value);
4123
4128
  }
4124
4129
  /** Adds a value to the document. */
4125
- addIn(path16, value) {
4130
+ addIn(path17, value) {
4126
4131
  if (assertCollection(this.contents))
4127
- this.contents.addIn(path16, value);
4132
+ this.contents.addIn(path17, value);
4128
4133
  }
4129
4134
  /**
4130
4135
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
@@ -4199,14 +4204,14 @@ var require_Document = __commonJS({
4199
4204
  * Removes a value from the document.
4200
4205
  * @returns `true` if the item was found and removed.
4201
4206
  */
4202
- deleteIn(path16) {
4203
- if (Collection.isEmptyPath(path16)) {
4207
+ deleteIn(path17) {
4208
+ if (Collection.isEmptyPath(path17)) {
4204
4209
  if (this.contents == null)
4205
4210
  return false;
4206
4211
  this.contents = null;
4207
4212
  return true;
4208
4213
  }
4209
- return assertCollection(this.contents) ? this.contents.deleteIn(path16) : false;
4214
+ return assertCollection(this.contents) ? this.contents.deleteIn(path17) : false;
4210
4215
  }
4211
4216
  /**
4212
4217
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -4221,10 +4226,10 @@ var require_Document = __commonJS({
4221
4226
  * scalar values from their surrounding node; to disable set `keepScalar` to
4222
4227
  * `true` (collections are always returned intact).
4223
4228
  */
4224
- getIn(path16, keepScalar) {
4225
- if (Collection.isEmptyPath(path16))
4229
+ getIn(path17, keepScalar) {
4230
+ if (Collection.isEmptyPath(path17))
4226
4231
  return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
4227
- return identity.isCollection(this.contents) ? this.contents.getIn(path16, keepScalar) : void 0;
4232
+ return identity.isCollection(this.contents) ? this.contents.getIn(path17, keepScalar) : void 0;
4228
4233
  }
4229
4234
  /**
4230
4235
  * Checks if the document includes a value with the key `key`.
@@ -4235,10 +4240,10 @@ var require_Document = __commonJS({
4235
4240
  /**
4236
4241
  * Checks if the document includes a value at `path`.
4237
4242
  */
4238
- hasIn(path16) {
4239
- if (Collection.isEmptyPath(path16))
4243
+ hasIn(path17) {
4244
+ if (Collection.isEmptyPath(path17))
4240
4245
  return this.contents !== void 0;
4241
- return identity.isCollection(this.contents) ? this.contents.hasIn(path16) : false;
4246
+ return identity.isCollection(this.contents) ? this.contents.hasIn(path17) : false;
4242
4247
  }
4243
4248
  /**
4244
4249
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -4255,13 +4260,13 @@ var require_Document = __commonJS({
4255
4260
  * Sets a value in this document. For `!!set`, `value` needs to be a
4256
4261
  * boolean to add/remove the item from the set.
4257
4262
  */
4258
- setIn(path16, value) {
4259
- if (Collection.isEmptyPath(path16)) {
4263
+ setIn(path17, value) {
4264
+ if (Collection.isEmptyPath(path17)) {
4260
4265
  this.contents = value;
4261
4266
  } else if (this.contents == null) {
4262
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path16), value);
4267
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path17), value);
4263
4268
  } else if (assertCollection(this.contents)) {
4264
- this.contents.setIn(path16, value);
4269
+ this.contents.setIn(path17, value);
4265
4270
  }
4266
4271
  }
4267
4272
  /**
@@ -6213,9 +6218,9 @@ var require_cst_visit = __commonJS({
6213
6218
  visit.BREAK = BREAK;
6214
6219
  visit.SKIP = SKIP;
6215
6220
  visit.REMOVE = REMOVE;
6216
- visit.itemAtPath = (cst, path16) => {
6221
+ visit.itemAtPath = (cst, path17) => {
6217
6222
  let item = cst;
6218
- for (const [field, index] of path16) {
6223
+ for (const [field, index] of path17) {
6219
6224
  const tok = item?.[field];
6220
6225
  if (tok && "items" in tok) {
6221
6226
  item = tok.items[index];
@@ -6224,23 +6229,23 @@ var require_cst_visit = __commonJS({
6224
6229
  }
6225
6230
  return item;
6226
6231
  };
6227
- visit.parentCollection = (cst, path16) => {
6228
- const parent = visit.itemAtPath(cst, path16.slice(0, -1));
6229
- const field = path16[path16.length - 1][0];
6232
+ visit.parentCollection = (cst, path17) => {
6233
+ const parent = visit.itemAtPath(cst, path17.slice(0, -1));
6234
+ const field = path17[path17.length - 1][0];
6230
6235
  const coll = parent?.[field];
6231
6236
  if (coll && "items" in coll)
6232
6237
  return coll;
6233
6238
  throw new Error("Parent collection not found");
6234
6239
  };
6235
- function _visit(path16, item, visitor) {
6236
- let ctrl = visitor(item, path16);
6240
+ function _visit(path17, item, visitor) {
6241
+ let ctrl = visitor(item, path17);
6237
6242
  if (typeof ctrl === "symbol")
6238
6243
  return ctrl;
6239
6244
  for (const field of ["key", "value"]) {
6240
6245
  const token = item[field];
6241
6246
  if (token && "items" in token) {
6242
6247
  for (let i = 0; i < token.items.length; ++i) {
6243
- const ci = _visit(Object.freeze(path16.concat([[field, i]])), token.items[i], visitor);
6248
+ const ci = _visit(Object.freeze(path17.concat([[field, i]])), token.items[i], visitor);
6244
6249
  if (typeof ci === "number")
6245
6250
  i = ci - 1;
6246
6251
  else if (ci === BREAK)
@@ -6251,10 +6256,10 @@ var require_cst_visit = __commonJS({
6251
6256
  }
6252
6257
  }
6253
6258
  if (typeof ctrl === "function" && field === "key")
6254
- ctrl = ctrl(item, path16);
6259
+ ctrl = ctrl(item, path17);
6255
6260
  }
6256
6261
  }
6257
- return typeof ctrl === "function" ? ctrl(item, path16) : ctrl;
6262
+ return typeof ctrl === "function" ? ctrl(item, path17) : ctrl;
6258
6263
  }
6259
6264
  exports2.visit = visit;
6260
6265
  }
@@ -7539,14 +7544,14 @@ var require_parser = __commonJS({
7539
7544
  case "scalar":
7540
7545
  case "single-quoted-scalar":
7541
7546
  case "double-quoted-scalar": {
7542
- const fs18 = this.flowScalar(this.type);
7547
+ const fs19 = this.flowScalar(this.type);
7543
7548
  if (atNextItem || it.value) {
7544
- map.items.push({ start, key: fs18, sep: [] });
7549
+ map.items.push({ start, key: fs19, sep: [] });
7545
7550
  this.onKeyLine = true;
7546
7551
  } else if (it.sep) {
7547
- this.stack.push(fs18);
7552
+ this.stack.push(fs19);
7548
7553
  } else {
7549
- Object.assign(it, { key: fs18, sep: [] });
7554
+ Object.assign(it, { key: fs19, sep: [] });
7550
7555
  this.onKeyLine = true;
7551
7556
  }
7552
7557
  return;
@@ -7674,13 +7679,13 @@ var require_parser = __commonJS({
7674
7679
  case "scalar":
7675
7680
  case "single-quoted-scalar":
7676
7681
  case "double-quoted-scalar": {
7677
- const fs18 = this.flowScalar(this.type);
7682
+ const fs19 = this.flowScalar(this.type);
7678
7683
  if (!it || it.value)
7679
- fc.items.push({ start: [], key: fs18, sep: [] });
7684
+ fc.items.push({ start: [], key: fs19, sep: [] });
7680
7685
  else if (it.sep)
7681
- this.stack.push(fs18);
7686
+ this.stack.push(fs19);
7682
7687
  else
7683
- Object.assign(it, { key: fs18, sep: [] });
7688
+ Object.assign(it, { key: fs19, sep: [] });
7684
7689
  return;
7685
7690
  }
7686
7691
  case "flow-map-end":
@@ -11181,8 +11186,8 @@ var require_utils = __commonJS({
11181
11186
  }
11182
11187
  return ind;
11183
11188
  }
11184
- function removeDotSegments(path16) {
11185
- let input = path16;
11189
+ function removeDotSegments(path17) {
11190
+ let input = path17;
11186
11191
  const output = [];
11187
11192
  let nextSlash = -1;
11188
11193
  let len = 0;
@@ -11381,8 +11386,8 @@ var require_schemes = __commonJS({
11381
11386
  wsComponent.secure = void 0;
11382
11387
  }
11383
11388
  if (wsComponent.resourceName) {
11384
- const [path16, query] = wsComponent.resourceName.split("?");
11385
- wsComponent.path = path16 && path16 !== "/" ? path16 : void 0;
11389
+ const [path17, query] = wsComponent.resourceName.split("?");
11390
+ wsComponent.path = path17 && path17 !== "/" ? path17 : void 0;
11386
11391
  wsComponent.query = query;
11387
11392
  wsComponent.resourceName = void 0;
11388
11393
  }
@@ -14735,12 +14740,12 @@ var require_dist2 = __commonJS({
14735
14740
  throw new Error(`Unknown format "${name}"`);
14736
14741
  return f;
14737
14742
  };
14738
- function addFormats2(ajv2, list, fs18, exportName) {
14743
+ function addFormats2(ajv2, list, fs19, exportName) {
14739
14744
  var _a;
14740
14745
  var _b;
14741
14746
  (_a = (_b = ajv2.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
14742
14747
  for (const f of list)
14743
- ajv2.addFormat(f, fs18[f]);
14748
+ ajv2.addFormat(f, fs19[f]);
14744
14749
  }
14745
14750
  module2.exports = exports2 = formatsPlugin;
14746
14751
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -15275,7 +15280,7 @@ async function installSinglePackage(pkg, options = {}) {
15275
15280
  onProgress?.({ phase: "downloading", package: pkg.id });
15276
15281
  if (pkg.npmPackage) {
15277
15282
  try {
15278
- const { execSync: execSync4 } = await import("child_process");
15283
+ const { execSync: execSync5 } = await import("child_process");
15279
15284
  if (!import_fs4.default.existsSync(installPath)) {
15280
15285
  import_fs4.default.mkdirSync(installPath, { recursive: true });
15281
15286
  }
@@ -15283,16 +15288,16 @@ async function installSinglePackage(pkg, options = {}) {
15283
15288
  const resourcesPath = process.env.RESOURCES_PATH;
15284
15289
  const npmCmd = resourcesPath ? import_path4.default.join(resourcesPath, "bundled-runtimes", "node", "bin", "npm") : "npm";
15285
15290
  if (!import_fs4.default.existsSync(import_path4.default.join(installPath, "package.json"))) {
15286
- execSync4(`"${npmCmd}" init -y`, { cwd: installPath, stdio: "pipe" });
15291
+ execSync5(`"${npmCmd}" init -y`, { cwd: installPath, stdio: "pipe" });
15287
15292
  }
15288
- execSync4(`"${npmCmd}" install ${pkg.npmPackage}`, { cwd: installPath, stdio: "pipe" });
15293
+ execSync5(`"${npmCmd}" install ${pkg.npmPackage}`, { cwd: installPath, stdio: "pipe" });
15289
15294
  if (pkg.postInstall) {
15290
15295
  onProgress?.({ phase: "postInstall", package: pkg.id, message: pkg.postInstall });
15291
15296
  const postInstallCmd = pkg.postInstall.replace(
15292
15297
  /^npx\s+(\S+)/,
15293
15298
  `"${import_path4.default.join(installPath, "node_modules", ".bin", "$1")}"`
15294
15299
  );
15295
- execSync4(postInstallCmd, { cwd: installPath, stdio: "pipe" });
15300
+ execSync5(postInstallCmd, { cwd: installPath, stdio: "pipe" });
15296
15301
  }
15297
15302
  import_fs4.default.writeFileSync(
15298
15303
  import_path4.default.join(installPath, "manifest.json"),
@@ -15314,15 +15319,15 @@ async function installSinglePackage(pkg, options = {}) {
15314
15319
  }
15315
15320
  if (pkg.pipPackage) {
15316
15321
  try {
15317
- const { execSync: execSync4 } = await import("child_process");
15322
+ const { execSync: execSync5 } = await import("child_process");
15318
15323
  if (!import_fs4.default.existsSync(installPath)) {
15319
15324
  import_fs4.default.mkdirSync(installPath, { recursive: true });
15320
15325
  }
15321
15326
  onProgress?.({ phase: "installing", package: pkg.id, message: `pip install ${pkg.pipPackage}` });
15322
15327
  const pythonPath = import_path4.default.join(PATHS.runtimes, "python", "bin", "python3");
15323
15328
  const pythonCmd = import_fs4.default.existsSync(pythonPath) ? pythonPath : "python3";
15324
- execSync4(`"${pythonCmd}" -m venv "${installPath}/venv"`, { stdio: "pipe" });
15325
- execSync4(`"${installPath}/venv/bin/pip" install ${pkg.pipPackage}`, { stdio: "pipe" });
15329
+ execSync5(`"${pythonCmd}" -m venv "${installPath}/venv"`, { stdio: "pipe" });
15330
+ execSync5(`"${installPath}/venv/bin/pip" install ${pkg.pipPackage}`, { stdio: "pipe" });
15326
15331
  import_fs4.default.writeFileSync(
15327
15332
  import_path4.default.join(installPath, "manifest.json"),
15328
15333
  JSON.stringify({
@@ -15544,7 +15549,7 @@ async function listInstalled(kind) {
15544
15549
  return packages;
15545
15550
  }
15546
15551
  async function installStackDependencies(stackPath, onProgress) {
15547
- const { execSync: execSync4 } = await import("child_process");
15552
+ const { execSync: execSync5 } = await import("child_process");
15548
15553
  const nodePath = import_path4.default.join(stackPath, "node");
15549
15554
  if (import_fs4.default.existsSync(nodePath)) {
15550
15555
  const packageJsonPath = import_path4.default.join(nodePath, "package.json");
@@ -15552,7 +15557,7 @@ async function installStackDependencies(stackPath, onProgress) {
15552
15557
  onProgress?.({ phase: "installing-deps", message: "Installing Node.js dependencies..." });
15553
15558
  try {
15554
15559
  const npmCmd = await findNpmExecutable();
15555
- execSync4(`"${npmCmd}" install`, { cwd: nodePath, stdio: "pipe" });
15560
+ execSync5(`"${npmCmd}" install`, { cwd: nodePath, stdio: "pipe" });
15556
15561
  } catch (error) {
15557
15562
  console.warn(`Warning: Failed to install Node.js dependencies: ${error.message}`);
15558
15563
  }
@@ -15565,8 +15570,8 @@ async function installStackDependencies(stackPath, onProgress) {
15565
15570
  onProgress?.({ phase: "installing-deps", message: "Installing Python dependencies..." });
15566
15571
  try {
15567
15572
  const pythonCmd = await findPythonExecutable();
15568
- execSync4(`"${pythonCmd}" -m venv venv`, { cwd: pythonPath, stdio: "pipe" });
15569
- execSync4("./venv/bin/pip install -r requirements.txt", { cwd: pythonPath, stdio: "pipe" });
15573
+ execSync5(`"${pythonCmd}" -m venv venv`, { cwd: pythonPath, stdio: "pipe" });
15574
+ execSync5("./venv/bin/pip install -r requirements.txt", { cwd: pythonPath, stdio: "pipe" });
15570
15575
  } catch (error) {
15571
15576
  console.warn(`Warning: Failed to install Python dependencies: ${error.message}`);
15572
15577
  }
@@ -15606,6 +15611,213 @@ async function findPythonExecutable() {
15606
15611
  return "python3";
15607
15612
  }
15608
15613
 
15614
+ // ../packages/core/src/deps.js
15615
+ var import_fs5 = __toESM(require("fs"), 1);
15616
+ var import_path5 = __toESM(require("path"), 1);
15617
+ var import_child_process = require("child_process");
15618
+ init_src();
15619
+ init_src2();
15620
+ function checkRuntime(runtime) {
15621
+ const name = runtime.replace(/^runtime:/, "");
15622
+ const rudiPath = import_path5.default.join(PATHS.runtimes, name);
15623
+ if (import_fs5.default.existsSync(rudiPath)) {
15624
+ const binPath = getBinPath(rudiPath, name);
15625
+ if (binPath && import_fs5.default.existsSync(binPath)) {
15626
+ const version = getVersion(binPath, name);
15627
+ return { available: true, path: binPath, version, source: "rudi" };
15628
+ }
15629
+ }
15630
+ const systemCmd = getSystemCommand(name);
15631
+ const systemPath = which(systemCmd);
15632
+ if (systemPath) {
15633
+ const version = getVersion(systemPath, name);
15634
+ return { available: true, path: systemPath, version, source: "system" };
15635
+ }
15636
+ return { available: false, path: null, version: null, source: null };
15637
+ }
15638
+ function checkBinary(binary) {
15639
+ const name = binary.replace(/^binary:/, "");
15640
+ const rudiPath = import_path5.default.join(PATHS.binaries, name);
15641
+ if (import_fs5.default.existsSync(rudiPath)) {
15642
+ const binPath = getBinPath(rudiPath, name);
15643
+ if (binPath && import_fs5.default.existsSync(binPath)) {
15644
+ const version = getVersion(binPath, name);
15645
+ return { available: true, path: binPath, version, source: "rudi" };
15646
+ }
15647
+ }
15648
+ const systemPath = which(name);
15649
+ if (systemPath) {
15650
+ const version = getVersion(systemPath, name);
15651
+ return { available: true, path: systemPath, version, source: "system" };
15652
+ }
15653
+ return { available: false, path: null, version: null, source: null };
15654
+ }
15655
+ function checkAllDependencies(resolved) {
15656
+ const results = [];
15657
+ let satisfied = true;
15658
+ if (resolved.runtime) {
15659
+ const runtime = resolved.runtime.replace(/^runtime:/, "");
15660
+ const check = checkRuntime(runtime);
15661
+ results.push({
15662
+ type: "runtime",
15663
+ name: runtime,
15664
+ required: true,
15665
+ ...check
15666
+ });
15667
+ if (!check.available) satisfied = false;
15668
+ }
15669
+ for (const rt of resolved.requires?.runtimes || []) {
15670
+ const name = rt.replace(/^runtime:/, "");
15671
+ const check = checkRuntime(name);
15672
+ results.push({
15673
+ type: "runtime",
15674
+ name,
15675
+ required: true,
15676
+ ...check
15677
+ });
15678
+ if (!check.available) satisfied = false;
15679
+ }
15680
+ for (const bin of resolved.requires?.binaries || []) {
15681
+ const name = bin.replace(/^binary:/, "");
15682
+ const check = checkBinary(name);
15683
+ results.push({
15684
+ type: "binary",
15685
+ name,
15686
+ required: true,
15687
+ ...check
15688
+ });
15689
+ if (!check.available) satisfied = false;
15690
+ }
15691
+ return { satisfied, results };
15692
+ }
15693
+ function formatDependencyResults(results) {
15694
+ const lines = [];
15695
+ for (const r of results) {
15696
+ const icon = r.available ? "\u2713" : "\u2717";
15697
+ const version = r.version ? ` v${r.version}` : "";
15698
+ const source = r.source ? ` (${r.source})` : "";
15699
+ const status = r.available ? `${icon} ${r.name}${version}${source}` : `${icon} ${r.name} - not found`;
15700
+ lines.push(` ${status}`);
15701
+ }
15702
+ return lines;
15703
+ }
15704
+ function getBinPath(baseDir, name) {
15705
+ const arch = process.arch === "arm64" ? "arm64" : "x64";
15706
+ const isWindows = process.platform === "win32";
15707
+ const ext = isWindows ? ".exe" : "";
15708
+ const exeMap = {
15709
+ node: "node",
15710
+ python: "python3",
15711
+ deno: "deno",
15712
+ bun: "bun",
15713
+ ffmpeg: "ffmpeg",
15714
+ ripgrep: "rg",
15715
+ sqlite: "sqlite3",
15716
+ jq: "jq",
15717
+ yq: "yq"
15718
+ };
15719
+ const exe = exeMap[name] || name;
15720
+ const archPath = import_path5.default.join(baseDir, arch, "bin", exe + ext);
15721
+ if (import_fs5.default.existsSync(archPath)) return archPath;
15722
+ const flatPath = import_path5.default.join(baseDir, "bin", exe + ext);
15723
+ if (import_fs5.default.existsSync(flatPath)) return flatPath;
15724
+ const directPath = import_path5.default.join(baseDir, exe + ext);
15725
+ if (import_fs5.default.existsSync(directPath)) return directPath;
15726
+ return null;
15727
+ }
15728
+ function getSystemCommand(name) {
15729
+ const cmdMap = {
15730
+ python: "python3",
15731
+ node: "node",
15732
+ deno: "deno",
15733
+ bun: "bun"
15734
+ };
15735
+ return cmdMap[name] || name;
15736
+ }
15737
+ function which(cmd) {
15738
+ try {
15739
+ const result = (0, import_child_process.execSync)(`which ${cmd} 2>/dev/null`, { encoding: "utf-8" });
15740
+ return result.trim();
15741
+ } catch {
15742
+ return null;
15743
+ }
15744
+ }
15745
+ function getVersion(binPath, name) {
15746
+ const versionFlags = {
15747
+ node: "--version",
15748
+ python: "--version",
15749
+ python3: "--version",
15750
+ deno: "--version",
15751
+ bun: "--version",
15752
+ ffmpeg: "-version",
15753
+ rg: "--version",
15754
+ ripgrep: "--version",
15755
+ sqlite3: "--version",
15756
+ jq: "--version",
15757
+ yq: "--version"
15758
+ };
15759
+ const flag = versionFlags[name] || "--version";
15760
+ try {
15761
+ const output = (0, import_child_process.execSync)(`"${binPath}" ${flag} 2>&1`, { encoding: "utf-8" });
15762
+ const match = output.match(/(\d+\.\d+(?:\.\d+)?)/);
15763
+ return match ? match[1] : output.split("\n")[0].trim();
15764
+ } catch {
15765
+ return null;
15766
+ }
15767
+ }
15768
+ function getAvailableDeps() {
15769
+ const installedRuntimes = scanDirectory(PATHS.runtimes);
15770
+ const installedBinaries = scanDirectory(PATHS.binaries);
15771
+ const commonRuntimes = ["node", "python", "deno", "bun"];
15772
+ const commonBinaries = ["ffmpeg", "ripgrep", "sqlite3", "jq", "yq", "git", "docker", "rg"];
15773
+ const runtimeNames = [.../* @__PURE__ */ new Set([...installedRuntimes, ...commonRuntimes])];
15774
+ const binaryNames = [.../* @__PURE__ */ new Set([...installedBinaries, ...commonBinaries])];
15775
+ const runtimes = runtimeNames.map((name) => ({
15776
+ name,
15777
+ ...checkRuntime(name)
15778
+ }));
15779
+ const binaries = binaryNames.filter((name) => name !== "rg").map((name) => ({
15780
+ name,
15781
+ ...checkBinary(name)
15782
+ }));
15783
+ return { runtimes, binaries };
15784
+ }
15785
+ function scanDirectory(dir) {
15786
+ if (!import_fs5.default.existsSync(dir)) return [];
15787
+ try {
15788
+ return import_fs5.default.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
15789
+ } catch {
15790
+ return [];
15791
+ }
15792
+ }
15793
+ async function getAllDepsFromRegistry() {
15794
+ const index = await fetchIndex();
15795
+ const runtimes = (index.packages?.runtimes?.official || []).map((rt) => {
15796
+ const name = rt.id.replace(/^runtime:/, "");
15797
+ const check = checkRuntime(name);
15798
+ return {
15799
+ name,
15800
+ registryVersion: rt.version,
15801
+ description: rt.description,
15802
+ ...check,
15803
+ status: check.available ? check.source === "rudi" ? "installed" : "system" : "available"
15804
+ };
15805
+ });
15806
+ const binaries = (index.packages?.binaries?.official || []).map((bin) => {
15807
+ const name = bin.id.replace(/^binary:/, "");
15808
+ const check = checkBinary(name);
15809
+ return {
15810
+ name,
15811
+ registryVersion: bin.version,
15812
+ description: bin.description,
15813
+ managed: bin.managed !== false,
15814
+ ...check,
15815
+ status: check.available ? check.source === "rudi" ? "installed" : "system" : "available"
15816
+ };
15817
+ });
15818
+ return { runtimes, binaries };
15819
+ }
15820
+
15609
15821
  // src/commands/search.js
15610
15822
  function pluralizeKind(kind) {
15611
15823
  if (!kind) return "packages";
@@ -15711,31 +15923,31 @@ Total: ${totalCount} package(s) available`);
15711
15923
  }
15712
15924
 
15713
15925
  // src/commands/install.js
15714
- var fs6 = __toESM(require("fs/promises"), 1);
15715
- var path6 = __toESM(require("path"), 1);
15926
+ var fs7 = __toESM(require("fs/promises"), 1);
15927
+ var path7 = __toESM(require("path"), 1);
15716
15928
 
15717
15929
  // src/utils/mcp-registry.js
15718
- var fs5 = __toESM(require("fs/promises"), 1);
15719
- var path5 = __toESM(require("path"), 1);
15930
+ var fs6 = __toESM(require("fs/promises"), 1);
15931
+ var path6 = __toESM(require("path"), 1);
15720
15932
  var os2 = __toESM(require("os"), 1);
15721
15933
  var HOME = os2.homedir();
15722
15934
  var AGENT_CONFIGS = {
15723
- claude: path5.join(HOME, ".claude", "settings.json"),
15724
- codex: path5.join(HOME, ".codex", "config.toml"),
15725
- gemini: path5.join(HOME, ".gemini", "settings.json")
15935
+ claude: path6.join(HOME, ".claude", "settings.json"),
15936
+ codex: path6.join(HOME, ".codex", "config.toml"),
15937
+ gemini: path6.join(HOME, ".gemini", "settings.json")
15726
15938
  };
15727
15939
  async function readJson(filePath) {
15728
15940
  try {
15729
- const content = await fs5.readFile(filePath, "utf-8");
15941
+ const content = await fs6.readFile(filePath, "utf-8");
15730
15942
  return JSON.parse(content);
15731
15943
  } catch {
15732
15944
  return {};
15733
15945
  }
15734
15946
  }
15735
15947
  async function writeJson(filePath, data) {
15736
- const dir = path5.dirname(filePath);
15737
- await fs5.mkdir(dir, { recursive: true });
15738
- await fs5.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
15948
+ const dir = path6.dirname(filePath);
15949
+ await fs6.mkdir(dir, { recursive: true });
15950
+ await fs6.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
15739
15951
  }
15740
15952
  function parseTomlValue(value) {
15741
15953
  if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
@@ -15843,16 +16055,16 @@ function stringifyToml(config, prefix = "") {
15843
16055
  }
15844
16056
  async function readToml(filePath) {
15845
16057
  try {
15846
- const content = await fs5.readFile(filePath, "utf-8");
16058
+ const content = await fs6.readFile(filePath, "utf-8");
15847
16059
  return parseToml(content);
15848
16060
  } catch {
15849
16061
  return {};
15850
16062
  }
15851
16063
  }
15852
16064
  async function writeToml(filePath, data) {
15853
- const dir = path5.dirname(filePath);
15854
- await fs5.mkdir(dir, { recursive: true });
15855
- await fs5.writeFile(filePath, stringifyToml(data), "utf-8");
16065
+ const dir = path6.dirname(filePath);
16066
+ await fs6.mkdir(dir, { recursive: true });
16067
+ await fs6.writeFile(filePath, stringifyToml(data), "utf-8");
15856
16068
  }
15857
16069
  function parseEnvFile(content) {
15858
16070
  const env = {};
@@ -15874,9 +16086,9 @@ function parseEnvFile(content) {
15874
16086
  return env;
15875
16087
  }
15876
16088
  async function readStackEnv(installPath) {
15877
- const envPath = path5.join(installPath, ".env");
16089
+ const envPath = path6.join(installPath, ".env");
15878
16090
  try {
15879
- const content = await fs5.readFile(envPath, "utf-8");
16091
+ const content = await fs6.readFile(envPath, "utf-8");
15880
16092
  return parseEnvFile(content);
15881
16093
  } catch {
15882
16094
  return {};
@@ -15887,9 +16099,9 @@ async function buildMcpConfig(stackId, installPath, manifest) {
15887
16099
  let args = [];
15888
16100
  const cwd = installPath;
15889
16101
  const resolveRelativePath2 = (value) => {
15890
- if (!value || path5.isAbsolute(value)) return value;
16102
+ if (!value || path6.isAbsolute(value)) return value;
15891
16103
  const isPathLike = value.startsWith(".") || value.includes("/") || value.includes("\\");
15892
- return isPathLike ? path5.join(installPath, value) : value;
16104
+ return isPathLike ? path6.join(installPath, value) : value;
15893
16105
  };
15894
16106
  if (manifest.command) {
15895
16107
  const cmdArray = Array.isArray(manifest.command) ? manifest.command : [manifest.command];
@@ -15900,7 +16112,7 @@ async function buildMcpConfig(stackId, installPath, manifest) {
15900
16112
  args = (manifest.mcp.args || []).map((arg) => resolveRelativePath2(arg));
15901
16113
  if (manifest.mcp.entry) {
15902
16114
  args = args.map(
15903
- (arg) => arg === manifest.mcp.entry ? path5.join(installPath, manifest.mcp.entry) : arg
16115
+ (arg) => arg === manifest.mcp.entry ? path6.join(installPath, manifest.mcp.entry) : arg
15904
16116
  );
15905
16117
  }
15906
16118
  } else {
@@ -15934,9 +16146,9 @@ async function optimizeEntryPoint(installPath, command, args) {
15934
16146
  }
15935
16147
  const tsFile = args[tsFileIndex];
15936
16148
  const jsFile = tsFile.replace("/src/", "/dist/").replace(".ts", ".js");
15937
- const jsPath = path5.isAbsolute(jsFile) ? jsFile : path5.join(installPath, jsFile);
16149
+ const jsPath = path6.isAbsolute(jsFile) ? jsFile : path6.join(installPath, jsFile);
15938
16150
  try {
15939
- await fs5.access(jsPath);
16151
+ await fs6.access(jsPath);
15940
16152
  return {
15941
16153
  command: "node",
15942
16154
  args: [jsPath]
@@ -16055,12 +16267,12 @@ async function unregisterMcpGemini(stackId) {
16055
16267
  }
16056
16268
  }
16057
16269
  async function getInstalledAgents() {
16058
- const agentsDir = path5.join(HOME, ".rudi", "agents");
16270
+ const agentsDir = path6.join(HOME, ".rudi", "agents");
16059
16271
  const installed = [];
16060
16272
  for (const agent of ["claude", "codex", "gemini"]) {
16061
- const agentPath = path5.join(agentsDir, agent);
16273
+ const agentPath = path6.join(agentsDir, agent);
16062
16274
  try {
16063
- await fs5.access(agentPath);
16275
+ await fs6.access(agentPath);
16064
16276
  installed.push(agent);
16065
16277
  } catch {
16066
16278
  }
@@ -16106,9 +16318,9 @@ async function unregisterMcpAll(stackId, targetAgents = null) {
16106
16318
 
16107
16319
  // src/commands/install.js
16108
16320
  async function loadManifest(installPath) {
16109
- const manifestPath = path6.join(installPath, "manifest.json");
16321
+ const manifestPath = path7.join(installPath, "manifest.json");
16110
16322
  try {
16111
- const content = await fs6.readFile(manifestPath, "utf-8");
16323
+ const content = await fs7.readFile(manifestPath, "utf-8");
16112
16324
  return JSON.parse(content);
16113
16325
  } catch {
16114
16326
  return null;
@@ -16136,9 +16348,9 @@ function getSecretLabel(secret) {
16136
16348
  async function createEnvFile(installPath, manifest) {
16137
16349
  const secrets = getManifestSecrets(manifest);
16138
16350
  if (!secrets.length) return null;
16139
- const envPath = path6.join(installPath, ".env");
16351
+ const envPath = path7.join(installPath, ".env");
16140
16352
  try {
16141
- await fs6.access(envPath);
16353
+ await fs7.access(envPath);
16142
16354
  console.log(` .env file already exists, preserving existing secrets`);
16143
16355
  return envPath;
16144
16356
  } catch {
@@ -16160,7 +16372,7 @@ async function createEnvFile(installPath, manifest) {
16160
16372
  lines.push(`${key}=`);
16161
16373
  lines.push("");
16162
16374
  }
16163
- await fs6.writeFile(envPath, lines.join("\n"), "utf-8");
16375
+ await fs7.writeFile(envPath, lines.join("\n"), "utf-8");
16164
16376
  return envPath;
16165
16377
  }
16166
16378
  async function cmdInstall(args, flags) {
@@ -16212,6 +16424,19 @@ Required secrets:`);
16212
16424
  console.log(` - ${name}`);
16213
16425
  }
16214
16426
  }
16427
+ const depCheck = checkAllDependencies(resolved);
16428
+ if (depCheck.results.length > 0) {
16429
+ console.log(`
16430
+ System dependencies:`);
16431
+ for (const line of formatDependencyResults(depCheck.results)) {
16432
+ console.log(line);
16433
+ }
16434
+ if (!depCheck.satisfied && !force) {
16435
+ console.error(`
16436
+ \u2717 Missing required dependencies. Install them first or use --force to skip.`);
16437
+ process.exit(1);
16438
+ }
16439
+ }
16215
16440
  console.log(`
16216
16441
  Installing...`);
16217
16442
  const result = await installPackage(pkgId, {
@@ -16274,32 +16499,32 @@ Run with: rudi run ${pkgId}`);
16274
16499
  }
16275
16500
 
16276
16501
  // ../packages/runner/src/spawn.js
16277
- var import_child_process = require("child_process");
16278
- var import_path6 = __toESM(require("path"), 1);
16279
- var import_fs6 = __toESM(require("fs"), 1);
16502
+ var import_child_process2 = require("child_process");
16503
+ var import_path7 = __toESM(require("path"), 1);
16504
+ var import_fs7 = __toESM(require("fs"), 1);
16280
16505
 
16281
16506
  // ../packages/runner/src/secrets.js
16282
- var import_fs5 = __toESM(require("fs"), 1);
16283
- var import_path5 = __toESM(require("path"), 1);
16507
+ var import_fs6 = __toESM(require("fs"), 1);
16508
+ var import_path6 = __toESM(require("path"), 1);
16284
16509
  var import_os2 = __toESM(require("os"), 1);
16285
- var SECRETS_PATH = import_path5.default.join(import_os2.default.homedir(), ".rudi", "secrets.json");
16510
+ var SECRETS_PATH = import_path6.default.join(import_os2.default.homedir(), ".rudi", "secrets.json");
16286
16511
  function loadSecrets() {
16287
- if (!import_fs5.default.existsSync(SECRETS_PATH)) {
16512
+ if (!import_fs6.default.existsSync(SECRETS_PATH)) {
16288
16513
  return {};
16289
16514
  }
16290
16515
  try {
16291
- const content = import_fs5.default.readFileSync(SECRETS_PATH, "utf-8");
16516
+ const content = import_fs6.default.readFileSync(SECRETS_PATH, "utf-8");
16292
16517
  return JSON.parse(content);
16293
16518
  } catch {
16294
16519
  return {};
16295
16520
  }
16296
16521
  }
16297
16522
  function saveSecrets(secrets) {
16298
- const dir = import_path5.default.dirname(SECRETS_PATH);
16299
- if (!import_fs5.default.existsSync(dir)) {
16300
- import_fs5.default.mkdirSync(dir, { recursive: true });
16523
+ const dir = import_path6.default.dirname(SECRETS_PATH);
16524
+ if (!import_fs6.default.existsSync(dir)) {
16525
+ import_fs6.default.mkdirSync(dir, { recursive: true });
16301
16526
  }
16302
- import_fs5.default.writeFileSync(SECRETS_PATH, JSON.stringify(secrets, null, 2), {
16527
+ import_fs6.default.writeFileSync(SECRETS_PATH, JSON.stringify(secrets, null, 2), {
16303
16528
  mode: 384
16304
16529
  // Read/write only for owner
16305
16530
  });
@@ -16385,12 +16610,12 @@ async function runStack(id, options = {}) {
16385
16610
  const { inputs = {}, cwd, env = {}, onStdout, onStderr, onExit, signal } = options;
16386
16611
  const startTime = Date.now();
16387
16612
  const packagePath = getPackagePath(id);
16388
- const manifestPath = import_path6.default.join(packagePath, "manifest.json");
16389
- const { default: fs18 } = await import("fs");
16390
- if (!fs18.existsSync(manifestPath)) {
16613
+ const manifestPath = import_path7.default.join(packagePath, "manifest.json");
16614
+ const { default: fs19 } = await import("fs");
16615
+ if (!fs19.existsSync(manifestPath)) {
16391
16616
  throw new Error(`Stack manifest not found: ${id}`);
16392
16617
  }
16393
- const manifest = JSON.parse(fs18.readFileSync(manifestPath, "utf-8"));
16618
+ const manifest = JSON.parse(fs19.readFileSync(manifestPath, "utf-8"));
16394
16619
  const { command, args } = resolveCommandFromManifest(manifest, packagePath);
16395
16620
  const secrets = await getSecrets(manifest.requires?.secrets || []);
16396
16621
  const runEnv = {
@@ -16401,7 +16626,7 @@ async function runStack(id, options = {}) {
16401
16626
  RUDI_PACKAGE_ID: id,
16402
16627
  RUDI_PACKAGE_PATH: packagePath
16403
16628
  };
16404
- const proc = (0, import_child_process.spawn)(command, args, {
16629
+ const proc = (0, import_child_process2.spawn)(command, args, {
16405
16630
  cwd: cwd || packagePath,
16406
16631
  env: runEnv,
16407
16632
  stdio: ["pipe", "pipe", "pipe"],
@@ -16446,15 +16671,15 @@ async function runStack(id, options = {}) {
16446
16671
  }
16447
16672
  function getCommand(runtime) {
16448
16673
  const runtimeName = runtime.replace("runtime:", "");
16449
- const runtimePath = import_path6.default.join(PATHS.runtimes, runtimeName);
16674
+ const runtimePath = import_path7.default.join(PATHS.runtimes, runtimeName);
16450
16675
  const binaryPaths = [
16451
- import_path6.default.join(runtimePath, "bin", runtimeName === "python" ? "python3" : runtimeName),
16452
- import_path6.default.join(runtimePath, "bin", runtimeName),
16453
- import_path6.default.join(runtimePath, runtimeName === "python" ? "python3" : runtimeName),
16454
- import_path6.default.join(runtimePath, runtimeName)
16676
+ import_path7.default.join(runtimePath, "bin", runtimeName === "python" ? "python3" : runtimeName),
16677
+ import_path7.default.join(runtimePath, "bin", runtimeName),
16678
+ import_path7.default.join(runtimePath, runtimeName === "python" ? "python3" : runtimeName),
16679
+ import_path7.default.join(runtimePath, runtimeName)
16455
16680
  ];
16456
16681
  for (const binPath of binaryPaths) {
16457
- if (import_fs6.default.existsSync(binPath)) {
16682
+ if (import_fs7.default.existsSync(binPath)) {
16458
16683
  return binPath;
16459
16684
  }
16460
16685
  }
@@ -16478,7 +16703,7 @@ function resolveCommandFromManifest(manifest, packagePath) {
16478
16703
  return { command: command2, args };
16479
16704
  }
16480
16705
  const entry = manifest.entry || "index.js";
16481
- const entryPath = import_path6.default.join(packagePath, entry);
16706
+ const entryPath = import_path7.default.join(packagePath, entry);
16482
16707
  const runtime = manifest.runtime || "runtime:node";
16483
16708
  const command = getCommand(runtime);
16484
16709
  return { command, args: [entryPath] };
@@ -16487,21 +16712,21 @@ function resolveRelativePath(value, basePath) {
16487
16712
  if (typeof value !== "string" || value.startsWith("-")) {
16488
16713
  return value;
16489
16714
  }
16490
- if (import_path6.default.isAbsolute(value)) {
16715
+ if (import_path7.default.isAbsolute(value)) {
16491
16716
  return value;
16492
16717
  }
16493
16718
  if (value.includes("/") || value.startsWith(".")) {
16494
- return import_path6.default.join(basePath, value);
16719
+ return import_path7.default.join(basePath, value);
16495
16720
  }
16496
16721
  return value;
16497
16722
  }
16498
16723
 
16499
16724
  // ../packages/manifest/src/stack.js
16500
16725
  var import_yaml2 = __toESM(require_dist(), 1);
16501
- var import_fs7 = __toESM(require("fs"), 1);
16502
- var import_path7 = __toESM(require("path"), 1);
16726
+ var import_fs8 = __toESM(require("fs"), 1);
16727
+ var import_path8 = __toESM(require("path"), 1);
16503
16728
  function parseStackManifest(filePath) {
16504
- const content = import_fs7.default.readFileSync(filePath, "utf-8");
16729
+ const content = import_fs8.default.readFileSync(filePath, "utf-8");
16505
16730
  return parseStackYaml(content, filePath);
16506
16731
  }
16507
16732
  function parseStackYaml(content, source = "stack.yaml") {
@@ -16619,8 +16844,8 @@ function validateStackManifest(manifest, source) {
16619
16844
  function findStackManifest(dir) {
16620
16845
  const candidates = ["stack.yaml", "stack.yml", "manifest.yaml", "manifest.yml"];
16621
16846
  for (const filename of candidates) {
16622
- const filePath = import_path7.default.join(dir, filename);
16623
- if (import_fs7.default.existsSync(filePath)) {
16847
+ const filePath = import_path8.default.join(dir, filename);
16848
+ if (import_fs8.default.existsSync(filePath)) {
16624
16849
  return filePath;
16625
16850
  }
16626
16851
  }
@@ -16775,8 +17000,8 @@ var validatePromptInternal = ajv.compile(promptSchema);
16775
17000
  var validateRuntimeInternal = ajv.compile(runtimeSchema);
16776
17001
 
16777
17002
  // src/commands/run.js
16778
- var import_fs8 = __toESM(require("fs"), 1);
16779
- var import_path8 = __toESM(require("path"), 1);
17003
+ var import_fs9 = __toESM(require("fs"), 1);
17004
+ var import_path9 = __toESM(require("path"), 1);
16780
17005
  async function cmdRun(args, flags) {
16781
17006
  const stackId = args[0];
16782
17007
  if (!stackId) {
@@ -16797,9 +17022,9 @@ async function cmdRun(args, flags) {
16797
17022
  if (manifestPath) {
16798
17023
  manifest = parseStackManifest(manifestPath);
16799
17024
  } else {
16800
- const jsonPath = import_path8.default.join(packagePath, "manifest.json");
16801
- if (import_fs8.default.existsSync(jsonPath)) {
16802
- manifest = JSON.parse(import_fs8.default.readFileSync(jsonPath, "utf-8"));
17025
+ const jsonPath = import_path9.default.join(packagePath, "manifest.json");
17026
+ if (import_fs9.default.existsSync(jsonPath)) {
17027
+ manifest = JSON.parse(import_fs9.default.readFileSync(jsonPath, "utf-8"));
16803
17028
  }
16804
17029
  }
16805
17030
  } catch (error) {
@@ -17255,13 +17480,13 @@ function promptSecret(prompt) {
17255
17480
  }
17256
17481
 
17257
17482
  // src/commands/db.js
17258
- var import_fs10 = require("fs");
17259
- var import_path10 = require("path");
17483
+ var import_fs11 = require("fs");
17484
+ var import_path11 = require("path");
17260
17485
 
17261
17486
  // ../packages/db/src/index.js
17262
17487
  var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
17263
- var import_path9 = __toESM(require("path"), 1);
17264
- var import_fs9 = __toESM(require("fs"), 1);
17488
+ var import_path10 = __toESM(require("path"), 1);
17489
+ var import_fs10 = __toESM(require("fs"), 1);
17265
17490
  init_src();
17266
17491
 
17267
17492
  // ../packages/db/src/schema.js
@@ -17301,7 +17526,7 @@ CREATE TABLE IF NOT EXISTS sessions (
17301
17526
  project_id TEXT,
17302
17527
 
17303
17528
  -- Origin tracking
17304
- origin TEXT NOT NULL CHECK (origin IN ('promptstack', 'provider-import', 'mixed')),
17529
+ origin TEXT NOT NULL CHECK (origin IN ('rudi', 'provider-import', 'mixed')),
17305
17530
  origin_imported_at TEXT,
17306
17531
  origin_native_file TEXT,
17307
17532
 
@@ -17998,9 +18223,9 @@ var DB_PATH = PATHS.dbFile;
17998
18223
  var db = null;
17999
18224
  function getDb(options = {}) {
18000
18225
  if (!db) {
18001
- const dbDir = import_path9.default.dirname(DB_PATH);
18002
- if (!import_fs9.default.existsSync(dbDir)) {
18003
- import_fs9.default.mkdirSync(dbDir, { recursive: true });
18226
+ const dbDir = import_path10.default.dirname(DB_PATH);
18227
+ if (!import_fs10.default.existsSync(dbDir)) {
18228
+ import_fs10.default.mkdirSync(dbDir, { recursive: true });
18004
18229
  }
18005
18230
  db = new import_better_sqlite3.default(DB_PATH, {
18006
18231
  readonly: options.readonly || false
@@ -18013,7 +18238,7 @@ function getDb(options = {}) {
18013
18238
  return db;
18014
18239
  }
18015
18240
  function isDatabaseInitialized() {
18016
- if (!import_fs9.default.existsSync(DB_PATH)) {
18241
+ if (!import_fs10.default.existsSync(DB_PATH)) {
18017
18242
  return false;
18018
18243
  }
18019
18244
  try {
@@ -18033,7 +18258,7 @@ function getDbPath() {
18033
18258
  }
18034
18259
  function getDbSize() {
18035
18260
  try {
18036
- const stats = import_fs9.default.statSync(DB_PATH);
18261
+ const stats = import_fs10.default.statSync(DB_PATH);
18037
18262
  return stats.size;
18038
18263
  } catch {
18039
18264
  return null;
@@ -18294,12 +18519,12 @@ function dbBackup(args, flags) {
18294
18519
  let backupPath = args[0];
18295
18520
  if (!backupPath) {
18296
18521
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
18297
- backupPath = (0, import_path10.join)((0, import_path10.dirname)(dbPath), `rudi-backup-${timestamp}.db`);
18522
+ backupPath = (0, import_path11.join)((0, import_path11.dirname)(dbPath), `rudi-backup-${timestamp}.db`);
18298
18523
  }
18299
18524
  if (backupPath.startsWith("~")) {
18300
- backupPath = (0, import_path10.join)(process.env.HOME || "", backupPath.slice(1));
18525
+ backupPath = (0, import_path11.join)(process.env.HOME || "", backupPath.slice(1));
18301
18526
  }
18302
- if ((0, import_fs10.existsSync)(backupPath) && !flags.force) {
18527
+ if ((0, import_fs11.existsSync)(backupPath) && !flags.force) {
18303
18528
  console.error(`Backup file already exists: ${backupPath}`);
18304
18529
  console.error("Use --force to overwrite.");
18305
18530
  process.exit(1);
@@ -18311,7 +18536,7 @@ function dbBackup(args, flags) {
18311
18536
  const db3 = getDb();
18312
18537
  db3.exec("VACUUM INTO ?", [backupPath]);
18313
18538
  } catch (e) {
18314
- (0, import_fs10.copyFileSync)(dbPath, backupPath);
18539
+ (0, import_fs11.copyFileSync)(dbPath, backupPath);
18315
18540
  }
18316
18541
  const size = getDbSize();
18317
18542
  console.log(` Size: ${formatBytes(size)}`);
@@ -18416,24 +18641,24 @@ function dbTables(flags) {
18416
18641
  }
18417
18642
 
18418
18643
  // src/commands/import.js
18419
- var import_fs11 = require("fs");
18420
- var import_path11 = require("path");
18644
+ var import_fs12 = require("fs");
18645
+ var import_path12 = require("path");
18421
18646
  var import_os3 = require("os");
18422
18647
  var import_crypto2 = require("crypto");
18423
18648
  var PROVIDERS = {
18424
18649
  claude: {
18425
18650
  name: "Claude Code",
18426
- baseDir: (0, import_path11.join)((0, import_os3.homedir)(), ".claude", "projects"),
18651
+ baseDir: (0, import_path12.join)((0, import_os3.homedir)(), ".claude", "projects"),
18427
18652
  pattern: /\.jsonl$/
18428
18653
  },
18429
18654
  codex: {
18430
18655
  name: "Codex",
18431
- baseDir: (0, import_path11.join)((0, import_os3.homedir)(), ".codex", "sessions"),
18656
+ baseDir: (0, import_path12.join)((0, import_os3.homedir)(), ".codex", "sessions"),
18432
18657
  pattern: /\.jsonl$/
18433
18658
  },
18434
18659
  gemini: {
18435
18660
  name: "Gemini",
18436
- baseDir: (0, import_path11.join)((0, import_os3.homedir)(), ".gemini", "sessions"),
18661
+ baseDir: (0, import_path12.join)((0, import_os3.homedir)(), ".gemini", "sessions"),
18437
18662
  pattern: /\.jsonl$/
18438
18663
  }
18439
18664
  };
@@ -18500,7 +18725,7 @@ async function importSessions(args, flags) {
18500
18725
  console.log(`
18501
18726
  \u25B6 ${provider.name}`);
18502
18727
  console.log(` Source: ${provider.baseDir}`);
18503
- if (!(0, import_fs11.existsSync)(provider.baseDir)) {
18728
+ if (!(0, import_fs12.existsSync)(provider.baseDir)) {
18504
18729
  console.log(` \u26A0 Directory not found, skipping`);
18505
18730
  continue;
18506
18731
  }
@@ -18543,14 +18768,14 @@ async function importSessions(args, flags) {
18543
18768
  const now = Date.now();
18544
18769
  const maxAgeMs = maxAgeDays ? maxAgeDays * 24 * 60 * 60 * 1e3 : null;
18545
18770
  for (const filepath of files) {
18546
- const sessionId = (0, import_path11.basename)(filepath, ".jsonl");
18771
+ const sessionId = (0, import_path12.basename)(filepath, ".jsonl");
18547
18772
  if (existingIds.has(sessionId)) {
18548
18773
  skipped.existing++;
18549
18774
  continue;
18550
18775
  }
18551
18776
  let stat;
18552
18777
  try {
18553
- stat = (0, import_fs11.statSync)(filepath);
18778
+ stat = (0, import_fs12.statSync)(filepath);
18554
18779
  } catch (e) {
18555
18780
  skipped.error++;
18556
18781
  continue;
@@ -18648,7 +18873,7 @@ function showImportStatus(flags) {
18648
18873
  }
18649
18874
  console.log("\nProvider directories:");
18650
18875
  for (const [key, provider] of Object.entries(PROVIDERS)) {
18651
- const exists = (0, import_fs11.existsSync)(provider.baseDir);
18876
+ const exists = (0, import_fs12.existsSync)(provider.baseDir);
18652
18877
  let count = 0;
18653
18878
  if (exists) {
18654
18879
  const files = findSessionFiles(provider.baseDir, provider.pattern);
@@ -18662,10 +18887,10 @@ function showImportStatus(flags) {
18662
18887
  console.log("To import: rudi import sessions [provider]");
18663
18888
  }
18664
18889
  function findSessionFiles(dir, pattern, files = []) {
18665
- if (!(0, import_fs11.existsSync)(dir)) return files;
18890
+ if (!(0, import_fs12.existsSync)(dir)) return files;
18666
18891
  try {
18667
- for (const entry of (0, import_fs11.readdirSync)(dir, { withFileTypes: true })) {
18668
- const fullPath = (0, import_path11.join)(dir, entry.name);
18892
+ for (const entry of (0, import_fs12.readdirSync)(dir, { withFileTypes: true })) {
18893
+ const fullPath = (0, import_path12.join)(dir, entry.name);
18669
18894
  if (entry.isDirectory()) {
18670
18895
  findSessionFiles(fullPath, pattern, files);
18671
18896
  } else if (pattern.test(entry.name)) {
@@ -18678,11 +18903,11 @@ function findSessionFiles(dir, pattern, files = []) {
18678
18903
  }
18679
18904
  function parseSessionFile(filepath, provider) {
18680
18905
  try {
18681
- const stat = (0, import_fs11.statSync)(filepath);
18682
- const content = (0, import_fs11.readFileSync)(filepath, "utf-8");
18906
+ const stat = (0, import_fs12.statSync)(filepath);
18907
+ const content = (0, import_fs12.readFileSync)(filepath, "utf-8");
18683
18908
  const lines = content.split("\n").filter((l) => l.trim());
18684
18909
  if (lines.length === 0) return null;
18685
- const sessionId = (0, import_path11.basename)(filepath, ".jsonl");
18910
+ const sessionId = (0, import_path12.basename)(filepath, ".jsonl");
18686
18911
  const isAgent = sessionId.startsWith("agent-");
18687
18912
  let title = null;
18688
18913
  let cwd = null;
@@ -18714,7 +18939,7 @@ function parseSessionFile(filepath, provider) {
18714
18939
  title = isAgent ? "Agent Session" : "Imported Session";
18715
18940
  }
18716
18941
  if (!cwd) {
18717
- const parentDir = (0, import_path11.basename)((0, import_path11.dirname)(filepath));
18942
+ const parentDir = (0, import_path12.basename)((0, import_path12.dirname)(filepath));
18718
18943
  if (parentDir.startsWith("-")) {
18719
18944
  cwd = parentDir.replace(/-/g, "/").replace(/^\//, "/");
18720
18945
  } else {
@@ -18738,7 +18963,7 @@ function parseSessionFile(filepath, provider) {
18738
18963
  }
18739
18964
 
18740
18965
  // src/commands/doctor.js
18741
- var import_fs12 = __toESM(require("fs"), 1);
18966
+ var import_fs13 = __toESM(require("fs"), 1);
18742
18967
  async function cmdDoctor(args, flags) {
18743
18968
  console.log("RUDI Health Check");
18744
18969
  console.log("\u2550".repeat(50));
@@ -18756,12 +18981,12 @@ async function cmdDoctor(args, flags) {
18756
18981
  { path: PATHS.cache, name: "Cache" }
18757
18982
  ];
18758
18983
  for (const dir of dirs) {
18759
- const exists = import_fs12.default.existsSync(dir.path);
18984
+ const exists = import_fs13.default.existsSync(dir.path);
18760
18985
  const status = exists ? "\u2713" : "\u2717";
18761
18986
  console.log(` ${status} ${dir.name}: ${dir.path}`);
18762
18987
  if (!exists) {
18763
18988
  issues.push(`Missing directory: ${dir.name}`);
18764
- fixes.push(() => import_fs12.default.mkdirSync(dir.path, { recursive: true }));
18989
+ fixes.push(() => import_fs13.default.mkdirSync(dir.path, { recursive: true }));
18765
18990
  }
18766
18991
  }
18767
18992
  console.log("\n\u{1F4BE} Database");
@@ -18798,10 +19023,40 @@ async function cmdDoctor(args, flags) {
18798
19023
  } catch (error) {
18799
19024
  console.log(` \u2717 Error reading secrets: ${error.message}`);
18800
19025
  }
18801
- console.log("\n\u2699\uFE0F Environment");
19026
+ console.log("\n\u2699\uFE0F Runtimes");
19027
+ try {
19028
+ const { runtimes, binaries } = flags.all ? await getAllDepsFromRegistry() : getAvailableDeps();
19029
+ for (const rt of runtimes) {
19030
+ const icon = rt.available ? "\u2713" : "\u25CB";
19031
+ const version = rt.version ? `v${rt.version}` : "";
19032
+ const source = rt.available ? `(${rt.source})` : flags.all ? "available" : "not found";
19033
+ console.log(` ${icon} ${rt.name}: ${version} ${source}`);
19034
+ }
19035
+ console.log("\n\u{1F527} Binaries");
19036
+ for (const bin of binaries) {
19037
+ const icon = bin.available ? "\u2713" : "\u25CB";
19038
+ const version = bin.version ? `v${bin.version}` : "";
19039
+ const managed = bin.managed === false ? " (external)" : "";
19040
+ const source = bin.available ? `(${bin.source})` : flags.all ? `available${managed}` : "not found";
19041
+ console.log(` ${icon} ${bin.name}: ${version} ${source}`);
19042
+ }
19043
+ if (flags.all) {
19044
+ const availableRuntimes = runtimes.filter((r) => !r.available).length;
19045
+ const availableBinaries = binaries.filter((b) => !b.available && b.managed !== false).length;
19046
+ if (availableRuntimes + availableBinaries > 0) {
19047
+ console.log(`
19048
+ Install with: rudi install runtime:<name> or rudi install binary:<name>`);
19049
+ }
19050
+ }
19051
+ } catch (error) {
19052
+ console.log(` \u2717 Error checking dependencies: ${error.message}`);
19053
+ }
19054
+ console.log("\n\u{1F4CD} Environment");
18802
19055
  const nodeVersion = process.version;
18803
19056
  const nodeOk = parseInt(nodeVersion.slice(1)) >= 18;
18804
19057
  console.log(` ${nodeOk ? "\u2713" : "\u2717"} Node.js: ${nodeVersion} ${nodeOk ? "" : "(requires >=18)"}`);
19058
+ console.log(` \u2713 Platform: ${process.platform}-${process.arch}`);
19059
+ console.log(` \u2713 RUDI Home: ${PATHS.home}`);
18805
19060
  if (!nodeOk) {
18806
19061
  issues.push("Node.js version too old (requires >=18)");
18807
19062
  }
@@ -18831,9 +19086,9 @@ async function cmdDoctor(args, flags) {
18831
19086
  }
18832
19087
 
18833
19088
  // src/commands/update.js
18834
- var import_fs13 = __toESM(require("fs"), 1);
18835
- var import_path12 = __toESM(require("path"), 1);
18836
- var import_child_process2 = require("child_process");
19089
+ var import_fs14 = __toESM(require("fs"), 1);
19090
+ var import_path13 = __toESM(require("path"), 1);
19091
+ var import_child_process3 = require("child_process");
18837
19092
  init_src();
18838
19093
  init_src2();
18839
19094
  async function cmdUpdate(args, flags) {
@@ -18858,7 +19113,7 @@ async function cmdUpdate(args, flags) {
18858
19113
  async function updatePackage(pkgId, flags) {
18859
19114
  const [kind, name] = parsePackageId(pkgId);
18860
19115
  const installPath = getPackagePath(pkgId);
18861
- if (!import_fs13.default.existsSync(installPath)) {
19116
+ if (!import_fs14.default.existsSync(installPath)) {
18862
19117
  return { success: false, error: "Package not installed" };
18863
19118
  }
18864
19119
  const pkg = await getPackage(pkgId);
@@ -18868,7 +19123,7 @@ async function updatePackage(pkgId, flags) {
18868
19123
  console.log(`Updating ${pkgId}...`);
18869
19124
  if (pkg.npmPackage) {
18870
19125
  try {
18871
- (0, import_child_process2.execSync)(`npm install ${pkg.npmPackage}@latest`, {
19126
+ (0, import_child_process3.execSync)(`npm install ${pkg.npmPackage}@latest`, {
18872
19127
  cwd: installPath,
18873
19128
  stdio: flags.verbose ? "inherit" : "pipe"
18874
19129
  });
@@ -18881,11 +19136,11 @@ async function updatePackage(pkgId, flags) {
18881
19136
  }
18882
19137
  if (pkg.pipPackage) {
18883
19138
  try {
18884
- const venvPip = import_path12.default.join(installPath, "venv", "bin", "pip");
18885
- (0, import_child_process2.execSync)(`"${venvPip}" install --upgrade ${pkg.pipPackage}`, {
19139
+ const venvPip = import_path13.default.join(installPath, "venv", "bin", "pip");
19140
+ (0, import_child_process3.execSync)(`"${venvPip}" install --upgrade ${pkg.pipPackage}`, {
18886
19141
  stdio: flags.verbose ? "inherit" : "pipe"
18887
19142
  });
18888
- const versionOutput = (0, import_child_process2.execSync)(`"${venvPip}" show ${pkg.pipPackage} | grep Version`, {
19143
+ const versionOutput = (0, import_child_process3.execSync)(`"${venvPip}" show ${pkg.pipPackage} | grep Version`, {
18889
19144
  encoding: "utf-8"
18890
19145
  });
18891
19146
  const version = versionOutput.split(":")[1]?.trim();
@@ -18898,7 +19153,7 @@ async function updatePackage(pkgId, flags) {
18898
19153
  if (kind === "runtime" && !pkg.npmPackage && !pkg.pipPackage) {
18899
19154
  try {
18900
19155
  const { downloadRuntime: downloadRuntime2 } = await Promise.resolve().then(() => (init_src2(), src_exports));
18901
- import_fs13.default.rmSync(installPath, { recursive: true, force: true });
19156
+ import_fs14.default.rmSync(installPath, { recursive: true, force: true });
18902
19157
  await downloadRuntime2(name, pkg.version || "latest", installPath, {
18903
19158
  onProgress: (p) => {
18904
19159
  if (flags.verbose) console.log(` ${p.phase}...`);
@@ -18918,8 +19173,8 @@ async function updateAll(flags) {
18918
19173
  let failed = 0;
18919
19174
  for (const kind of kinds) {
18920
19175
  const dir = kind === "runtime" ? PATHS.runtimes : kind === "stack" ? PATHS.stacks : PATHS.prompts;
18921
- if (!import_fs13.default.existsSync(dir)) continue;
18922
- const entries = import_fs13.default.readdirSync(dir, { withFileTypes: true });
19176
+ if (!import_fs14.default.existsSync(dir)) continue;
19177
+ const entries = import_fs14.default.readdirSync(dir, { withFileTypes: true });
18923
19178
  for (const entry of entries) {
18924
19179
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
18925
19180
  const pkgId = `${kind}:${entry.name}`;
@@ -18938,14 +19193,14 @@ Updated ${updated} package(s)${failed > 0 ? `, ${failed} failed` : ""}`);
18938
19193
  }
18939
19194
  function getInstalledVersion(installPath, npmPackage) {
18940
19195
  try {
18941
- const pkgJsonPath = import_path12.default.join(installPath, "node_modules", npmPackage.replace("@", "").split("/")[0], "package.json");
18942
- if (import_fs13.default.existsSync(pkgJsonPath)) {
18943
- const pkgJson = JSON.parse(import_fs13.default.readFileSync(pkgJsonPath, "utf-8"));
19196
+ const pkgJsonPath = import_path13.default.join(installPath, "node_modules", npmPackage.replace("@", "").split("/")[0], "package.json");
19197
+ if (import_fs14.default.existsSync(pkgJsonPath)) {
19198
+ const pkgJson = JSON.parse(import_fs14.default.readFileSync(pkgJsonPath, "utf-8"));
18944
19199
  return pkgJson.version;
18945
19200
  }
18946
- const rootPkgPath = import_path12.default.join(installPath, "package.json");
18947
- if (import_fs13.default.existsSync(rootPkgPath)) {
18948
- const rootPkg = JSON.parse(import_fs13.default.readFileSync(rootPkgPath, "utf-8"));
19201
+ const rootPkgPath = import_path13.default.join(installPath, "package.json");
19202
+ if (import_fs14.default.existsSync(rootPkgPath)) {
19203
+ const rootPkg = JSON.parse(import_fs14.default.readFileSync(rootPkgPath, "utf-8"));
18949
19204
  const dep = rootPkg.dependencies?.[npmPackage];
18950
19205
  if (dep) return dep.replace(/[\^~]/, "");
18951
19206
  }
@@ -18954,30 +19209,30 @@ function getInstalledVersion(installPath, npmPackage) {
18954
19209
  return null;
18955
19210
  }
18956
19211
  function updateRuntimeMetadata(installPath, updates) {
18957
- const metaPath = import_path12.default.join(installPath, "runtime.json");
19212
+ const metaPath = import_path13.default.join(installPath, "runtime.json");
18958
19213
  try {
18959
19214
  let meta = {};
18960
- if (import_fs13.default.existsSync(metaPath)) {
18961
- meta = JSON.parse(import_fs13.default.readFileSync(metaPath, "utf-8"));
19215
+ if (import_fs14.default.existsSync(metaPath)) {
19216
+ meta = JSON.parse(import_fs14.default.readFileSync(metaPath, "utf-8"));
18962
19217
  }
18963
19218
  meta = { ...meta, ...updates };
18964
- import_fs13.default.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
19219
+ import_fs14.default.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
18965
19220
  } catch {
18966
19221
  }
18967
19222
  }
18968
19223
 
18969
19224
  // db/index.js
18970
19225
  var import_better_sqlite32 = __toESM(require("better-sqlite3"), 1);
18971
- var import_path13 = __toESM(require("path"), 1);
19226
+ var import_path14 = __toESM(require("path"), 1);
18972
19227
  var import_os4 = __toESM(require("os"), 1);
18973
- var import_fs14 = __toESM(require("fs"), 1);
18974
- var PROMPT_STACK_HOME = import_path13.default.join(import_os4.default.homedir(), ".prompt-stack");
18975
- var DB_PATH2 = import_path13.default.join(PROMPT_STACK_HOME, "prompt-stack.db");
19228
+ var import_fs15 = __toESM(require("fs"), 1);
19229
+ var RUDI_HOME2 = import_path14.default.join(import_os4.default.homedir(), ".rudi");
19230
+ var DB_PATH2 = import_path14.default.join(RUDI_HOME2, "rudi.db");
18976
19231
  var db2 = null;
18977
19232
  function getDb2(options = {}) {
18978
19233
  if (!db2) {
18979
- if (!import_fs14.default.existsSync(PROMPT_STACK_HOME)) {
18980
- import_fs14.default.mkdirSync(PROMPT_STACK_HOME, { recursive: true });
19234
+ if (!import_fs15.default.existsSync(RUDI_HOME2)) {
19235
+ import_fs15.default.mkdirSync(RUDI_HOME2, { recursive: true });
18981
19236
  }
18982
19237
  db2 = new import_better_sqlite32.default(DB_PATH2, {
18983
19238
  readonly: options.readonly || false
@@ -19135,7 +19390,7 @@ function getBeforeCrashLogs() {
19135
19390
  }
19136
19391
 
19137
19392
  // src/commands/logs.js
19138
- var import_fs15 = __toESM(require("fs"), 1);
19393
+ var import_fs16 = __toESM(require("fs"), 1);
19139
19394
  function parseTimeAgo(str) {
19140
19395
  const match = str.match(/^(\d+)([smhd])$/);
19141
19396
  if (!match) return null;
@@ -19235,7 +19490,7 @@ function exportLogs(logs, filepath, format) {
19235
19490
  });
19236
19491
  content = JSON.stringify(formatted, null, 2);
19237
19492
  }
19238
- import_fs15.default.writeFileSync(filepath, content, "utf-8");
19493
+ import_fs16.default.writeFileSync(filepath, content, "utf-8");
19239
19494
  return filepath;
19240
19495
  }
19241
19496
  function printStats(stats) {
@@ -19361,9 +19616,9 @@ async function handleLogsCommand(args, flags) {
19361
19616
  }
19362
19617
 
19363
19618
  // src/commands/which.js
19364
- var fs16 = __toESM(require("fs/promises"), 1);
19365
- var path14 = __toESM(require("path"), 1);
19366
- var import_child_process3 = require("child_process");
19619
+ var fs17 = __toESM(require("fs/promises"), 1);
19620
+ var path15 = __toESM(require("path"), 1);
19621
+ var import_child_process4 = require("child_process");
19367
19622
  init_src();
19368
19623
  async function cmdWhich(args, flags) {
19369
19624
  const stackId = args[0];
@@ -19431,7 +19686,7 @@ Installed stacks:`);
19431
19686
  if (runtimeInfo.entry) {
19432
19687
  console.log("");
19433
19688
  console.log("Run MCP server directly:");
19434
- const entryPath = path14.join(stackPath, runtimeInfo.entry);
19689
+ const entryPath = path15.join(stackPath, runtimeInfo.entry);
19435
19690
  if (runtimeInfo.runtime === "node") {
19436
19691
  console.log(` echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node ${entryPath}`);
19437
19692
  } else if (runtimeInfo.runtime === "python") {
@@ -19450,27 +19705,27 @@ Installed stacks:`);
19450
19705
  async function detectRuntime(stackPath) {
19451
19706
  const runtimes = ["node", "python"];
19452
19707
  for (const runtime of runtimes) {
19453
- const runtimePath = path14.join(stackPath, runtime);
19708
+ const runtimePath = path15.join(stackPath, runtime);
19454
19709
  try {
19455
- await fs16.access(runtimePath);
19710
+ await fs17.access(runtimePath);
19456
19711
  if (runtime === "node") {
19457
- const distEntry = path14.join(runtimePath, "dist", "index.js");
19458
- const srcEntry = path14.join(runtimePath, "src", "index.ts");
19712
+ const distEntry = path15.join(runtimePath, "dist", "index.js");
19713
+ const srcEntry = path15.join(runtimePath, "src", "index.ts");
19459
19714
  try {
19460
- await fs16.access(distEntry);
19715
+ await fs17.access(distEntry);
19461
19716
  return { runtime: "node", entry: `${runtime}/dist/index.js` };
19462
19717
  } catch {
19463
19718
  try {
19464
- await fs16.access(srcEntry);
19719
+ await fs17.access(srcEntry);
19465
19720
  return { runtime: "node", entry: `${runtime}/src/index.ts` };
19466
19721
  } catch {
19467
19722
  return { runtime: "node", entry: null };
19468
19723
  }
19469
19724
  }
19470
19725
  } else if (runtime === "python") {
19471
- const entry = path14.join(runtimePath, "src", "index.py");
19726
+ const entry = path15.join(runtimePath, "src", "index.py");
19472
19727
  try {
19473
- await fs16.access(entry);
19728
+ await fs17.access(entry);
19474
19729
  return { runtime: "python", entry: `${runtime}/src/index.py` };
19475
19730
  } catch {
19476
19731
  return { runtime: "python", entry: null };
@@ -19486,21 +19741,21 @@ async function checkAuth(stackPath, runtime) {
19486
19741
  const authFiles = [];
19487
19742
  let configured = false;
19488
19743
  if (runtime === "node" || runtime === "python") {
19489
- const runtimePath = path14.join(stackPath, runtime);
19490
- const tokenPath = path14.join(runtimePath, "token.json");
19744
+ const runtimePath = path15.join(stackPath, runtime);
19745
+ const tokenPath = path15.join(runtimePath, "token.json");
19491
19746
  try {
19492
- await fs16.access(tokenPath);
19747
+ await fs17.access(tokenPath);
19493
19748
  authFiles.push(`${runtime}/token.json`);
19494
19749
  configured = true;
19495
19750
  } catch {
19496
- const accountsPath = path14.join(runtimePath, "accounts");
19751
+ const accountsPath = path15.join(runtimePath, "accounts");
19497
19752
  try {
19498
- const accounts = await fs16.readdir(accountsPath);
19753
+ const accounts = await fs17.readdir(accountsPath);
19499
19754
  for (const account of accounts) {
19500
19755
  if (account.startsWith(".")) continue;
19501
- const accountTokenPath = path14.join(accountsPath, account, "token.json");
19756
+ const accountTokenPath = path15.join(accountsPath, account, "token.json");
19502
19757
  try {
19503
- await fs16.access(accountTokenPath);
19758
+ await fs17.access(accountTokenPath);
19504
19759
  authFiles.push(`${runtime}/accounts/${account}/token.json`);
19505
19760
  configured = true;
19506
19761
  } catch {
@@ -19510,9 +19765,9 @@ async function checkAuth(stackPath, runtime) {
19510
19765
  }
19511
19766
  }
19512
19767
  }
19513
- const envPath = path14.join(stackPath, ".env");
19768
+ const envPath = path15.join(stackPath, ".env");
19514
19769
  try {
19515
- const envContent = await fs16.readFile(envPath, "utf-8");
19770
+ const envContent = await fs17.readFile(envPath, "utf-8");
19516
19771
  const hasValues = envContent.split("\n").some((line) => {
19517
19772
  const trimmed = line.trim();
19518
19773
  if (!trimmed || trimmed.startsWith("#")) return false;
@@ -19541,7 +19796,7 @@ async function checkAuth(stackPath, runtime) {
19541
19796
  }
19542
19797
  function checkIfRunning(stackName) {
19543
19798
  try {
19544
- const result = (0, import_child_process3.execSync)(`ps aux | grep "${stackName}" | grep -v grep || true`, {
19799
+ const result = (0, import_child_process4.execSync)(`ps aux | grep "${stackName}" | grep -v grep || true`, {
19545
19800
  encoding: "utf-8",
19546
19801
  stdio: ["pipe", "pipe", "ignore"]
19547
19802
  // Suppress stderr
@@ -19556,9 +19811,9 @@ function checkIfRunning(stackName) {
19556
19811
  }
19557
19812
 
19558
19813
  // src/commands/auth.js
19559
- var fs17 = __toESM(require("fs/promises"), 1);
19560
- var path15 = __toESM(require("path"), 1);
19561
- var import_child_process4 = require("child_process");
19814
+ var fs18 = __toESM(require("fs/promises"), 1);
19815
+ var path16 = __toESM(require("path"), 1);
19816
+ var import_child_process5 = require("child_process");
19562
19817
  init_src();
19563
19818
  var net = __toESM(require("net"), 1);
19564
19819
  async function findAvailablePort(basePort = 3456) {
@@ -19589,26 +19844,26 @@ function isPortAvailable(port) {
19589
19844
  async function detectRuntime2(stackPath) {
19590
19845
  const runtimes = ["node", "python"];
19591
19846
  for (const runtime of runtimes) {
19592
- const runtimePath = path15.join(stackPath, runtime);
19847
+ const runtimePath = path16.join(stackPath, runtime);
19593
19848
  try {
19594
- await fs17.access(runtimePath);
19849
+ await fs18.access(runtimePath);
19595
19850
  if (runtime === "node") {
19596
- const authTs = path15.join(runtimePath, "src", "auth.ts");
19597
- const authJs = path15.join(runtimePath, "dist", "auth.js");
19851
+ const authTs = path16.join(runtimePath, "src", "auth.ts");
19852
+ const authJs = path16.join(runtimePath, "dist", "auth.js");
19598
19853
  try {
19599
- await fs17.access(authTs);
19854
+ await fs18.access(authTs);
19600
19855
  return { runtime: "node", authScript: authTs, useTsx: true };
19601
19856
  } catch {
19602
19857
  try {
19603
- await fs17.access(authJs);
19858
+ await fs18.access(authJs);
19604
19859
  return { runtime: "node", authScript: authJs, useTsx: false };
19605
19860
  } catch {
19606
19861
  }
19607
19862
  }
19608
19863
  } else if (runtime === "python") {
19609
- const authPy = path15.join(runtimePath, "src", "auth.py");
19864
+ const authPy = path16.join(runtimePath, "src", "auth.py");
19610
19865
  try {
19611
- await fs17.access(authPy);
19866
+ await fs18.access(authPy);
19612
19867
  return { runtime: "python", authScript: authPy, useTsx: false };
19613
19868
  } catch {
19614
19869
  }
@@ -19658,14 +19913,14 @@ Installed stacks:`);
19658
19913
  console.log(`Using port: ${port}`);
19659
19914
  console.log("");
19660
19915
  let cmd;
19661
- const cwd = path15.dirname(authInfo.authScript);
19916
+ const cwd = path16.dirname(authInfo.authScript);
19662
19917
  if (authInfo.runtime === "node") {
19663
- const distAuth = path15.join(cwd, "..", "dist", "auth.js");
19918
+ const distAuth = path16.join(cwd, "..", "dist", "auth.js");
19664
19919
  let useBuiltInPort = false;
19665
19920
  let tempAuthScript = null;
19666
19921
  try {
19667
- await fs17.access(distAuth);
19668
- const distContent = await fs17.readFile(distAuth, "utf-8");
19922
+ await fs18.access(distAuth);
19923
+ const distContent = await fs18.readFile(distAuth, "utf-8");
19669
19924
  if (distContent.includes("findAvailablePort")) {
19670
19925
  console.log("Using compiled authentication script...");
19671
19926
  cmd = `node ${distAuth}${accountEmail ? ` ${accountEmail}` : ""}`;
@@ -19674,11 +19929,11 @@ Installed stacks:`);
19674
19929
  } catch {
19675
19930
  }
19676
19931
  if (!useBuiltInPort) {
19677
- const authContent = await fs17.readFile(authInfo.authScript, "utf-8");
19932
+ const authContent = await fs18.readFile(authInfo.authScript, "utf-8");
19678
19933
  const tempExt = authInfo.useTsx ? ".ts" : ".mjs";
19679
- tempAuthScript = path15.join(cwd, "..", `auth-temp${tempExt}`);
19934
+ tempAuthScript = path16.join(cwd, "..", `auth-temp${tempExt}`);
19680
19935
  const modifiedContent = authContent.replace(/localhost:3456/g, `localhost:${port}`).replace(/server\.listen\(3456/g, `server.listen(${port}`);
19681
- await fs17.writeFile(tempAuthScript, modifiedContent);
19936
+ await fs18.writeFile(tempAuthScript, modifiedContent);
19682
19937
  if (authInfo.useTsx) {
19683
19938
  cmd = `npx tsx ${tempAuthScript}${accountEmail ? ` ${accountEmail}` : ""}`;
19684
19939
  } else {
@@ -19688,17 +19943,17 @@ Installed stacks:`);
19688
19943
  console.log("Starting OAuth flow...");
19689
19944
  console.log("");
19690
19945
  try {
19691
- (0, import_child_process4.execSync)(cmd, {
19946
+ (0, import_child_process5.execSync)(cmd, {
19692
19947
  cwd,
19693
19948
  stdio: "inherit"
19694
19949
  });
19695
19950
  if (tempAuthScript) {
19696
- await fs17.unlink(tempAuthScript);
19951
+ await fs18.unlink(tempAuthScript);
19697
19952
  }
19698
19953
  } catch (error) {
19699
19954
  if (tempAuthScript) {
19700
19955
  try {
19701
- await fs17.unlink(tempAuthScript);
19956
+ await fs18.unlink(tempAuthScript);
19702
19957
  } catch {
19703
19958
  }
19704
19959
  }
@@ -19708,7 +19963,7 @@ Installed stacks:`);
19708
19963
  cmd = `python3 ${authInfo.authScript}${accountEmail ? ` ${accountEmail}` : ""}`;
19709
19964
  console.log("Starting OAuth flow...");
19710
19965
  console.log("");
19711
- (0, import_child_process4.execSync)(cmd, {
19966
+ (0, import_child_process5.execSync)(cmd, {
19712
19967
  cwd,
19713
19968
  stdio: "inherit",
19714
19969
  env: {