@learnrudi/cli 1.9.8 → 1.9.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -70,9 +70,9 @@ function ensureDirectories() {
70
70
  }
71
71
  }
72
72
  function parsePackageId(id) {
73
- const match = id.match(/^(stack|prompt|runtime|binary|agent):(.+)$/);
73
+ const match = id.match(/^(stack|prompt|runtime|binary|agent|npm):(.+)$/);
74
74
  if (!match) {
75
- throw new Error(`Invalid package ID: ${id} (expected format: kind:name, where kind is one of: ${PACKAGE_KINDS.join(", ")})`);
75
+ throw new Error(`Invalid package ID: ${id} (expected format: kind:name, where kind is one of: ${PACKAGE_KINDS.join(", ")}, npm)`);
76
76
  }
77
77
  return [match[1], match[2]];
78
78
  }
@@ -92,14 +92,21 @@ function getPackagePath(id) {
92
92
  return import_path.default.join(PATHS.binaries, name);
93
93
  case "agent":
94
94
  return import_path.default.join(PATHS.agents, name);
95
+ case "npm":
96
+ const sanitized = name.replace(/\//g, "__").replace(/^@/, "");
97
+ return import_path.default.join(PATHS.binaries, "npm", sanitized);
95
98
  default:
96
99
  throw new Error(`Unknown package kind: ${kind}`);
97
100
  }
98
101
  }
99
102
  function getLockfilePath(id) {
100
103
  const [kind, name] = parsePackageId(id);
101
- const lockDir = kind === "binary" ? "binaries" : kind + "s";
102
- return import_path.default.join(PATHS.locks, lockDir, `${name}.lock.yaml`);
104
+ let lockName = name;
105
+ if (kind === "npm") {
106
+ lockName = name.replace(/\//g, "__").replace(/^@/, "");
107
+ }
108
+ const lockDir = kind === "binary" ? "binaries" : kind === "npm" ? "npms" : kind + "s";
109
+ return import_path.default.join(PATHS.locks, lockDir, `${lockName}.lock.yaml`);
103
110
  }
104
111
  function isPackageInstalled(id) {
105
112
  const packagePath = getPackagePath(id);
@@ -190,27 +197,6 @@ var init_src = __esm({
190
197
  });
191
198
 
192
199
  // node_modules/.pnpm/@learnrudi+registry-client@1.0.1/node_modules/@learnrudi/registry-client/src/index.js
193
- var src_exports = {};
194
- __export(src_exports, {
195
- CACHE_TTL: () => CACHE_TTL,
196
- DEFAULT_REGISTRY_URL: () => DEFAULT_REGISTRY_URL,
197
- PACKAGE_KINDS: () => PACKAGE_KINDS2,
198
- RUNTIMES_DOWNLOAD_BASE: () => RUNTIMES_DOWNLOAD_BASE,
199
- RUNTIMES_RELEASE_VERSION: () => RUNTIMES_RELEASE_VERSION,
200
- checkCache: () => checkCache,
201
- clearCache: () => clearCache,
202
- computeHash: () => computeHash,
203
- downloadPackage: () => downloadPackage,
204
- downloadRuntime: () => downloadRuntime,
205
- downloadTool: () => downloadTool,
206
- fetchIndex: () => fetchIndex,
207
- getManifest: () => getManifest,
208
- getPackage: () => getPackage,
209
- getPackageKinds: () => getPackageKinds,
210
- listPackages: () => listPackages,
211
- searchPackages: () => searchPackages,
212
- verifyHash: () => verifyHash
213
- });
214
200
  function getLocalRegistryPaths() {
215
201
  if (process.env.USE_LOCAL_REGISTRY !== "true") {
216
202
  return [];
@@ -316,19 +302,6 @@ function clearCache() {
316
302
  import_fs2.default.unlinkSync(PATHS.registryCache);
317
303
  }
318
304
  }
319
- function checkCache() {
320
- const cachePath = PATHS.registryCache;
321
- if (!import_fs2.default.existsSync(cachePath)) {
322
- return { fresh: false, age: null };
323
- }
324
- try {
325
- const stat = import_fs2.default.statSync(cachePath);
326
- const age = Date.now() - stat.mtimeMs;
327
- return { fresh: age <= CACHE_TTL, age };
328
- } catch {
329
- return { fresh: false, age: null };
330
- }
331
- }
332
305
  function getKindSection(kind) {
333
306
  return KIND_PLURALS[kind] || `${kind}s`;
334
307
  }
@@ -420,9 +393,6 @@ async function listPackages(kind) {
420
393
  if (!section) return [];
421
394
  return [...section.official || [], ...section.community || []];
422
395
  }
423
- function getPackageKinds() {
424
- return PACKAGE_KINDS2;
425
- }
426
396
  async function downloadPackage(pkg, destPath, options = {}) {
427
397
  const { onProgress } = options;
428
398
  const registryPath = pkg.path;
@@ -833,33 +803,11 @@ function guessArchiveType(filename) {
833
803
  if (filename.endsWith(".zip")) return "zip";
834
804
  return "tar.gz";
835
805
  }
836
- async function verifyHash(filePath, expectedHash) {
837
- return new Promise((resolve, reject) => {
838
- const hash = import_crypto.default.createHash("sha256");
839
- const stream = import_fs2.default.createReadStream(filePath);
840
- stream.on("data", (data) => hash.update(data));
841
- stream.on("end", () => {
842
- const actualHash = hash.digest("hex");
843
- resolve(actualHash === expectedHash);
844
- });
845
- stream.on("error", reject);
846
- });
847
- }
848
- async function computeHash(filePath) {
849
- return new Promise((resolve, reject) => {
850
- const hash = import_crypto.default.createHash("sha256");
851
- const stream = import_fs2.default.createReadStream(filePath);
852
- stream.on("data", (data) => hash.update(data));
853
- stream.on("end", () => resolve(hash.digest("hex")));
854
- stream.on("error", reject);
855
- });
856
- }
857
- var import_fs2, import_path2, import_crypto, DEFAULT_REGISTRY_URL, RUNTIMES_DOWNLOAD_BASE, CACHE_TTL, PACKAGE_KINDS2, KIND_PLURALS, GITHUB_RAW_BASE, RUNTIMES_RELEASE_VERSION;
806
+ var import_fs2, import_path2, DEFAULT_REGISTRY_URL, RUNTIMES_DOWNLOAD_BASE, CACHE_TTL, PACKAGE_KINDS2, KIND_PLURALS, GITHUB_RAW_BASE, RUNTIMES_RELEASE_VERSION;
858
807
  var init_src2 = __esm({
859
808
  "node_modules/.pnpm/@learnrudi+registry-client@1.0.1/node_modules/@learnrudi/registry-client/src/index.js"() {
860
809
  import_fs2 = __toESM(require("fs"), 1);
861
810
  import_path2 = __toESM(require("path"), 1);
862
- import_crypto = __toESM(require("crypto"), 1);
863
811
  init_src();
864
812
  DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/learn-rudi/registry/main/index.json";
865
813
  RUNTIMES_DOWNLOAD_BASE = "https://github.com/learn-rudi/registry/releases/download";
@@ -873,8 +821,11 @@ var init_src2 = __esm({
873
821
  }
874
822
  });
875
823
 
876
- // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/resolver.js
824
+ // packages/core/src/resolver.js
877
825
  async function resolvePackage(id) {
826
+ if (id.startsWith("npm:")) {
827
+ return resolveDynamicNpm(id);
828
+ }
878
829
  const normalizedId = id.includes(":") ? id : `stack:${id}`;
879
830
  const pkg = await getPackage(normalizedId);
880
831
  if (!pkg) {
@@ -912,6 +863,51 @@ async function resolvePackage(id) {
912
863
  installType: mergedPkg.installType
913
864
  };
914
865
  }
866
+ async function resolveDynamicNpm(id) {
867
+ const spec = id.replace("npm:", "");
868
+ let name, version;
869
+ if (spec.startsWith("@")) {
870
+ const parts = spec.split("@");
871
+ if (parts.length >= 3) {
872
+ name = `@${parts[1]}`;
873
+ version = parts[2];
874
+ } else {
875
+ name = `@${parts[1]}`;
876
+ version = "latest";
877
+ }
878
+ } else {
879
+ const lastAt = spec.lastIndexOf("@");
880
+ if (lastAt > 0) {
881
+ name = spec.substring(0, lastAt);
882
+ version = spec.substring(lastAt + 1);
883
+ } else {
884
+ name = spec;
885
+ version = "latest";
886
+ }
887
+ }
888
+ const sanitizedName = name.replace(/\//g, "__").replace(/^@/, "");
889
+ const installDir = `npm/${sanitizedName}`;
890
+ const fullId = id;
891
+ const installed = isPackageInstalled(fullId);
892
+ return {
893
+ id: fullId,
894
+ kind: "binary",
895
+ name,
896
+ version,
897
+ description: `Dynamic npm package: ${name}`,
898
+ installType: "npm",
899
+ npmPackage: name,
900
+ installDir,
901
+ installed,
902
+ dependencies: [],
903
+ source: {
904
+ type: "npm",
905
+ spec
906
+ },
907
+ // bins will be discovered after install by installer
908
+ bins: null
909
+ };
910
+ }
915
911
  async function resolveDependencies(pkg) {
916
912
  const dependencies = [];
917
913
  const runtimes = pkg.requires?.runtimes || (pkg.runtime ? [pkg.runtime] : []);
@@ -1028,7 +1024,7 @@ function compareVersions(a, b) {
1028
1024
  return 0;
1029
1025
  }
1030
1026
  var init_resolver = __esm({
1031
- "node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/resolver.js"() {
1027
+ "packages/core/src/resolver.js"() {
1032
1028
  init_src2();
1033
1029
  init_src();
1034
1030
  }
@@ -1111,17 +1107,17 @@ var require_visit = __commonJS({
1111
1107
  visit.BREAK = BREAK;
1112
1108
  visit.SKIP = SKIP;
1113
1109
  visit.REMOVE = REMOVE;
1114
- function visit_(key, node, visitor, path30) {
1115
- const ctrl = callVisitor(key, node, visitor, path30);
1110
+ function visit_(key, node, visitor, path35) {
1111
+ const ctrl = callVisitor(key, node, visitor, path35);
1116
1112
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
1117
- replaceNode(key, path30, ctrl);
1118
- return visit_(key, ctrl, visitor, path30);
1113
+ replaceNode(key, path35, ctrl);
1114
+ return visit_(key, ctrl, visitor, path35);
1119
1115
  }
1120
1116
  if (typeof ctrl !== "symbol") {
1121
1117
  if (identity.isCollection(node)) {
1122
- path30 = Object.freeze(path30.concat(node));
1118
+ path35 = Object.freeze(path35.concat(node));
1123
1119
  for (let i = 0; i < node.items.length; ++i) {
1124
- const ci = visit_(i, node.items[i], visitor, path30);
1120
+ const ci = visit_(i, node.items[i], visitor, path35);
1125
1121
  if (typeof ci === "number")
1126
1122
  i = ci - 1;
1127
1123
  else if (ci === BREAK)
@@ -1132,13 +1128,13 @@ var require_visit = __commonJS({
1132
1128
  }
1133
1129
  }
1134
1130
  } else if (identity.isPair(node)) {
1135
- path30 = Object.freeze(path30.concat(node));
1136
- const ck = visit_("key", node.key, visitor, path30);
1131
+ path35 = Object.freeze(path35.concat(node));
1132
+ const ck = visit_("key", node.key, visitor, path35);
1137
1133
  if (ck === BREAK)
1138
1134
  return BREAK;
1139
1135
  else if (ck === REMOVE)
1140
1136
  node.key = null;
1141
- const cv = visit_("value", node.value, visitor, path30);
1137
+ const cv = visit_("value", node.value, visitor, path35);
1142
1138
  if (cv === BREAK)
1143
1139
  return BREAK;
1144
1140
  else if (cv === REMOVE)
@@ -1159,17 +1155,17 @@ var require_visit = __commonJS({
1159
1155
  visitAsync.BREAK = BREAK;
1160
1156
  visitAsync.SKIP = SKIP;
1161
1157
  visitAsync.REMOVE = REMOVE;
1162
- async function visitAsync_(key, node, visitor, path30) {
1163
- const ctrl = await callVisitor(key, node, visitor, path30);
1158
+ async function visitAsync_(key, node, visitor, path35) {
1159
+ const ctrl = await callVisitor(key, node, visitor, path35);
1164
1160
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
1165
- replaceNode(key, path30, ctrl);
1166
- return visitAsync_(key, ctrl, visitor, path30);
1161
+ replaceNode(key, path35, ctrl);
1162
+ return visitAsync_(key, ctrl, visitor, path35);
1167
1163
  }
1168
1164
  if (typeof ctrl !== "symbol") {
1169
1165
  if (identity.isCollection(node)) {
1170
- path30 = Object.freeze(path30.concat(node));
1166
+ path35 = Object.freeze(path35.concat(node));
1171
1167
  for (let i = 0; i < node.items.length; ++i) {
1172
- const ci = await visitAsync_(i, node.items[i], visitor, path30);
1168
+ const ci = await visitAsync_(i, node.items[i], visitor, path35);
1173
1169
  if (typeof ci === "number")
1174
1170
  i = ci - 1;
1175
1171
  else if (ci === BREAK)
@@ -1180,13 +1176,13 @@ var require_visit = __commonJS({
1180
1176
  }
1181
1177
  }
1182
1178
  } else if (identity.isPair(node)) {
1183
- path30 = Object.freeze(path30.concat(node));
1184
- const ck = await visitAsync_("key", node.key, visitor, path30);
1179
+ path35 = Object.freeze(path35.concat(node));
1180
+ const ck = await visitAsync_("key", node.key, visitor, path35);
1185
1181
  if (ck === BREAK)
1186
1182
  return BREAK;
1187
1183
  else if (ck === REMOVE)
1188
1184
  node.key = null;
1189
- const cv = await visitAsync_("value", node.value, visitor, path30);
1185
+ const cv = await visitAsync_("value", node.value, visitor, path35);
1190
1186
  if (cv === BREAK)
1191
1187
  return BREAK;
1192
1188
  else if (cv === REMOVE)
@@ -1213,23 +1209,23 @@ var require_visit = __commonJS({
1213
1209
  }
1214
1210
  return visitor;
1215
1211
  }
1216
- function callVisitor(key, node, visitor, path30) {
1212
+ function callVisitor(key, node, visitor, path35) {
1217
1213
  if (typeof visitor === "function")
1218
- return visitor(key, node, path30);
1214
+ return visitor(key, node, path35);
1219
1215
  if (identity.isMap(node))
1220
- return visitor.Map?.(key, node, path30);
1216
+ return visitor.Map?.(key, node, path35);
1221
1217
  if (identity.isSeq(node))
1222
- return visitor.Seq?.(key, node, path30);
1218
+ return visitor.Seq?.(key, node, path35);
1223
1219
  if (identity.isPair(node))
1224
- return visitor.Pair?.(key, node, path30);
1220
+ return visitor.Pair?.(key, node, path35);
1225
1221
  if (identity.isScalar(node))
1226
- return visitor.Scalar?.(key, node, path30);
1222
+ return visitor.Scalar?.(key, node, path35);
1227
1223
  if (identity.isAlias(node))
1228
- return visitor.Alias?.(key, node, path30);
1224
+ return visitor.Alias?.(key, node, path35);
1229
1225
  return void 0;
1230
1226
  }
1231
- function replaceNode(key, path30, node) {
1232
- const parent = path30[path30.length - 1];
1227
+ function replaceNode(key, path35, node) {
1228
+ const parent = path35[path35.length - 1];
1233
1229
  if (identity.isCollection(parent)) {
1234
1230
  parent.items[key] = node;
1235
1231
  } else if (identity.isPair(parent)) {
@@ -1837,10 +1833,10 @@ var require_Collection = __commonJS({
1837
1833
  var createNode = require_createNode();
1838
1834
  var identity = require_identity();
1839
1835
  var Node = require_Node();
1840
- function collectionFromPath(schema, path30, value) {
1836
+ function collectionFromPath(schema, path35, value) {
1841
1837
  let v = value;
1842
- for (let i = path30.length - 1; i >= 0; --i) {
1843
- const k = path30[i];
1838
+ for (let i = path35.length - 1; i >= 0; --i) {
1839
+ const k = path35[i];
1844
1840
  if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
1845
1841
  const a = [];
1846
1842
  a[k] = v;
@@ -1859,7 +1855,7 @@ var require_Collection = __commonJS({
1859
1855
  sourceObjects: /* @__PURE__ */ new Map()
1860
1856
  });
1861
1857
  }
1862
- var isEmptyPath = (path30) => path30 == null || typeof path30 === "object" && !!path30[Symbol.iterator]().next().done;
1858
+ var isEmptyPath = (path35) => path35 == null || typeof path35 === "object" && !!path35[Symbol.iterator]().next().done;
1863
1859
  var Collection = class extends Node.NodeBase {
1864
1860
  constructor(type, schema) {
1865
1861
  super(type);
@@ -1889,11 +1885,11 @@ var require_Collection = __commonJS({
1889
1885
  * be a Pair instance or a `{ key, value }` object, which may not have a key
1890
1886
  * that already exists in the map.
1891
1887
  */
1892
- addIn(path30, value) {
1893
- if (isEmptyPath(path30))
1888
+ addIn(path35, value) {
1889
+ if (isEmptyPath(path35))
1894
1890
  this.add(value);
1895
1891
  else {
1896
- const [key, ...rest] = path30;
1892
+ const [key, ...rest] = path35;
1897
1893
  const node = this.get(key, true);
1898
1894
  if (identity.isCollection(node))
1899
1895
  node.addIn(rest, value);
@@ -1907,8 +1903,8 @@ var require_Collection = __commonJS({
1907
1903
  * Removes a value from the collection.
1908
1904
  * @returns `true` if the item was found and removed.
1909
1905
  */
1910
- deleteIn(path30) {
1911
- const [key, ...rest] = path30;
1906
+ deleteIn(path35) {
1907
+ const [key, ...rest] = path35;
1912
1908
  if (rest.length === 0)
1913
1909
  return this.delete(key);
1914
1910
  const node = this.get(key, true);
@@ -1922,8 +1918,8 @@ var require_Collection = __commonJS({
1922
1918
  * scalar values from their surrounding node; to disable set `keepScalar` to
1923
1919
  * `true` (collections are always returned intact).
1924
1920
  */
1925
- getIn(path30, keepScalar) {
1926
- const [key, ...rest] = path30;
1921
+ getIn(path35, keepScalar) {
1922
+ const [key, ...rest] = path35;
1927
1923
  const node = this.get(key, true);
1928
1924
  if (rest.length === 0)
1929
1925
  return !keepScalar && identity.isScalar(node) ? node.value : node;
@@ -1941,8 +1937,8 @@ var require_Collection = __commonJS({
1941
1937
  /**
1942
1938
  * Checks if the collection includes a value with the key `key`.
1943
1939
  */
1944
- hasIn(path30) {
1945
- const [key, ...rest] = path30;
1940
+ hasIn(path35) {
1941
+ const [key, ...rest] = path35;
1946
1942
  if (rest.length === 0)
1947
1943
  return this.has(key);
1948
1944
  const node = this.get(key, true);
@@ -1952,8 +1948,8 @@ var require_Collection = __commonJS({
1952
1948
  * Sets a value in this collection. For `!!set`, `value` needs to be a
1953
1949
  * boolean to add/remove the item from the set.
1954
1950
  */
1955
- setIn(path30, value) {
1956
- const [key, ...rest] = path30;
1951
+ setIn(path35, value) {
1952
+ const [key, ...rest] = path35;
1957
1953
  if (rest.length === 0) {
1958
1954
  this.set(key, value);
1959
1955
  } else {
@@ -4457,9 +4453,9 @@ var require_Document = __commonJS({
4457
4453
  this.contents.add(value);
4458
4454
  }
4459
4455
  /** Adds a value to the document. */
4460
- addIn(path30, value) {
4456
+ addIn(path35, value) {
4461
4457
  if (assertCollection(this.contents))
4462
- this.contents.addIn(path30, value);
4458
+ this.contents.addIn(path35, value);
4463
4459
  }
4464
4460
  /**
4465
4461
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
@@ -4534,14 +4530,14 @@ var require_Document = __commonJS({
4534
4530
  * Removes a value from the document.
4535
4531
  * @returns `true` if the item was found and removed.
4536
4532
  */
4537
- deleteIn(path30) {
4538
- if (Collection.isEmptyPath(path30)) {
4533
+ deleteIn(path35) {
4534
+ if (Collection.isEmptyPath(path35)) {
4539
4535
  if (this.contents == null)
4540
4536
  return false;
4541
4537
  this.contents = null;
4542
4538
  return true;
4543
4539
  }
4544
- return assertCollection(this.contents) ? this.contents.deleteIn(path30) : false;
4540
+ return assertCollection(this.contents) ? this.contents.deleteIn(path35) : false;
4545
4541
  }
4546
4542
  /**
4547
4543
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -4556,10 +4552,10 @@ var require_Document = __commonJS({
4556
4552
  * scalar values from their surrounding node; to disable set `keepScalar` to
4557
4553
  * `true` (collections are always returned intact).
4558
4554
  */
4559
- getIn(path30, keepScalar) {
4560
- if (Collection.isEmptyPath(path30))
4555
+ getIn(path35, keepScalar) {
4556
+ if (Collection.isEmptyPath(path35))
4561
4557
  return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
4562
- return identity.isCollection(this.contents) ? this.contents.getIn(path30, keepScalar) : void 0;
4558
+ return identity.isCollection(this.contents) ? this.contents.getIn(path35, keepScalar) : void 0;
4563
4559
  }
4564
4560
  /**
4565
4561
  * Checks if the document includes a value with the key `key`.
@@ -4570,10 +4566,10 @@ var require_Document = __commonJS({
4570
4566
  /**
4571
4567
  * Checks if the document includes a value at `path`.
4572
4568
  */
4573
- hasIn(path30) {
4574
- if (Collection.isEmptyPath(path30))
4569
+ hasIn(path35) {
4570
+ if (Collection.isEmptyPath(path35))
4575
4571
  return this.contents !== void 0;
4576
- return identity.isCollection(this.contents) ? this.contents.hasIn(path30) : false;
4572
+ return identity.isCollection(this.contents) ? this.contents.hasIn(path35) : false;
4577
4573
  }
4578
4574
  /**
4579
4575
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -4590,13 +4586,13 @@ var require_Document = __commonJS({
4590
4586
  * Sets a value in this document. For `!!set`, `value` needs to be a
4591
4587
  * boolean to add/remove the item from the set.
4592
4588
  */
4593
- setIn(path30, value) {
4594
- if (Collection.isEmptyPath(path30)) {
4589
+ setIn(path35, value) {
4590
+ if (Collection.isEmptyPath(path35)) {
4595
4591
  this.contents = value;
4596
4592
  } else if (this.contents == null) {
4597
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path30), value);
4593
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path35), value);
4598
4594
  } else if (assertCollection(this.contents)) {
4599
- this.contents.setIn(path30, value);
4595
+ this.contents.setIn(path35, value);
4600
4596
  }
4601
4597
  }
4602
4598
  /**
@@ -6548,9 +6544,9 @@ var require_cst_visit = __commonJS({
6548
6544
  visit.BREAK = BREAK;
6549
6545
  visit.SKIP = SKIP;
6550
6546
  visit.REMOVE = REMOVE;
6551
- visit.itemAtPath = (cst, path30) => {
6547
+ visit.itemAtPath = (cst, path35) => {
6552
6548
  let item = cst;
6553
- for (const [field, index] of path30) {
6549
+ for (const [field, index] of path35) {
6554
6550
  const tok = item?.[field];
6555
6551
  if (tok && "items" in tok) {
6556
6552
  item = tok.items[index];
@@ -6559,23 +6555,23 @@ var require_cst_visit = __commonJS({
6559
6555
  }
6560
6556
  return item;
6561
6557
  };
6562
- visit.parentCollection = (cst, path30) => {
6563
- const parent = visit.itemAtPath(cst, path30.slice(0, -1));
6564
- const field = path30[path30.length - 1][0];
6558
+ visit.parentCollection = (cst, path35) => {
6559
+ const parent = visit.itemAtPath(cst, path35.slice(0, -1));
6560
+ const field = path35[path35.length - 1][0];
6565
6561
  const coll = parent?.[field];
6566
6562
  if (coll && "items" in coll)
6567
6563
  return coll;
6568
6564
  throw new Error("Parent collection not found");
6569
6565
  };
6570
- function _visit(path30, item, visitor) {
6571
- let ctrl = visitor(item, path30);
6566
+ function _visit(path35, item, visitor) {
6567
+ let ctrl = visitor(item, path35);
6572
6568
  if (typeof ctrl === "symbol")
6573
6569
  return ctrl;
6574
6570
  for (const field of ["key", "value"]) {
6575
6571
  const token = item[field];
6576
6572
  if (token && "items" in token) {
6577
6573
  for (let i = 0; i < token.items.length; ++i) {
6578
- const ci = _visit(Object.freeze(path30.concat([[field, i]])), token.items[i], visitor);
6574
+ const ci = _visit(Object.freeze(path35.concat([[field, i]])), token.items[i], visitor);
6579
6575
  if (typeof ci === "number")
6580
6576
  i = ci - 1;
6581
6577
  else if (ci === BREAK)
@@ -6586,10 +6582,10 @@ var require_cst_visit = __commonJS({
6586
6582
  }
6587
6583
  }
6588
6584
  if (typeof ctrl === "function" && field === "key")
6589
- ctrl = ctrl(item, path30);
6585
+ ctrl = ctrl(item, path35);
6590
6586
  }
6591
6587
  }
6592
- return typeof ctrl === "function" ? ctrl(item, path30) : ctrl;
6588
+ return typeof ctrl === "function" ? ctrl(item, path35) : ctrl;
6593
6589
  }
6594
6590
  exports2.visit = visit;
6595
6591
  }
@@ -7874,14 +7870,14 @@ var require_parser = __commonJS({
7874
7870
  case "scalar":
7875
7871
  case "single-quoted-scalar":
7876
7872
  case "double-quoted-scalar": {
7877
- const fs32 = this.flowScalar(this.type);
7873
+ const fs35 = this.flowScalar(this.type);
7878
7874
  if (atNextItem || it.value) {
7879
- map.items.push({ start, key: fs32, sep: [] });
7875
+ map.items.push({ start, key: fs35, sep: [] });
7880
7876
  this.onKeyLine = true;
7881
7877
  } else if (it.sep) {
7882
- this.stack.push(fs32);
7878
+ this.stack.push(fs35);
7883
7879
  } else {
7884
- Object.assign(it, { key: fs32, sep: [] });
7880
+ Object.assign(it, { key: fs35, sep: [] });
7885
7881
  this.onKeyLine = true;
7886
7882
  }
7887
7883
  return;
@@ -8009,13 +8005,13 @@ var require_parser = __commonJS({
8009
8005
  case "scalar":
8010
8006
  case "single-quoted-scalar":
8011
8007
  case "double-quoted-scalar": {
8012
- const fs32 = this.flowScalar(this.type);
8008
+ const fs35 = this.flowScalar(this.type);
8013
8009
  if (!it || it.value)
8014
- fc.items.push({ start: [], key: fs32, sep: [] });
8010
+ fc.items.push({ start: [], key: fs35, sep: [] });
8015
8011
  else if (it.sep)
8016
- this.stack.push(fs32);
8012
+ this.stack.push(fs35);
8017
8013
  else
8018
- Object.assign(it, { key: fs32, sep: [] });
8014
+ Object.assign(it, { key: fs35, sep: [] });
8019
8015
  return;
8020
8016
  }
8021
8017
  case "flow-map-end":
@@ -8323,15 +8319,13 @@ var require_dist = __commonJS({
8323
8319
  }
8324
8320
  });
8325
8321
 
8326
- // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/lockfile.js
8322
+ // packages/core/src/lockfile.js
8327
8323
  async function writeLockfile(resolved) {
8328
- const [kind, name] = parsePackageId(resolved.id);
8329
- const lockKind = kind === "binary" ? "binaries" : kind + "s";
8330
- const lockDir = import_path3.default.join(PATHS.locks, lockKind);
8324
+ const lockPath = getLockfilePath(resolved.id);
8325
+ const lockDir = import_path3.default.dirname(lockPath);
8331
8326
  if (!import_fs3.default.existsSync(lockDir)) {
8332
8327
  import_fs3.default.mkdirSync(lockDir, { recursive: true });
8333
8328
  }
8334
- const lockPath = import_path3.default.join(lockDir, `${name}.lock.yaml`);
8335
8329
  const lockfile = {
8336
8330
  id: resolved.id,
8337
8331
  version: resolved.version,
@@ -8443,7 +8437,7 @@ async function cleanOrphanedLockfiles() {
8443
8437
  }
8444
8438
  var import_fs3, import_path3, import_yaml;
8445
8439
  var init_lockfile = __esm({
8446
- "node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/lockfile.js"() {
8440
+ "packages/core/src/lockfile.js"() {
8447
8441
  import_fs3 = __toESM(require("fs"), 1);
8448
8442
  import_path3 = __toESM(require("path"), 1);
8449
8443
  import_yaml = __toESM(require_dist(), 1);
@@ -8451,28 +8445,91 @@ var init_lockfile = __esm({
8451
8445
  }
8452
8446
  });
8453
8447
 
8454
- // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/shims.js
8448
+ // packages/core/src/shims.js
8455
8449
  var shims_exports = {};
8456
8450
  __export(shims_exports, {
8457
8451
  createShimsForTool: () => createShimsForTool,
8452
+ getAllShimOwners: () => getAllShimOwners,
8453
+ getShimOwner: () => getShimOwner,
8458
8454
  listShims: () => listShims,
8459
8455
  removeShims: () => removeShims,
8460
8456
  validateShim: () => validateShim
8461
8457
  });
8458
+ function getShimRegistryPath() {
8459
+ return import_path4.default.join(PATHS.home, "shim-registry.json");
8460
+ }
8461
+ function loadShimRegistry() {
8462
+ const registryPath = getShimRegistryPath();
8463
+ try {
8464
+ if (import_fs4.default.existsSync(registryPath)) {
8465
+ return JSON.parse(import_fs4.default.readFileSync(registryPath, "utf-8"));
8466
+ }
8467
+ } catch {
8468
+ }
8469
+ return {};
8470
+ }
8471
+ function saveShimRegistry(registry) {
8472
+ const registryPath = getShimRegistryPath();
8473
+ const dir = import_path4.default.dirname(registryPath);
8474
+ if (!import_fs4.default.existsSync(dir)) {
8475
+ import_fs4.default.mkdirSync(dir, { recursive: true });
8476
+ }
8477
+ import_fs4.default.writeFileSync(registryPath, JSON.stringify(registry, null, 2));
8478
+ }
8479
+ function registerShim(bin, owner, type, target) {
8480
+ const registry = loadShimRegistry();
8481
+ const existing = registry[bin];
8482
+ let collision = false;
8483
+ let previousOwner = void 0;
8484
+ if (existing && existing.owner !== owner) {
8485
+ collision = true;
8486
+ previousOwner = existing.owner;
8487
+ }
8488
+ registry[bin] = {
8489
+ owner,
8490
+ type,
8491
+ target,
8492
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
8493
+ };
8494
+ saveShimRegistry(registry);
8495
+ return { collision, previousOwner };
8496
+ }
8497
+ function unregisterShim(bin) {
8498
+ const registry = loadShimRegistry();
8499
+ delete registry[bin];
8500
+ saveShimRegistry(registry);
8501
+ }
8502
+ function getShimOwner(bin) {
8503
+ const registry = loadShimRegistry();
8504
+ return registry[bin] || null;
8505
+ }
8506
+ function getAllShimOwners() {
8507
+ return loadShimRegistry();
8508
+ }
8462
8509
  async function createShimsForTool(manifest) {
8463
8510
  const bins = manifest.bins || [manifest.name || manifest.id.split(":")[1]];
8511
+ const created = [];
8512
+ const collisions = [];
8464
8513
  for (const bin of bins) {
8465
8514
  const target = resolveBinTarget(manifest, bin);
8466
8515
  if (!import_fs4.default.existsSync(target)) {
8467
8516
  console.warn(`[Shims] Warning: Binary target does not exist: ${target}`);
8468
8517
  continue;
8469
8518
  }
8519
+ const shimType = manifest.installType === "binary" ? "symlink" : "wrapper";
8470
8520
  if (manifest.installType === "binary") {
8471
8521
  createSymlinkShim(bin, target, PATHS.bins);
8472
8522
  } else {
8473
8523
  createWrapperShim(bin, target, PATHS.bins);
8474
8524
  }
8525
+ const { collision, previousOwner } = registerShim(bin, manifest.id, shimType, target);
8526
+ if (collision) {
8527
+ collisions.push({ bin, previousOwner });
8528
+ console.warn(`[Shims] Warning: '${bin}' was owned by ${previousOwner}, now owned by ${manifest.id}`);
8529
+ }
8530
+ created.push(bin);
8475
8531
  }
8532
+ return { created, collisions };
8476
8533
  }
8477
8534
  function resolveBinTarget(manifest, bin) {
8478
8535
  switch (manifest.installType) {
@@ -8513,14 +8570,21 @@ function createSymlinkShim(name, targetAbs, binsDir) {
8513
8570
  console.log(`[Shims] Created symlink shim: ${name} \u2192 ${targetAbs}`);
8514
8571
  }
8515
8572
  function removeShims(bins) {
8573
+ const removed = [];
8574
+ const notFound = [];
8516
8575
  for (const bin of bins) {
8517
8576
  const shimPath = import_path4.default.join(PATHS.bins, bin);
8518
8577
  try {
8519
8578
  import_fs4.default.unlinkSync(shimPath);
8579
+ unregisterShim(bin);
8580
+ removed.push(bin);
8520
8581
  console.log(`[Shims] Removed shim: ${bin}`);
8521
8582
  } catch (err) {
8583
+ notFound.push(bin);
8584
+ unregisterShim(bin);
8522
8585
  }
8523
8586
  }
8587
+ return { removed, notFound };
8524
8588
  }
8525
8589
  function listShims() {
8526
8590
  if (!import_fs4.default.existsSync(PATHS.bins)) {
@@ -8569,16 +8633,53 @@ function validateShim(bin) {
8569
8633
  }
8570
8634
  var import_fs4, import_path4;
8571
8635
  var init_shims = __esm({
8572
- "node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/shims.js"() {
8636
+ "packages/core/src/shims.js"() {
8573
8637
  import_fs4 = __toESM(require("fs"), 1);
8574
8638
  import_path4 = __toESM(require("path"), 1);
8575
8639
  init_src();
8576
8640
  }
8577
8641
  });
8578
8642
 
8579
- // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/installer.js
8643
+ // packages/core/src/installer.js
8644
+ function discoverNpmBins(installPath, packageName) {
8645
+ try {
8646
+ const pkgJsonPath = import_path5.default.join(installPath, "node_modules", packageName, "package.json");
8647
+ if (!import_fs5.default.existsSync(pkgJsonPath)) {
8648
+ console.warn(`[Installer] Warning: Could not find package.json at ${pkgJsonPath}`);
8649
+ return [];
8650
+ }
8651
+ const pkgJson = JSON.parse(import_fs5.default.readFileSync(pkgJsonPath, "utf8"));
8652
+ const bins = [];
8653
+ if (typeof pkgJson.bin === "string") {
8654
+ const binName = packageName.split("/").pop();
8655
+ bins.push(binName);
8656
+ } else if (typeof pkgJson.bin === "object" && pkgJson.bin !== null) {
8657
+ bins.push(...Object.keys(pkgJson.bin));
8658
+ } else {
8659
+ console.warn(`[Installer] Warning: Package '${packageName}' has no 'bin' field`);
8660
+ }
8661
+ return bins;
8662
+ } catch (error) {
8663
+ console.warn(`[Installer] Error discovering bins: ${error.message}`);
8664
+ return [];
8665
+ }
8666
+ }
8667
+ function hasInstallScripts(installPath, packageName) {
8668
+ try {
8669
+ const pkgJsonPath = import_path5.default.join(installPath, "node_modules", packageName, "package.json");
8670
+ if (!import_fs5.default.existsSync(pkgJsonPath)) {
8671
+ return false;
8672
+ }
8673
+ const pkgJson = JSON.parse(import_fs5.default.readFileSync(pkgJsonPath, "utf8"));
8674
+ const scripts = pkgJson.scripts || {};
8675
+ const installScriptKeys = ["preinstall", "install", "postinstall", "prepare"];
8676
+ return installScriptKeys.some((key) => scripts[key]);
8677
+ } catch (error) {
8678
+ return false;
8679
+ }
8680
+ }
8580
8681
  async function installPackage(id, options = {}) {
8581
- const { force = false, onProgress } = options;
8682
+ const { force = false, allowScripts = false, onProgress } = options;
8582
8683
  ensureDirectories();
8583
8684
  onProgress?.({ phase: "resolving", package: id });
8584
8685
  const resolved = await resolvePackage(id);
@@ -8598,7 +8699,7 @@ async function installPackage(id, options = {}) {
8598
8699
  for (const pkg of toInstall) {
8599
8700
  onProgress?.({ phase: "installing", package: pkg.id, total: toInstall.length, current: results.length + 1 });
8600
8701
  try {
8601
- const result = await installSinglePackage(pkg, { force, onProgress });
8702
+ const result = await installSinglePackage(pkg, { force, allowScripts, onProgress });
8602
8703
  results.push(result);
8603
8704
  } catch (error) {
8604
8705
  return {
@@ -8618,7 +8719,7 @@ async function installPackage(id, options = {}) {
8618
8719
  };
8619
8720
  }
8620
8721
  async function installSinglePackage(pkg, options = {}) {
8621
- const { force = false, onProgress } = options;
8722
+ const { force = false, allowScripts = false, onProgress } = options;
8622
8723
  const installPath = getPackagePath(pkg.id);
8623
8724
  if (import_fs5.default.existsSync(installPath) && !force) {
8624
8725
  return { success: true, id: pkg.id, path: installPath, skipped: true };
@@ -8638,7 +8739,23 @@ async function installSinglePackage(pkg, options = {}) {
8638
8739
  if (!import_fs5.default.existsSync(import_path5.default.join(installPath, "package.json"))) {
8639
8740
  execSync10(`"${npmCmd}" init -y`, { cwd: installPath, stdio: "pipe" });
8640
8741
  }
8641
- execSync10(`"${npmCmd}" install ${pkg.npmPackage}`, { cwd: installPath, stdio: "pipe" });
8742
+ const shouldIgnoreScripts = pkg.source?.type === "npm" && !allowScripts;
8743
+ const installFlags = shouldIgnoreScripts ? "--ignore-scripts --no-audit --no-fund" : "--no-audit --no-fund";
8744
+ execSync10(`"${npmCmd}" install ${pkg.npmPackage} ${installFlags}`, { cwd: installPath, stdio: "pipe" });
8745
+ let bins = pkg.bins;
8746
+ if (!bins || bins.length === 0) {
8747
+ bins = discoverNpmBins(installPath, pkg.npmPackage);
8748
+ console.log(`[Installer] Discovered binaries: ${bins.join(", ") || "(none)"}`);
8749
+ }
8750
+ let installedVersion = pkg.version || "latest";
8751
+ try {
8752
+ const pkgJsonPath = import_path5.default.join(installPath, "node_modules", pkg.npmPackage, "package.json");
8753
+ if (import_fs5.default.existsSync(pkgJsonPath)) {
8754
+ const pkgJson = JSON.parse(import_fs5.default.readFileSync(pkgJsonPath, "utf8"));
8755
+ installedVersion = pkgJson.version;
8756
+ }
8757
+ } catch (err) {
8758
+ }
8642
8759
  if (pkg.postInstall) {
8643
8760
  onProgress?.({ phase: "postInstall", package: pkg.id, message: pkg.postInstall });
8644
8761
  const postInstallCmd = pkg.postInstall.replace(
@@ -8647,27 +8764,43 @@ async function installSinglePackage(pkg, options = {}) {
8647
8764
  );
8648
8765
  execSync10(postInstallCmd, { cwd: installPath, stdio: "pipe" });
8649
8766
  }
8767
+ const scriptsDetected = hasInstallScripts(installPath, pkg.npmPackage);
8768
+ const scriptsPolicy = installFlags.includes("--ignore-scripts") ? "ignore" : "allow";
8769
+ if (scriptsDetected && scriptsPolicy === "ignore") {
8770
+ console.warn(`
8771
+ \u26A0\uFE0F This package defines install scripts that were skipped for security.`);
8772
+ console.warn(` If the CLI fails to run, reinstall with:`);
8773
+ console.warn(` rudi install ${pkg.id} --allow-scripts
8774
+ `);
8775
+ }
8650
8776
  const manifest2 = {
8651
8777
  id: pkg.id,
8652
8778
  kind: pkg.kind,
8653
8779
  name: pkgName,
8654
- version: pkg.version || "latest",
8780
+ version: installedVersion,
8655
8781
  npmPackage: pkg.npmPackage,
8782
+ bins,
8783
+ hasInstallScripts: scriptsDetected,
8784
+ scriptsPolicy,
8656
8785
  postInstall: pkg.postInstall,
8657
8786
  installedAt: (/* @__PURE__ */ new Date()).toISOString(),
8658
- source: "npm"
8787
+ source: pkg.source || { type: "npm" }
8659
8788
  };
8660
8789
  import_fs5.default.writeFileSync(
8661
8790
  import_path5.default.join(installPath, "manifest.json"),
8662
8791
  JSON.stringify(manifest2, null, 2)
8663
8792
  );
8664
- await createShimsForTool({
8665
- id: pkg.id,
8666
- installType: "npm",
8667
- installDir: installPath,
8668
- bins: pkg.bins || [pkgName],
8669
- name: pkgName
8670
- });
8793
+ if (bins && bins.length > 0) {
8794
+ await createShimsForTool({
8795
+ id: pkg.id,
8796
+ installType: "npm",
8797
+ installDir: installPath,
8798
+ bins,
8799
+ name: pkgName
8800
+ });
8801
+ } else {
8802
+ console.warn(`[Installer] Warning: No binaries found for ${pkg.npmPackage}`);
8803
+ }
8671
8804
  return { success: true, id: pkg.id, path: installPath };
8672
8805
  } catch (error) {
8673
8806
  throw new Error(`Failed to install ${pkg.npmPackage}: ${error.message}`);
@@ -8815,17 +8948,33 @@ async function uninstallPackage(id) {
8815
8948
  return { success: false, error: `Package not installed: ${id}` };
8816
8949
  }
8817
8950
  try {
8951
+ let bins = [];
8952
+ if (kind !== "prompt") {
8953
+ const manifestPath = import_path5.default.join(installPath, "manifest.json");
8954
+ if (import_fs5.default.existsSync(manifestPath)) {
8955
+ try {
8956
+ const manifest = JSON.parse(import_fs5.default.readFileSync(manifestPath, "utf-8"));
8957
+ bins = manifest.bins || manifest.binaries || [];
8958
+ } catch {
8959
+ bins = [name];
8960
+ }
8961
+ }
8962
+ }
8963
+ if (bins.length > 0) {
8964
+ removeShims(bins);
8965
+ }
8818
8966
  if (kind === "prompt") {
8819
8967
  import_fs5.default.unlinkSync(installPath);
8820
8968
  } else {
8821
8969
  import_fs5.default.rmSync(installPath, { recursive: true });
8822
8970
  }
8823
- const lockDir = kind === "binary" ? "binaries" : kind + "s";
8824
- const lockPath = import_path5.default.join(PATHS.locks, lockDir, `${name}.lock.yaml`);
8971
+ const lockDir = kind === "binary" ? "binaries" : kind === "npm" ? "npms" : kind + "s";
8972
+ const lockName = name.replace(/\//g, "__").replace(/^@/, "");
8973
+ const lockPath = import_path5.default.join(PATHS.locks, lockDir, `${lockName}.lock.yaml`);
8825
8974
  if (import_fs5.default.existsSync(lockPath)) {
8826
8975
  import_fs5.default.unlinkSync(lockPath);
8827
8976
  }
8828
- return { success: true };
8977
+ return { success: true, removedShims: bins };
8829
8978
  } catch (error) {
8830
8979
  return { success: false, error: error.message };
8831
8980
  }
@@ -9109,7 +9258,7 @@ async function installPythonRequirements(pythonPath, onProgress) {
9109
9258
  }
9110
9259
  var import_fs5, import_path5;
9111
9260
  var init_installer = __esm({
9112
- "node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/installer.js"() {
9261
+ "packages/core/src/installer.js"() {
9113
9262
  import_fs5 = __toESM(require("fs"), 1);
9114
9263
  import_path5 = __toESM(require("path"), 1);
9115
9264
  init_src();
@@ -9120,7 +9269,7 @@ var init_installer = __esm({
9120
9269
  }
9121
9270
  });
9122
9271
 
9123
- // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/deps.js
9272
+ // packages/core/src/deps.js
9124
9273
  function checkRuntime(runtime) {
9125
9274
  const name = runtime.replace(/^runtime:/, "");
9126
9275
  const rudiPath = import_path6.default.join(PATHS.runtimes, name);
@@ -9323,7 +9472,7 @@ async function getAllDepsFromRegistry() {
9323
9472
  }
9324
9473
  var import_fs6, import_path6, import_child_process;
9325
9474
  var init_deps = __esm({
9326
- "node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/deps.js"() {
9475
+ "packages/core/src/deps.js"() {
9327
9476
  import_fs6 = __toESM(require("fs"), 1);
9328
9477
  import_path6 = __toESM(require("path"), 1);
9329
9478
  import_child_process = require("child_process");
@@ -9332,7 +9481,7 @@ var init_deps = __esm({
9332
9481
  }
9333
9482
  });
9334
9483
 
9335
- // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/rudi-config.js
9484
+ // packages/core/src/rudi-config.js
9336
9485
  function createRudiConfig() {
9337
9486
  const now = (/* @__PURE__ */ new Date()).toISOString();
9338
9487
  return {
@@ -9555,7 +9704,7 @@ function updateSecretStatus(secretName, configured, provider) {
9555
9704
  }
9556
9705
  var fs7, path7, RUDI_JSON_PATH, RUDI_JSON_TMP, RUDI_JSON_LOCK, CONFIG_MODE, LOCK_TIMEOUT_MS;
9557
9706
  var init_rudi_config = __esm({
9558
- "node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/rudi-config.js"() {
9707
+ "packages/core/src/rudi-config.js"() {
9559
9708
  fs7 = __toESM(require("fs"), 1);
9560
9709
  path7 = __toESM(require("path"), 1);
9561
9710
  init_src();
@@ -9567,7 +9716,7 @@ var init_rudi_config = __esm({
9567
9716
  }
9568
9717
  });
9569
9718
 
9570
- // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/tool-index.js
9719
+ // packages/core/src/tool-index.js
9571
9720
  function loadSecrets() {
9572
9721
  try {
9573
9722
  const content = fs8.readFileSync(SECRETS_PATH, "utf-8");
@@ -9825,7 +9974,7 @@ async function indexAllStacks(options = {}) {
9825
9974
  }
9826
9975
  var import_child_process2, fs8, path8, readline, TOOL_INDEX_PATH, TOOL_INDEX_TMP, SECRETS_PATH, REQUEST_TIMEOUT_MS, PROTOCOL_VERSION;
9827
9976
  var init_tool_index = __esm({
9828
- "node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/tool-index.js"() {
9977
+ "packages/core/src/tool-index.js"() {
9829
9978
  import_child_process2 = require("child_process");
9830
9979
  fs8 = __toESM(require("fs"), 1);
9831
9980
  path8 = __toESM(require("path"), 1);
@@ -9840,7 +9989,7 @@ var init_tool_index = __esm({
9840
9989
  }
9841
9990
  });
9842
9991
 
9843
- // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/system-registry.js
9992
+ // packages/core/src/system-registry.js
9844
9993
  async function registerSystemBinary(name, options = {}) {
9845
9994
  const {
9846
9995
  searchPaths = getDefaultSearchPaths(),
@@ -9974,7 +10123,7 @@ function getSystemBinaryInfo(name) {
9974
10123
  }
9975
10124
  var import_fs7, import_path7, import_child_process3;
9976
10125
  var init_system_registry = __esm({
9977
- "node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/system-registry.js"() {
10126
+ "packages/core/src/system-registry.js"() {
9978
10127
  import_fs7 = __toESM(require("fs"), 1);
9979
10128
  import_path7 = __toESM(require("path"), 1);
9980
10129
  import_child_process3 = require("child_process");
@@ -9983,9 +10132,9 @@ var init_system_registry = __esm({
9983
10132
  }
9984
10133
  });
9985
10134
 
9986
- // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/index.js
9987
- var src_exports2 = {};
9988
- __export(src_exports2, {
10135
+ // packages/core/src/index.js
10136
+ var src_exports = {};
10137
+ __export(src_exports, {
9989
10138
  CONFIG_MODE: () => CONFIG_MODE,
9990
10139
  PATHS: () => PATHS,
9991
10140
  RUDI_JSON_PATH: () => RUDI_JSON_PATH,
@@ -10012,6 +10161,7 @@ __export(src_exports2, {
10012
10161
  formatDependencyResults: () => formatDependencyResults,
10013
10162
  getAllDepsFromRegistry: () => getAllDepsFromRegistry,
10014
10163
  getAllLockfiles: () => getAllLockfiles,
10164
+ getAllShimOwners: () => getAllShimOwners,
10015
10165
  getAvailableDeps: () => getAvailableDeps,
10016
10166
  getDefaultNpxBin: () => getDefaultNpxBin,
10017
10167
  getDefaultRuntimeBin: () => getDefaultRuntimeBin,
@@ -10021,6 +10171,7 @@ __export(src_exports2, {
10021
10171
  getLockfilePath: () => getLockfilePath,
10022
10172
  getPackage: () => getPackage,
10023
10173
  getPackagePath: () => getPackagePath,
10174
+ getShimOwner: () => getShimOwner,
10024
10175
  getSystemBinaryInfo: () => getSystemBinaryInfo,
10025
10176
  hasLockfile: () => hasLockfile,
10026
10177
  indexAllStacks: () => indexAllStacks,
@@ -10058,7 +10209,7 @@ __export(src_exports2, {
10058
10209
  writeToolIndex: () => writeToolIndex
10059
10210
  });
10060
10211
  var init_src3 = __esm({
10061
- "node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/index.js"() {
10212
+ "packages/core/src/index.js"() {
10062
10213
  init_src();
10063
10214
  init_src2();
10064
10215
  init_resolver();
@@ -10072,6 +10223,13 @@ var init_src3 = __esm({
10072
10223
  }
10073
10224
  });
10074
10225
 
10226
+ // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/shims.js
10227
+ var init_shims2 = __esm({
10228
+ "node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/shims.js"() {
10229
+ init_src();
10230
+ }
10231
+ });
10232
+
10075
10233
  // node_modules/.pnpm/ajv@8.17.1/node_modules/ajv/dist/compile/codegen/code.js
10076
10234
  var require_code = __commonJS({
10077
10235
  "node_modules/.pnpm/ajv@8.17.1/node_modules/ajv/dist/compile/codegen/code.js"(exports2) {
@@ -13265,8 +13423,8 @@ var require_utils = __commonJS({
13265
13423
  }
13266
13424
  return ind;
13267
13425
  }
13268
- function removeDotSegments(path30) {
13269
- let input = path30;
13426
+ function removeDotSegments(path35) {
13427
+ let input = path35;
13270
13428
  const output = [];
13271
13429
  let nextSlash = -1;
13272
13430
  let len = 0;
@@ -13465,8 +13623,8 @@ var require_schemes = __commonJS({
13465
13623
  wsComponent.secure = void 0;
13466
13624
  }
13467
13625
  if (wsComponent.resourceName) {
13468
- const [path30, query] = wsComponent.resourceName.split("?");
13469
- wsComponent.path = path30 && path30 !== "/" ? path30 : void 0;
13626
+ const [path35, query] = wsComponent.resourceName.split("?");
13627
+ wsComponent.path = path35 && path35 !== "/" ? path35 : void 0;
13470
13628
  wsComponent.query = query;
13471
13629
  wsComponent.resourceName = void 0;
13472
13630
  }
@@ -16819,12 +16977,12 @@ var require_dist2 = __commonJS({
16819
16977
  throw new Error(`Unknown format "${name}"`);
16820
16978
  return f;
16821
16979
  };
16822
- function addFormats2(ajv2, list, fs32, exportName) {
16980
+ function addFormats2(ajv2, list, fs35, exportName) {
16823
16981
  var _a;
16824
16982
  var _b;
16825
16983
  (_a = (_b = ajv2.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
16826
16984
  for (const f of list)
16827
- ajv2.addFormat(f, fs32[f]);
16985
+ ajv2.addFormat(f, fs35[f]);
16828
16986
  }
16829
16987
  module2.exports = exports2 = formatsPlugin;
16830
16988
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -16832,65 +16990,749 @@ var require_dist2 = __commonJS({
16832
16990
  }
16833
16991
  });
16834
16992
 
16835
- // node_modules/.pnpm/@learnrudi+utils@1.0.0/node_modules/@learnrudi/utils/src/args.js
16836
- function parseArgs(argv) {
16837
- const flags = {};
16838
- const args = [];
16839
- let command = null;
16840
- for (let i = 0; i < argv.length; i++) {
16841
- const arg = argv[i];
16842
- if (arg.startsWith("--")) {
16843
- const eqIndex = arg.indexOf("=");
16844
- if (eqIndex !== -1) {
16845
- const key = arg.slice(2, eqIndex);
16846
- const value = arg.slice(eqIndex + 1);
16847
- flags[key] = value;
16848
- } else {
16849
- const key = arg.slice(2);
16850
- const nextArg = argv[i + 1];
16851
- if (nextArg && !nextArg.startsWith("-")) {
16852
- flags[key] = nextArg;
16853
- i++;
16854
- } else {
16855
- flags[key] = true;
16856
- }
16857
- }
16858
- } else if (arg.startsWith("-") && arg.length > 1) {
16859
- const chars = arg.slice(1);
16860
- for (const char of chars) {
16861
- flags[char] = true;
16993
+ // packages/registry-client/src/index.js
16994
+ var src_exports2 = {};
16995
+ __export(src_exports2, {
16996
+ CACHE_TTL: () => CACHE_TTL2,
16997
+ DEFAULT_REGISTRY_URL: () => DEFAULT_REGISTRY_URL2,
16998
+ PACKAGE_KINDS: () => PACKAGE_KINDS4,
16999
+ RUNTIMES_DOWNLOAD_BASE: () => RUNTIMES_DOWNLOAD_BASE2,
17000
+ RUNTIMES_RELEASE_VERSION: () => RUNTIMES_RELEASE_VERSION2,
17001
+ checkCache: () => checkCache,
17002
+ clearCache: () => clearCache2,
17003
+ computeHash: () => computeHash,
17004
+ downloadPackage: () => downloadPackage2,
17005
+ downloadRuntime: () => downloadRuntime2,
17006
+ downloadTool: () => downloadTool2,
17007
+ fetchIndex: () => fetchIndex2,
17008
+ getManifest: () => getManifest2,
17009
+ getPackage: () => getPackage2,
17010
+ getPackageKinds: () => getPackageKinds,
17011
+ listPackages: () => listPackages2,
17012
+ searchPackages: () => searchPackages2,
17013
+ verifyHash: () => verifyHash
17014
+ });
17015
+ function getLocalRegistryPaths2() {
17016
+ if (process.env.USE_LOCAL_REGISTRY !== "true") {
17017
+ return [];
17018
+ }
17019
+ return [
17020
+ import_path18.default.join(process.cwd(), "registry", "index.json"),
17021
+ import_path18.default.join(process.cwd(), "..", "registry", "index.json"),
17022
+ "/Users/hoff/dev/RUDI/registry/index.json"
17023
+ ];
17024
+ }
17025
+ async function fetchIndex2(options = {}) {
17026
+ const { url = DEFAULT_REGISTRY_URL2, force = false } = options;
17027
+ const localResult = getLocalIndex2();
17028
+ if (localResult) {
17029
+ const { index: localIndex, mtime: localMtime } = localResult;
17030
+ const cacheMtime = getCacheMtime2();
17031
+ if (force || !cacheMtime || localMtime > cacheMtime) {
17032
+ cacheIndex2(localIndex);
17033
+ return localIndex;
17034
+ }
17035
+ }
17036
+ if (!force) {
17037
+ const cached = getCachedIndex2();
17038
+ if (cached) {
17039
+ return cached;
17040
+ }
17041
+ }
17042
+ if (localResult) {
17043
+ return localResult.index;
17044
+ }
17045
+ try {
17046
+ const response = await fetch(url, {
17047
+ headers: {
17048
+ "Accept": "application/json",
17049
+ "User-Agent": "rudi-cli/2.0"
16862
17050
  }
16863
- } else if (!command) {
16864
- command = arg;
16865
- } else {
16866
- args.push(arg);
17051
+ });
17052
+ if (!response.ok) {
17053
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
17054
+ }
17055
+ const index = await response.json();
17056
+ cacheIndex2(index);
17057
+ return index;
17058
+ } catch (error) {
17059
+ const fallback = getLocalIndex2();
17060
+ if (fallback) {
17061
+ return fallback.index;
16867
17062
  }
17063
+ throw new Error(`Failed to fetch registry: ${error.message}`);
16868
17064
  }
16869
- return { command, args, flags };
16870
17065
  }
16871
- function formatBytes(bytes) {
16872
- if (bytes === 0) return "0 B";
16873
- const k = 1024;
16874
- const sizes = ["B", "KB", "MB", "GB"];
16875
- const i = Math.floor(Math.log(bytes) / Math.log(k));
16876
- return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
17066
+ function getCachedIndex2() {
17067
+ const cachePath = PATHS.registryCache;
17068
+ if (!import_fs19.default.existsSync(cachePath)) {
17069
+ return null;
17070
+ }
17071
+ try {
17072
+ const stat = import_fs19.default.statSync(cachePath);
17073
+ const age = Date.now() - stat.mtimeMs;
17074
+ if (age > CACHE_TTL2) {
17075
+ return null;
17076
+ }
17077
+ return JSON.parse(import_fs19.default.readFileSync(cachePath, "utf-8"));
17078
+ } catch {
17079
+ return null;
17080
+ }
16877
17081
  }
16878
- function formatDuration(ms) {
16879
- if (ms < 1e3) return `${ms}ms`;
16880
- if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
16881
- const mins = Math.floor(ms / 6e4);
16882
- const secs = Math.floor(ms % 6e4 / 1e3);
16883
- return `${mins}m ${secs}s`;
17082
+ function cacheIndex2(index) {
17083
+ const cachePath = PATHS.registryCache;
17084
+ const cacheDir = import_path18.default.dirname(cachePath);
17085
+ if (!import_fs19.default.existsSync(cacheDir)) {
17086
+ import_fs19.default.mkdirSync(cacheDir, { recursive: true });
17087
+ }
17088
+ import_fs19.default.writeFileSync(cachePath, JSON.stringify(index, null, 2));
16884
17089
  }
16885
-
16886
- // node_modules/.pnpm/@learnrudi+utils@1.0.0/node_modules/@learnrudi/utils/src/help.js
16887
- function printVersion(version) {
16888
- console.log(`rudi v${version}`);
17090
+ function getCacheMtime2() {
17091
+ const cachePath = PATHS.registryCache;
17092
+ if (!import_fs19.default.existsSync(cachePath)) {
17093
+ return null;
17094
+ }
17095
+ try {
17096
+ return import_fs19.default.statSync(cachePath).mtimeMs;
17097
+ } catch {
17098
+ return null;
17099
+ }
16889
17100
  }
16890
- function printHelp(topic) {
16891
- if (topic) {
16892
- printCommandHelp(topic);
16893
- return;
17101
+ function getLocalIndex2() {
17102
+ for (const localPath of getLocalRegistryPaths2()) {
17103
+ if (import_fs19.default.existsSync(localPath)) {
17104
+ try {
17105
+ const index = JSON.parse(import_fs19.default.readFileSync(localPath, "utf-8"));
17106
+ const mtime = import_fs19.default.statSync(localPath).mtimeMs;
17107
+ return { index, mtime };
17108
+ } catch {
17109
+ continue;
17110
+ }
17111
+ }
17112
+ }
17113
+ return null;
17114
+ }
17115
+ function clearCache2() {
17116
+ if (import_fs19.default.existsSync(PATHS.registryCache)) {
17117
+ import_fs19.default.unlinkSync(PATHS.registryCache);
17118
+ }
17119
+ }
17120
+ function checkCache() {
17121
+ const cachePath = PATHS.registryCache;
17122
+ if (!import_fs19.default.existsSync(cachePath)) {
17123
+ return { fresh: false, age: null };
17124
+ }
17125
+ try {
17126
+ const stat = import_fs19.default.statSync(cachePath);
17127
+ const age = Date.now() - stat.mtimeMs;
17128
+ return { fresh: age <= CACHE_TTL2, age };
17129
+ } catch {
17130
+ return { fresh: false, age: null };
17131
+ }
17132
+ }
17133
+ function getKindSection2(kind) {
17134
+ return KIND_PLURALS2[kind] || `${kind}s`;
17135
+ }
17136
+ async function searchPackages2(query, options = {}) {
17137
+ const { kind } = options;
17138
+ const index = await fetchIndex2();
17139
+ const results = [];
17140
+ const queryLower = query.toLowerCase();
17141
+ const kinds = kind ? [kind] : PACKAGE_KINDS4;
17142
+ for (const k of kinds) {
17143
+ const section = index.packages?.[getKindSection2(k)];
17144
+ if (!section) continue;
17145
+ const packages = [...section.official || [], ...section.community || []];
17146
+ for (const pkg of packages) {
17147
+ if (matchesQuery2(pkg, queryLower)) {
17148
+ results.push({ ...pkg, kind: k });
17149
+ }
17150
+ }
17151
+ }
17152
+ return results;
17153
+ }
17154
+ function matchesQuery2(pkg, query) {
17155
+ const searchable = [
17156
+ pkg.id || "",
17157
+ pkg.name || "",
17158
+ pkg.description || "",
17159
+ ...pkg.tags || []
17160
+ ].join(" ").toLowerCase();
17161
+ return searchable.includes(query);
17162
+ }
17163
+ async function getPackage2(id) {
17164
+ const index = await fetchIndex2();
17165
+ const [kind, name] = id.includes(":") ? id.split(":") : [null, id];
17166
+ const kinds = kind ? [kind] : PACKAGE_KINDS4;
17167
+ for (const k of kinds) {
17168
+ const section = index.packages?.[getKindSection2(k)];
17169
+ if (!section) continue;
17170
+ const packages = [...section.official || [], ...section.community || []];
17171
+ for (const pkg of packages) {
17172
+ const kindPrefixPattern = new RegExp(`^(${PACKAGE_KINDS4.join("|")}):`);
17173
+ const pkgShortId = pkg.id?.replace(kindPrefixPattern, "") || "";
17174
+ if (pkgShortId === name || pkg.id === id) {
17175
+ return { ...pkg, kind: k };
17176
+ }
17177
+ }
17178
+ }
17179
+ return null;
17180
+ }
17181
+ async function getManifest2(pkg) {
17182
+ if (!pkg || !pkg.path) {
17183
+ return null;
17184
+ }
17185
+ const manifestPath = pkg.path;
17186
+ if (process.env.USE_LOCAL_REGISTRY === "true") {
17187
+ const localPaths = [
17188
+ import_path18.default.join(process.cwd(), "registry", manifestPath),
17189
+ import_path18.default.join(process.cwd(), "..", "registry", manifestPath),
17190
+ `/Users/hoff/dev/RUDI/registry/${manifestPath}`
17191
+ ];
17192
+ for (const localPath of localPaths) {
17193
+ if (import_fs19.default.existsSync(localPath)) {
17194
+ try {
17195
+ const content = import_fs19.default.readFileSync(localPath, "utf-8");
17196
+ return JSON.parse(content);
17197
+ } catch (err) {
17198
+ }
17199
+ }
17200
+ }
17201
+ }
17202
+ try {
17203
+ const url = `${GITHUB_RAW_BASE2}/${manifestPath}`;
17204
+ const response = await fetch(url, {
17205
+ headers: {
17206
+ "Accept": "application/json",
17207
+ "User-Agent": "rudi-cli/2.0"
17208
+ }
17209
+ });
17210
+ if (!response.ok) {
17211
+ return null;
17212
+ }
17213
+ return await response.json();
17214
+ } catch (err) {
17215
+ return null;
17216
+ }
17217
+ }
17218
+ async function listPackages2(kind) {
17219
+ const index = await fetchIndex2();
17220
+ const section = index.packages?.[getKindSection2(kind)];
17221
+ if (!section) return [];
17222
+ return [...section.official || [], ...section.community || []];
17223
+ }
17224
+ function getPackageKinds() {
17225
+ return PACKAGE_KINDS4;
17226
+ }
17227
+ async function downloadPackage2(pkg, destPath, options = {}) {
17228
+ const { onProgress } = options;
17229
+ const registryPath = pkg.path;
17230
+ if (!import_fs19.default.existsSync(destPath)) {
17231
+ import_fs19.default.mkdirSync(destPath, { recursive: true });
17232
+ }
17233
+ onProgress?.({ phase: "downloading", package: pkg.name || pkg.id });
17234
+ if (pkg.kind === "stack" || registryPath.includes("/stacks/")) {
17235
+ await downloadStackFromGitHub2(registryPath, destPath, onProgress);
17236
+ return { success: true, path: destPath };
17237
+ }
17238
+ if (registryPath.endsWith(".md")) {
17239
+ const url = `${GITHUB_RAW_BASE2}/${registryPath}`;
17240
+ const response = await fetch(url, {
17241
+ headers: { "User-Agent": "rudi-cli/2.0" }
17242
+ });
17243
+ if (!response.ok) {
17244
+ throw new Error(`Failed to download ${registryPath}: HTTP ${response.status}`);
17245
+ }
17246
+ const content = await response.text();
17247
+ const destDir = import_path18.default.dirname(destPath);
17248
+ if (!import_fs19.default.existsSync(destDir)) {
17249
+ import_fs19.default.mkdirSync(destDir, { recursive: true });
17250
+ }
17251
+ import_fs19.default.writeFileSync(destPath, content);
17252
+ return { success: true, path: destPath };
17253
+ }
17254
+ throw new Error(`Unsupported package type: ${registryPath}`);
17255
+ }
17256
+ async function downloadStackFromGitHub2(registryPath, destPath, onProgress) {
17257
+ const baseUrl = `${GITHUB_RAW_BASE2}/${registryPath}`;
17258
+ const apiUrl = `https://api.github.com/repos/learn-rudi/registry/contents/${registryPath}`;
17259
+ const listResponse = await fetch(apiUrl, {
17260
+ headers: {
17261
+ "User-Agent": "rudi-cli/2.0",
17262
+ "Accept": "application/vnd.github.v3+json"
17263
+ }
17264
+ });
17265
+ if (!listResponse.ok) {
17266
+ throw new Error(`Stack not found: ${registryPath}`);
17267
+ }
17268
+ const contents = await listResponse.json();
17269
+ if (!Array.isArray(contents)) {
17270
+ throw new Error(`Invalid stack directory: ${registryPath}`);
17271
+ }
17272
+ const existingItems = /* @__PURE__ */ new Map();
17273
+ for (const item of contents) {
17274
+ existingItems.set(item.name, item);
17275
+ }
17276
+ const manifestItem = existingItems.get("manifest.json");
17277
+ if (!manifestItem) {
17278
+ throw new Error(`Stack missing manifest.json: ${registryPath}`);
17279
+ }
17280
+ const manifestResponse = await fetch(manifestItem.download_url, {
17281
+ headers: { "User-Agent": "rudi-cli/2.0" }
17282
+ });
17283
+ const manifest = await manifestResponse.json();
17284
+ import_fs19.default.writeFileSync(import_path18.default.join(destPath, "manifest.json"), JSON.stringify(manifest, null, 2));
17285
+ onProgress?.({ phase: "downloading", file: "manifest.json" });
17286
+ const pkgJsonItem = existingItems.get("package.json");
17287
+ if (pkgJsonItem) {
17288
+ const pkgJsonResponse = await fetch(pkgJsonItem.download_url, {
17289
+ headers: { "User-Agent": "rudi-cli/2.0" }
17290
+ });
17291
+ if (pkgJsonResponse.ok) {
17292
+ const pkgJson = await pkgJsonResponse.text();
17293
+ import_fs19.default.writeFileSync(import_path18.default.join(destPath, "package.json"), pkgJson);
17294
+ onProgress?.({ phase: "downloading", file: "package.json" });
17295
+ }
17296
+ }
17297
+ const envExampleItem = existingItems.get(".env.example");
17298
+ if (envExampleItem) {
17299
+ const envResponse = await fetch(envExampleItem.download_url, {
17300
+ headers: { "User-Agent": "rudi-cli/2.0" }
17301
+ });
17302
+ if (envResponse.ok) {
17303
+ const envContent = await envResponse.text();
17304
+ import_fs19.default.writeFileSync(import_path18.default.join(destPath, ".env.example"), envContent);
17305
+ }
17306
+ }
17307
+ const tsconfigItem = existingItems.get("tsconfig.json");
17308
+ if (tsconfigItem) {
17309
+ const tsconfigResponse = await fetch(tsconfigItem.download_url, {
17310
+ headers: { "User-Agent": "rudi-cli/2.0" }
17311
+ });
17312
+ if (tsconfigResponse.ok) {
17313
+ const tsconfig = await tsconfigResponse.text();
17314
+ import_fs19.default.writeFileSync(import_path18.default.join(destPath, "tsconfig.json"), tsconfig);
17315
+ }
17316
+ }
17317
+ const requirementsItem = existingItems.get("requirements.txt");
17318
+ if (requirementsItem) {
17319
+ const reqResponse = await fetch(requirementsItem.download_url, {
17320
+ headers: { "User-Agent": "rudi-cli/2.0" }
17321
+ });
17322
+ if (reqResponse.ok) {
17323
+ const requirements = await reqResponse.text();
17324
+ import_fs19.default.writeFileSync(import_path18.default.join(destPath, "requirements.txt"), requirements);
17325
+ }
17326
+ }
17327
+ const sourceDirs = ["src", "dist", "node", "python", "lib"];
17328
+ for (const dirName of sourceDirs) {
17329
+ const dirItem = existingItems.get(dirName);
17330
+ if (dirItem && dirItem.type === "dir") {
17331
+ onProgress?.({ phase: "downloading", directory: dirName });
17332
+ await downloadDirectoryFromGitHub2(
17333
+ `${baseUrl}/${dirName}`,
17334
+ import_path18.default.join(destPath, dirName),
17335
+ onProgress
17336
+ );
17337
+ }
17338
+ }
17339
+ }
17340
+ async function downloadDirectoryFromGitHub2(dirUrl, destDir, onProgress) {
17341
+ const apiUrl = dirUrl.replace("https://raw.githubusercontent.com/", "https://api.github.com/repos/").replace("/main/", "/contents/");
17342
+ try {
17343
+ const response = await fetch(apiUrl, {
17344
+ headers: {
17345
+ "User-Agent": "rudi-cli/2.0",
17346
+ "Accept": "application/vnd.github.v3+json"
17347
+ }
17348
+ });
17349
+ if (!response.ok) {
17350
+ return;
17351
+ }
17352
+ const contents = await response.json();
17353
+ if (!Array.isArray(contents)) {
17354
+ return;
17355
+ }
17356
+ if (!import_fs19.default.existsSync(destDir)) {
17357
+ import_fs19.default.mkdirSync(destDir, { recursive: true });
17358
+ }
17359
+ for (const item of contents) {
17360
+ if (item.type === "file") {
17361
+ const fileResponse = await fetch(item.download_url, {
17362
+ headers: { "User-Agent": "rudi-cli/2.0" }
17363
+ });
17364
+ if (fileResponse.ok) {
17365
+ const content = await fileResponse.text();
17366
+ import_fs19.default.writeFileSync(import_path18.default.join(destDir, item.name), content);
17367
+ onProgress?.({ phase: "downloading", file: item.name });
17368
+ }
17369
+ } else if (item.type === "dir") {
17370
+ await downloadDirectoryFromGitHub2(
17371
+ item.url.replace("https://api.github.com/repos/", "https://raw.githubusercontent.com/").replace("/contents/", "/main/"),
17372
+ import_path18.default.join(destDir, item.name),
17373
+ onProgress
17374
+ );
17375
+ }
17376
+ }
17377
+ } catch (error) {
17378
+ console.error(`Warning: Could not download ${dirUrl}: ${error.message}`);
17379
+ }
17380
+ }
17381
+ async function downloadRuntime2(runtime, version, destPath, options = {}) {
17382
+ const { onProgress } = options;
17383
+ const platformArch = getPlatformArch();
17384
+ const shortVersion = version.replace(/\.x$/, "").replace(/\.0$/, "");
17385
+ const filename = `${runtime}-${shortVersion}-${platformArch}.tar.gz`;
17386
+ const url = `${RUNTIMES_DOWNLOAD_BASE2}/${RUNTIMES_RELEASE_VERSION2}/${filename}`;
17387
+ onProgress?.({ phase: "downloading", runtime, version, url });
17388
+ const tempDir = import_path18.default.join(PATHS.cache, "downloads");
17389
+ if (!import_fs19.default.existsSync(tempDir)) {
17390
+ import_fs19.default.mkdirSync(tempDir, { recursive: true });
17391
+ }
17392
+ const tempFile = import_path18.default.join(tempDir, filename);
17393
+ try {
17394
+ const response = await fetch(url, {
17395
+ headers: {
17396
+ "User-Agent": "rudi-cli/2.0",
17397
+ "Accept": "application/octet-stream"
17398
+ }
17399
+ });
17400
+ if (!response.ok) {
17401
+ throw new Error(`Failed to download ${runtime}: HTTP ${response.status}`);
17402
+ }
17403
+ const buffer = await response.arrayBuffer();
17404
+ import_fs19.default.writeFileSync(tempFile, Buffer.from(buffer));
17405
+ onProgress?.({ phase: "extracting", runtime, version });
17406
+ if (import_fs19.default.existsSync(destPath)) {
17407
+ import_fs19.default.rmSync(destPath, { recursive: true });
17408
+ }
17409
+ import_fs19.default.mkdirSync(destPath, { recursive: true });
17410
+ const { execSync: execSync10 } = await import("child_process");
17411
+ execSync10(`tar -xzf "${tempFile}" -C "${destPath}" --strip-components=1`, {
17412
+ stdio: "pipe"
17413
+ });
17414
+ import_fs19.default.unlinkSync(tempFile);
17415
+ import_fs19.default.writeFileSync(
17416
+ import_path18.default.join(destPath, "runtime.json"),
17417
+ JSON.stringify({
17418
+ runtime,
17419
+ version,
17420
+ platformArch,
17421
+ downloadedAt: (/* @__PURE__ */ new Date()).toISOString(),
17422
+ source: url
17423
+ }, null, 2)
17424
+ );
17425
+ onProgress?.({ phase: "complete", runtime, version, path: destPath });
17426
+ return { success: true, path: destPath };
17427
+ } catch (error) {
17428
+ if (import_fs19.default.existsSync(tempFile)) {
17429
+ import_fs19.default.unlinkSync(tempFile);
17430
+ }
17431
+ throw new Error(`Failed to install ${runtime} ${version}: ${error.message}`);
17432
+ }
17433
+ }
17434
+ async function downloadTool2(toolName, destPath, options = {}) {
17435
+ const { onProgress } = options;
17436
+ const platformArch = getPlatformArch();
17437
+ const toolManifest = await loadToolManifest2(toolName);
17438
+ if (!toolManifest) {
17439
+ throw new Error(`Binary manifest not found for: ${toolName}`);
17440
+ }
17441
+ const tempDir = import_path18.default.join(PATHS.cache, "downloads");
17442
+ if (!import_fs19.default.existsSync(tempDir)) {
17443
+ import_fs19.default.mkdirSync(tempDir, { recursive: true });
17444
+ }
17445
+ if (import_fs19.default.existsSync(destPath)) {
17446
+ import_fs19.default.rmSync(destPath, { recursive: true });
17447
+ }
17448
+ import_fs19.default.mkdirSync(destPath, { recursive: true });
17449
+ const { execSync: execSync10 } = await import("child_process");
17450
+ const downloads = toolManifest.downloads?.[platformArch];
17451
+ if (downloads && Array.isArray(downloads)) {
17452
+ const downloadedUrls = /* @__PURE__ */ new Set();
17453
+ for (const download of downloads) {
17454
+ const { url, type, binary } = download;
17455
+ if (downloadedUrls.has(url)) {
17456
+ await extractBinaryFromPath2(destPath, binary, destPath);
17457
+ continue;
17458
+ }
17459
+ onProgress?.({ phase: "downloading", tool: toolName, binary: import_path18.default.basename(binary), url });
17460
+ const urlFilename = import_path18.default.basename(new URL(url).pathname);
17461
+ const tempFile = import_path18.default.join(tempDir, urlFilename);
17462
+ try {
17463
+ const response = await fetch(url, {
17464
+ headers: {
17465
+ "User-Agent": "rudi-cli/2.0",
17466
+ "Accept": "application/octet-stream"
17467
+ }
17468
+ });
17469
+ if (!response.ok) {
17470
+ throw new Error(`Failed to download ${binary}: HTTP ${response.status}`);
17471
+ }
17472
+ const buffer = await response.arrayBuffer();
17473
+ import_fs19.default.writeFileSync(tempFile, Buffer.from(buffer));
17474
+ downloadedUrls.add(url);
17475
+ onProgress?.({ phase: "extracting", tool: toolName, binary: import_path18.default.basename(binary) });
17476
+ const archiveType = type || guessArchiveType2(urlFilename);
17477
+ if (archiveType === "zip") {
17478
+ execSync10(`unzip -o "${tempFile}" -d "${destPath}"`, { stdio: "pipe" });
17479
+ } else if (archiveType === "tar.xz") {
17480
+ execSync10(`tar -xJf "${tempFile}" -C "${destPath}"`, { stdio: "pipe" });
17481
+ } else if (archiveType === "tar.gz" || archiveType === "tgz") {
17482
+ execSync10(`tar -xzf "${tempFile}" -C "${destPath}"`, { stdio: "pipe" });
17483
+ } else {
17484
+ throw new Error(`Unsupported archive type: ${archiveType}`);
17485
+ }
17486
+ await extractBinaryFromPath2(destPath, binary, destPath);
17487
+ import_fs19.default.unlinkSync(tempFile);
17488
+ } catch (error) {
17489
+ if (import_fs19.default.existsSync(tempFile)) {
17490
+ import_fs19.default.unlinkSync(tempFile);
17491
+ }
17492
+ throw error;
17493
+ }
17494
+ }
17495
+ const binaries = toolManifest.binaries || [toolName];
17496
+ for (const bin of binaries) {
17497
+ const binPath = import_path18.default.join(destPath, bin);
17498
+ if (import_fs19.default.existsSync(binPath)) {
17499
+ import_fs19.default.chmodSync(binPath, 493);
17500
+ }
17501
+ }
17502
+ } else {
17503
+ const upstreamUrl = toolManifest.upstream?.[platformArch];
17504
+ if (!upstreamUrl) {
17505
+ throw new Error(`No upstream URL for ${toolName} on ${platformArch}`);
17506
+ }
17507
+ const extractConfig = toolManifest.extract?.[platformArch] || toolManifest.extract?.default;
17508
+ if (!extractConfig) {
17509
+ throw new Error(`No extract config for ${toolName} on ${platformArch}`);
17510
+ }
17511
+ onProgress?.({ phase: "downloading", tool: toolName, url: upstreamUrl });
17512
+ const urlFilename = import_path18.default.basename(new URL(upstreamUrl).pathname);
17513
+ const tempFile = import_path18.default.join(tempDir, urlFilename);
17514
+ try {
17515
+ const response = await fetch(upstreamUrl, {
17516
+ headers: {
17517
+ "User-Agent": "rudi-cli/2.0",
17518
+ "Accept": "application/octet-stream"
17519
+ }
17520
+ });
17521
+ if (!response.ok) {
17522
+ throw new Error(`Failed to download ${toolName}: HTTP ${response.status}`);
17523
+ }
17524
+ const buffer = await response.arrayBuffer();
17525
+ import_fs19.default.writeFileSync(tempFile, Buffer.from(buffer));
17526
+ onProgress?.({ phase: "extracting", tool: toolName });
17527
+ const archiveType = extractConfig.type || guessArchiveType2(urlFilename);
17528
+ const stripComponents = extractConfig.strip || 0;
17529
+ const stripFlag = stripComponents > 0 ? ` --strip-components=${stripComponents}` : "";
17530
+ if (archiveType === "zip") {
17531
+ execSync10(`unzip -o "${tempFile}" -d "${destPath}"`, { stdio: "pipe" });
17532
+ } else if (archiveType === "tar.xz") {
17533
+ execSync10(`tar -xJf "${tempFile}" -C "${destPath}"${stripFlag}`, { stdio: "pipe" });
17534
+ } else if (archiveType === "tar.gz" || archiveType === "tgz") {
17535
+ execSync10(`tar -xzf "${tempFile}" -C "${destPath}"${stripFlag}`, { stdio: "pipe" });
17536
+ } else {
17537
+ throw new Error(`Unsupported archive type: ${archiveType}`);
17538
+ }
17539
+ await extractBinaryFromPath2(destPath, extractConfig.binary || toolName, destPath);
17540
+ const binaries = [toolName, ...toolManifest.additionalBinaries || []];
17541
+ for (const bin of binaries) {
17542
+ const binPath = import_path18.default.join(destPath, bin);
17543
+ if (import_fs19.default.existsSync(binPath)) {
17544
+ import_fs19.default.chmodSync(binPath, 493);
17545
+ }
17546
+ }
17547
+ import_fs19.default.unlinkSync(tempFile);
17548
+ } catch (error) {
17549
+ if (import_fs19.default.existsSync(tempFile)) {
17550
+ import_fs19.default.unlinkSync(tempFile);
17551
+ }
17552
+ throw new Error(`Failed to install ${toolName}: ${error.message}`);
17553
+ }
17554
+ }
17555
+ import_fs19.default.writeFileSync(
17556
+ import_path18.default.join(destPath, "manifest.json"),
17557
+ JSON.stringify({
17558
+ id: `binary:${toolName}`,
17559
+ kind: "binary",
17560
+ name: toolManifest.name || toolName,
17561
+ version: toolManifest.version,
17562
+ binaries: toolManifest.bins || toolManifest.binaries || [toolName],
17563
+ platformArch,
17564
+ installedAt: (/* @__PURE__ */ new Date()).toISOString()
17565
+ }, null, 2)
17566
+ );
17567
+ onProgress?.({ phase: "complete", tool: toolName, path: destPath });
17568
+ return { success: true, path: destPath };
17569
+ }
17570
+ async function extractBinaryFromPath2(extractedPath, binaryPattern, destPath) {
17571
+ const directPath = import_path18.default.join(destPath, import_path18.default.basename(binaryPattern));
17572
+ if (!binaryPattern.includes("/") && !binaryPattern.includes("*")) {
17573
+ if (import_fs19.default.existsSync(directPath)) {
17574
+ return;
17575
+ }
17576
+ }
17577
+ if (binaryPattern.includes("*") || binaryPattern.includes("/")) {
17578
+ const parts = binaryPattern.split("/");
17579
+ let currentPath = extractedPath;
17580
+ for (let i = 0; i < parts.length; i++) {
17581
+ const part = parts[i];
17582
+ if (part.includes("*")) {
17583
+ if (!import_fs19.default.existsSync(currentPath)) break;
17584
+ const entries = import_fs19.default.readdirSync(currentPath);
17585
+ const pattern = new RegExp("^" + part.replace(/\*/g, ".*") + "$");
17586
+ const match = entries.find((e) => pattern.test(e));
17587
+ if (match) {
17588
+ currentPath = import_path18.default.join(currentPath, match);
17589
+ } else {
17590
+ break;
17591
+ }
17592
+ } else {
17593
+ currentPath = import_path18.default.join(currentPath, part);
17594
+ }
17595
+ }
17596
+ if (import_fs19.default.existsSync(currentPath) && currentPath !== destPath) {
17597
+ const finalPath = import_path18.default.join(destPath, import_path18.default.basename(currentPath));
17598
+ if (currentPath !== finalPath && !import_fs19.default.existsSync(finalPath)) {
17599
+ import_fs19.default.renameSync(currentPath, finalPath);
17600
+ }
17601
+ }
17602
+ }
17603
+ }
17604
+ async function loadToolManifest2(toolName) {
17605
+ for (const basePath of getLocalRegistryPaths2()) {
17606
+ const registryDir = import_path18.default.dirname(basePath);
17607
+ const manifestPath = import_path18.default.join(registryDir, "catalog", "binaries", `${toolName}.json`);
17608
+ if (import_fs19.default.existsSync(manifestPath)) {
17609
+ try {
17610
+ return JSON.parse(import_fs19.default.readFileSync(manifestPath, "utf-8"));
17611
+ } catch {
17612
+ continue;
17613
+ }
17614
+ }
17615
+ }
17616
+ try {
17617
+ const url = `https://raw.githubusercontent.com/learn-rudi/registry/main/catalog/binaries/${toolName}.json`;
17618
+ const response = await fetch(url, {
17619
+ headers: {
17620
+ "User-Agent": "rudi-cli/2.0",
17621
+ "Accept": "application/json"
17622
+ }
17623
+ });
17624
+ if (response.ok) {
17625
+ return await response.json();
17626
+ }
17627
+ } catch {
17628
+ }
17629
+ return null;
17630
+ }
17631
+ function guessArchiveType2(filename) {
17632
+ if (filename.endsWith(".tar.gz") || filename.endsWith(".tgz")) return "tar.gz";
17633
+ if (filename.endsWith(".tar.xz")) return "tar.xz";
17634
+ if (filename.endsWith(".zip")) return "zip";
17635
+ return "tar.gz";
17636
+ }
17637
+ async function verifyHash(filePath, expectedHash) {
17638
+ return new Promise((resolve, reject) => {
17639
+ const hash = import_crypto2.default.createHash("sha256");
17640
+ const stream = import_fs19.default.createReadStream(filePath);
17641
+ stream.on("data", (data) => hash.update(data));
17642
+ stream.on("end", () => {
17643
+ const actualHash = hash.digest("hex");
17644
+ resolve(actualHash === expectedHash);
17645
+ });
17646
+ stream.on("error", reject);
17647
+ });
17648
+ }
17649
+ async function computeHash(filePath) {
17650
+ return new Promise((resolve, reject) => {
17651
+ const hash = import_crypto2.default.createHash("sha256");
17652
+ const stream = import_fs19.default.createReadStream(filePath);
17653
+ stream.on("data", (data) => hash.update(data));
17654
+ stream.on("end", () => resolve(hash.digest("hex")));
17655
+ stream.on("error", reject);
17656
+ });
17657
+ }
17658
+ var import_fs19, import_path18, import_crypto2, DEFAULT_REGISTRY_URL2, RUNTIMES_DOWNLOAD_BASE2, CACHE_TTL2, PACKAGE_KINDS4, KIND_PLURALS2, GITHUB_RAW_BASE2, RUNTIMES_RELEASE_VERSION2;
17659
+ var init_src4 = __esm({
17660
+ "packages/registry-client/src/index.js"() {
17661
+ import_fs19 = __toESM(require("fs"), 1);
17662
+ import_path18 = __toESM(require("path"), 1);
17663
+ import_crypto2 = __toESM(require("crypto"), 1);
17664
+ init_src();
17665
+ DEFAULT_REGISTRY_URL2 = "https://raw.githubusercontent.com/learn-rudi/registry/main/index.json";
17666
+ RUNTIMES_DOWNLOAD_BASE2 = "https://github.com/learn-rudi/registry/releases/download";
17667
+ CACHE_TTL2 = 24 * 60 * 60 * 1e3;
17668
+ PACKAGE_KINDS4 = ["stack", "prompt", "runtime", "binary", "agent"];
17669
+ KIND_PLURALS2 = {
17670
+ binary: "binaries"
17671
+ };
17672
+ GITHUB_RAW_BASE2 = "https://raw.githubusercontent.com/learn-rudi/registry/main";
17673
+ RUNTIMES_RELEASE_VERSION2 = "v1.0.0";
17674
+ }
17675
+ });
17676
+
17677
+ // packages/utils/src/args.js
17678
+ function parseArgs(argv) {
17679
+ const flags = {};
17680
+ const args = [];
17681
+ let command = null;
17682
+ for (let i = 0; i < argv.length; i++) {
17683
+ const arg = argv[i];
17684
+ if (arg.startsWith("--")) {
17685
+ const eqIndex = arg.indexOf("=");
17686
+ if (eqIndex !== -1) {
17687
+ const key = arg.slice(2, eqIndex);
17688
+ const value = arg.slice(eqIndex + 1);
17689
+ flags[key] = value;
17690
+ } else {
17691
+ const key = arg.slice(2);
17692
+ const nextArg = argv[i + 1];
17693
+ if (nextArg && !nextArg.startsWith("-")) {
17694
+ flags[key] = nextArg;
17695
+ i++;
17696
+ } else {
17697
+ flags[key] = true;
17698
+ }
17699
+ }
17700
+ } else if (arg.startsWith("-") && arg.length > 1) {
17701
+ const chars = arg.slice(1);
17702
+ for (const char of chars) {
17703
+ flags[char] = true;
17704
+ }
17705
+ } else if (!command) {
17706
+ command = arg;
17707
+ } else {
17708
+ args.push(arg);
17709
+ }
17710
+ }
17711
+ return { command, args, flags };
17712
+ }
17713
+ function formatBytes(bytes) {
17714
+ if (bytes === 0) return "0 B";
17715
+ const k = 1024;
17716
+ const sizes = ["B", "KB", "MB", "GB"];
17717
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
17718
+ return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
17719
+ }
17720
+ function formatDuration(ms) {
17721
+ if (ms < 1e3) return `${ms}ms`;
17722
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
17723
+ const mins = Math.floor(ms / 6e4);
17724
+ const secs = Math.floor(ms % 6e4 / 1e3);
17725
+ return `${mins}m ${secs}s`;
17726
+ }
17727
+
17728
+ // packages/utils/src/help.js
17729
+ function printVersion(version) {
17730
+ console.log(`rudi v${version}`);
17731
+ }
17732
+ function printHelp(topic) {
17733
+ if (topic) {
17734
+ printCommandHelp(topic);
17735
+ return;
16894
17736
  }
16895
17737
  console.log(`
16896
17738
  rudi - RUDI CLI
@@ -17333,11 +18175,12 @@ Total: ${totalCount} package(s) available`);
17333
18175
 
17334
18176
  // src/commands/install.js
17335
18177
  var fs13 = __toESM(require("fs/promises"), 1);
18178
+ var fsSync = __toESM(require("fs"), 1);
17336
18179
  var path13 = __toESM(require("path"), 1);
17337
18180
  var import_child_process4 = require("child_process");
17338
18181
  init_src3();
17339
18182
 
17340
- // node_modules/.pnpm/@learnrudi+secrets@1.0.1/node_modules/@learnrudi/secrets/src/index.js
18183
+ // packages/secrets/src/index.js
17341
18184
  var fs10 = __toESM(require("fs"), 1);
17342
18185
  var path10 = __toESM(require("path"), 1);
17343
18186
  init_src();
@@ -17418,7 +18261,7 @@ function getStorageInfo() {
17418
18261
  };
17419
18262
  }
17420
18263
 
17421
- // node_modules/.pnpm/@learnrudi+mcp@1.0.0/node_modules/@learnrudi/mcp/src/agents.js
18264
+ // packages/mcp/src/agents.js
17422
18265
  var import_fs8 = __toESM(require("fs"), 1);
17423
18266
  var import_path8 = __toESM(require("path"), 1);
17424
18267
  var import_os2 = __toESM(require("os"), 1);
@@ -17593,7 +18436,7 @@ function getMcpServerSummary() {
17593
18436
  return summary;
17594
18437
  }
17595
18438
 
17596
- // node_modules/.pnpm/@learnrudi+mcp@1.0.0/node_modules/@learnrudi/mcp/src/registry.js
18439
+ // packages/mcp/src/registry.js
17597
18440
  var fs12 = __toESM(require("fs/promises"), 1);
17598
18441
  var path12 = __toESM(require("path"), 1);
17599
18442
  var os3 = __toESM(require("os"), 1);
@@ -17812,13 +18655,13 @@ function getBundledBinary(runtime, binary) {
17812
18655
  const rudiHome = process.env.RUDI_HOME || path13.join(process.env.HOME || process.env.USERPROFILE, ".rudi");
17813
18656
  if (runtime === "node") {
17814
18657
  const npmPath = platform === "win32" ? path13.join(rudiHome, "runtimes", "node", "npm.cmd") : path13.join(rudiHome, "runtimes", "node", "bin", "npm");
17815
- if (require("fs").existsSync(npmPath)) {
18658
+ if (fsSync.existsSync(npmPath)) {
17816
18659
  return npmPath;
17817
18660
  }
17818
18661
  }
17819
18662
  if (runtime === "python") {
17820
18663
  const pipPath = platform === "win32" ? path13.join(rudiHome, "runtimes", "python", "Scripts", "pip.exe") : path13.join(rudiHome, "runtimes", "python", "bin", "pip3");
17821
- if (require("fs").existsSync(pipPath)) {
18664
+ if (fsSync.existsSync(pipPath)) {
17822
18665
  return pipPath;
17823
18666
  }
17824
18667
  }
@@ -17928,8 +18771,8 @@ function validateStackEntryPoint(stackPath, manifest) {
17928
18771
  if (arg.startsWith("-")) continue;
17929
18772
  const looksLikeFile = fileExtensions.some((ext) => arg.endsWith(ext)) || arg.includes("/");
17930
18773
  if (!looksLikeFile) continue;
17931
- const entryPath = require("path").join(stackPath, arg);
17932
- if (!require("fs").existsSync(entryPath)) {
18774
+ const entryPath = path13.join(stackPath, arg);
18775
+ if (!fsSync.existsSync(entryPath)) {
17933
18776
  return { valid: false, error: `Entry point not found: ${arg}` };
17934
18777
  }
17935
18778
  return { valid: true };
@@ -17982,6 +18825,7 @@ async function cmdInstall(args, flags) {
17982
18825
  process.exit(1);
17983
18826
  }
17984
18827
  const force = flags.force || false;
18828
+ const allowScripts = flags["allow-scripts"] || flags.allowScripts || false;
17985
18829
  console.log(`Resolving ${pkgId}...`);
17986
18830
  try {
17987
18831
  const resolved = await resolvePackage(pkgId);
@@ -18043,6 +18887,7 @@ Or use --force to install anyway.`);
18043
18887
  Installing...`);
18044
18888
  const result = await installPackage(pkgId, {
18045
18889
  force,
18890
+ allowScripts,
18046
18891
  onProgress: (progress) => {
18047
18892
  if (progress.phase === "installing") {
18048
18893
  console.log(` Installing ${progress.package}...`);
@@ -18179,23 +19024,66 @@ Next steps:`);
18179
19024
  // src/commands/run.js
18180
19025
  init_src3();
18181
19026
 
18182
- // node_modules/.pnpm/@learnrudi+runner@1.0.1/node_modules/@learnrudi/runner/src/spawn.js
19027
+ // packages/runner/src/spawn.js
18183
19028
  var import_child_process5 = require("child_process");
18184
19029
  var import_path10 = __toESM(require("path"), 1);
18185
19030
  var import_fs10 = __toESM(require("fs"), 1);
18186
- init_src3();
18187
19031
 
18188
- // node_modules/.pnpm/@learnrudi+runner@1.0.1/node_modules/@learnrudi/runner/src/secrets.js
19032
+ // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/index.js
19033
+ init_src();
19034
+ init_src2();
19035
+
19036
+ // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/resolver.js
19037
+ init_src2();
19038
+ init_src();
19039
+
19040
+ // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/installer.js
19041
+ init_src();
19042
+ init_src2();
19043
+
19044
+ // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/lockfile.js
19045
+ var import_yaml2 = __toESM(require_dist(), 1);
19046
+ init_src();
19047
+
19048
+ // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/installer.js
19049
+ init_shims2();
19050
+
19051
+ // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/deps.js
19052
+ init_src();
19053
+ init_src2();
19054
+
19055
+ // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/rudi-config.js
19056
+ var path14 = __toESM(require("path"), 1);
19057
+ init_src();
19058
+ var RUDI_JSON_PATH2 = path14.join(RUDI_HOME, "rudi.json");
19059
+ var RUDI_JSON_TMP2 = path14.join(RUDI_HOME, "rudi.json.tmp");
19060
+ var RUDI_JSON_LOCK2 = path14.join(RUDI_HOME, "rudi.json.lock");
19061
+
19062
+ // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/tool-index.js
19063
+ var path15 = __toESM(require("path"), 1);
19064
+ init_src();
19065
+ var TOOL_INDEX_PATH2 = path15.join(RUDI_HOME, "cache", "tool-index.json");
19066
+ var TOOL_INDEX_TMP2 = path15.join(RUDI_HOME, "cache", "tool-index.json.tmp");
19067
+ var SECRETS_PATH2 = path15.join(RUDI_HOME, "secrets.json");
19068
+
19069
+ // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/index.js
19070
+ init_shims2();
19071
+
19072
+ // node_modules/.pnpm/@learnrudi+core@1.0.2/node_modules/@learnrudi/core/src/system-registry.js
19073
+ init_src();
19074
+ init_shims2();
19075
+
19076
+ // packages/runner/src/secrets.js
18189
19077
  var import_fs9 = __toESM(require("fs"), 1);
18190
19078
  var import_path9 = __toESM(require("path"), 1);
18191
19079
  var import_os3 = __toESM(require("os"), 1);
18192
- var SECRETS_PATH2 = import_path9.default.join(import_os3.default.homedir(), ".rudi", "secrets.json");
19080
+ var SECRETS_PATH3 = import_path9.default.join(import_os3.default.homedir(), ".rudi", "secrets.json");
18193
19081
  function loadSecrets3() {
18194
- if (!import_fs9.default.existsSync(SECRETS_PATH2)) {
19082
+ if (!import_fs9.default.existsSync(SECRETS_PATH3)) {
18195
19083
  return {};
18196
19084
  }
18197
19085
  try {
18198
- const content = import_fs9.default.readFileSync(SECRETS_PATH2, "utf-8");
19086
+ const content = import_fs9.default.readFileSync(SECRETS_PATH3, "utf-8");
18199
19087
  return JSON.parse(content);
18200
19088
  } catch {
18201
19089
  return {};
@@ -18246,17 +19134,17 @@ function redactSecrets(text, secrets) {
18246
19134
  return result;
18247
19135
  }
18248
19136
 
18249
- // node_modules/.pnpm/@learnrudi+runner@1.0.1/node_modules/@learnrudi/runner/src/spawn.js
19137
+ // packages/runner/src/spawn.js
18250
19138
  async function runStack(id, options = {}) {
18251
19139
  const { inputs = {}, cwd, env = {}, onStdout, onStderr, onExit, signal } = options;
18252
19140
  const startTime = Date.now();
18253
19141
  const packagePath = getPackagePath(id);
18254
19142
  const manifestPath = import_path10.default.join(packagePath, "manifest.json");
18255
- const { default: fs32 } = await import("fs");
18256
- if (!fs32.existsSync(manifestPath)) {
19143
+ const { default: fs35 } = await import("fs");
19144
+ if (!fs35.existsSync(manifestPath)) {
18257
19145
  throw new Error(`Stack manifest not found: ${id}`);
18258
19146
  }
18259
- const manifest = JSON.parse(fs32.readFileSync(manifestPath, "utf-8"));
19147
+ const manifest = JSON.parse(fs35.readFileSync(manifestPath, "utf-8"));
18260
19148
  const { command, args } = resolveCommandFromManifest(manifest, packagePath);
18261
19149
  const secrets = await getSecrets(manifest.requires?.secrets || []);
18262
19150
  const runEnv = {
@@ -18362,8 +19250,8 @@ function resolveRelativePath(value, basePath) {
18362
19250
  return value;
18363
19251
  }
18364
19252
 
18365
- // node_modules/.pnpm/@learnrudi+manifest@1.0.0/node_modules/@learnrudi/manifest/src/stack.js
18366
- var import_yaml2 = __toESM(require_dist(), 1);
19253
+ // packages/manifest/src/stack.js
19254
+ var import_yaml3 = __toESM(require_dist(), 1);
18367
19255
  var import_fs11 = __toESM(require("fs"), 1);
18368
19256
  var import_path11 = __toESM(require("path"), 1);
18369
19257
  function parseStackManifest(filePath) {
@@ -18371,7 +19259,7 @@ function parseStackManifest(filePath) {
18371
19259
  return parseStackYaml(content, filePath);
18372
19260
  }
18373
19261
  function parseStackYaml(content, source = "stack.yaml") {
18374
- const raw = (0, import_yaml2.parse)(content);
19262
+ const raw = (0, import_yaml3.parse)(content);
18375
19263
  if (!raw || typeof raw !== "object") {
18376
19264
  throw new Error(`Invalid stack manifest in ${source}: expected object`);
18377
19265
  }
@@ -18493,13 +19381,13 @@ function findStackManifest(dir) {
18493
19381
  return null;
18494
19382
  }
18495
19383
 
18496
- // node_modules/.pnpm/@learnrudi+manifest@1.0.0/node_modules/@learnrudi/manifest/src/prompt.js
18497
- var import_yaml3 = __toESM(require_dist(), 1);
18498
-
18499
- // node_modules/.pnpm/@learnrudi+manifest@1.0.0/node_modules/@learnrudi/manifest/src/runtime.js
19384
+ // packages/manifest/src/prompt.js
18500
19385
  var import_yaml4 = __toESM(require_dist(), 1);
18501
19386
 
18502
- // node_modules/.pnpm/@learnrudi+manifest@1.0.0/node_modules/@learnrudi/manifest/src/validate.js
19387
+ // packages/manifest/src/runtime.js
19388
+ var import_yaml5 = __toESM(require_dist(), 1);
19389
+
19390
+ // packages/manifest/src/validate.js
18503
19391
  var import_ajv = __toESM(require_ajv(), 1);
18504
19392
  var import_ajv_formats = __toESM(require_dist2(), 1);
18505
19393
  var ajv = new import_ajv.default({ allErrors: true, strict: false });
@@ -19235,13 +20123,13 @@ function promptSecret(prompt) {
19235
20123
  var import_fs14 = require("fs");
19236
20124
  var import_path14 = require("path");
19237
20125
 
19238
- // node_modules/.pnpm/@learnrudi+db@1.0.2/node_modules/@learnrudi/db/src/index.js
20126
+ // packages/db/src/index.js
19239
20127
  var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
19240
20128
  var import_path13 = __toESM(require("path"), 1);
19241
20129
  var import_fs13 = __toESM(require("fs"), 1);
19242
20130
  init_src();
19243
20131
 
19244
- // node_modules/.pnpm/@learnrudi+db@1.0.2/node_modules/@learnrudi/db/src/schema.js
20132
+ // packages/db/src/schema.js
19245
20133
  var SCHEMA_VERSION = 5;
19246
20134
  var SCHEMA_SQL = `
19247
20135
  -- Schema version tracking
@@ -19801,7 +20689,7 @@ function seedModelPricing(db2) {
19801
20689
  console.log(` Seeded ${pricingData.length} model pricing entries`);
19802
20690
  }
19803
20691
 
19804
- // node_modules/.pnpm/@learnrudi+db@1.0.2/node_modules/@learnrudi/db/src/search.js
20692
+ // packages/db/src/search.js
19805
20693
  function search(query, options = {}) {
19806
20694
  const { limit = 20, provider, sessionId, offset = 0 } = options;
19807
20695
  const db2 = getDb();
@@ -19888,7 +20776,7 @@ function searchFallback(query, options = {}) {
19888
20776
  return db2.prepare(sql).all(...params);
19889
20777
  }
19890
20778
 
19891
- // node_modules/.pnpm/@learnrudi+db@1.0.2/node_modules/@learnrudi/db/src/stats.js
20779
+ // packages/db/src/stats.js
19892
20780
  function getStats() {
19893
20781
  const db2 = getDb();
19894
20782
  const totals = db2.prepare(`
@@ -19995,7 +20883,7 @@ function getToolsUsage(db2) {
19995
20883
  return Object.entries(toolCounts).sort((a, b) => b[1] - a[1]).slice(0, 20).map(([name, count]) => ({ name, count }));
19996
20884
  }
19997
20885
 
19998
- // node_modules/.pnpm/@learnrudi+db@1.0.2/node_modules/@learnrudi/db/src/logs.js
20886
+ // packages/db/src/logs.js
19999
20887
  function queryLogs(options = {}) {
20000
20888
  const db2 = getDb();
20001
20889
  const {
@@ -20139,11 +21027,11 @@ function getBeforeCrashLogs() {
20139
21027
  return getRecentLogs(3e4);
20140
21028
  }
20141
21029
 
20142
- // node_modules/.pnpm/@learnrudi+db@1.0.2/node_modules/@learnrudi/db/src/import.js
21030
+ // packages/db/src/import.js
20143
21031
  init_src();
20144
21032
  var RUDI_HOME2 = PATHS.home;
20145
21033
 
20146
- // node_modules/.pnpm/@learnrudi+db@1.0.2/node_modules/@learnrudi/db/src/index.js
21034
+ // packages/db/src/index.js
20147
21035
  var DB_PATH = PATHS.dbFile;
20148
21036
  var db = null;
20149
21037
  function getDb(options = {}) {
@@ -20569,7 +21457,7 @@ function dbTables(flags) {
20569
21457
  var import_fs15 = require("fs");
20570
21458
  var import_path15 = require("path");
20571
21459
  var import_os4 = require("os");
20572
- var import_crypto2 = require("crypto");
21460
+ var import_crypto = require("crypto");
20573
21461
  var PROVIDERS = {
20574
21462
  claude: {
20575
21463
  name: "Claude Code",
@@ -20728,7 +21616,7 @@ async function importSessions(args, flags) {
20728
21616
  try {
20729
21617
  const nowIso = (/* @__PURE__ */ new Date()).toISOString();
20730
21618
  insertStmt.run(
20731
- (0, import_crypto2.randomUUID)(),
21619
+ (0, import_crypto.randomUUID)(),
20732
21620
  providerKey,
20733
21621
  sessionId,
20734
21622
  nowIso,
@@ -21147,13 +22035,115 @@ async function cmdHome(args, flags) {
21147
22035
  }
21148
22036
 
21149
22037
  // src/commands/init.js
21150
- var import_fs18 = __toESM(require("fs"), 1);
21151
- var import_path17 = __toESM(require("path"), 1);
22038
+ var import_fs20 = __toESM(require("fs"), 1);
22039
+ var import_path19 = __toESM(require("path"), 1);
21152
22040
  var import_promises = require("stream/promises");
21153
- var import_fs19 = require("fs");
22041
+ var import_fs21 = require("fs");
21154
22042
  var import_child_process6 = require("child_process");
21155
- init_src();
21156
- init_src2();
22043
+
22044
+ // packages/env/src/index.js
22045
+ var import_path17 = __toESM(require("path"), 1);
22046
+ var import_os5 = __toESM(require("os"), 1);
22047
+ var import_fs18 = __toESM(require("fs"), 1);
22048
+ var RUDI_HOME3 = import_path17.default.join(import_os5.default.homedir(), ".rudi");
22049
+ var PATHS2 = {
22050
+ // Root
22051
+ home: RUDI_HOME3,
22052
+ // Installed packages - shared with Studio for unified discovery
22053
+ packages: import_path17.default.join(RUDI_HOME3, "packages"),
22054
+ stacks: import_path17.default.join(RUDI_HOME3, "stacks"),
22055
+ // Shared with Studio
22056
+ prompts: import_path17.default.join(RUDI_HOME3, "prompts"),
22057
+ // Shared with Studio
22058
+ // Runtimes (interpreters: node, python, deno, bun)
22059
+ runtimes: import_path17.default.join(RUDI_HOME3, "runtimes"),
22060
+ // Binaries (utility CLIs: ffmpeg, imagemagick, ripgrep, etc.)
22061
+ binaries: import_path17.default.join(RUDI_HOME3, "binaries"),
22062
+ // Agents (AI CLI tools: claude, codex, gemini, copilot, ollama)
22063
+ agents: import_path17.default.join(RUDI_HOME3, "agents"),
22064
+ // Runtime binaries (content-addressed)
22065
+ store: import_path17.default.join(RUDI_HOME3, "store"),
22066
+ // Shims (symlinks to store/)
22067
+ bins: import_path17.default.join(RUDI_HOME3, "bins"),
22068
+ // Lockfiles
22069
+ locks: import_path17.default.join(RUDI_HOME3, "locks"),
22070
+ // Secrets (OS Keychain preferred, encrypted file fallback)
22071
+ vault: import_path17.default.join(RUDI_HOME3, "vault"),
22072
+ // Database (shared with Studio)
22073
+ db: RUDI_HOME3,
22074
+ dbFile: import_path17.default.join(RUDI_HOME3, "rudi.db"),
22075
+ // Cache
22076
+ cache: import_path17.default.join(RUDI_HOME3, "cache"),
22077
+ registryCache: import_path17.default.join(RUDI_HOME3, "cache", "registry.json"),
22078
+ // Config
22079
+ config: import_path17.default.join(RUDI_HOME3, "config.json"),
22080
+ // Logs
22081
+ logs: import_path17.default.join(RUDI_HOME3, "logs")
22082
+ };
22083
+ function getPlatformArch2() {
22084
+ const platform = import_os5.default.platform();
22085
+ const arch = import_os5.default.arch();
22086
+ const normalizedArch = arch === "x64" ? "x64" : arch === "arm64" ? "arm64" : arch;
22087
+ return `${platform}-${normalizedArch}`;
22088
+ }
22089
+ function ensureDirectories2() {
22090
+ const dirs = [
22091
+ PATHS2.stacks,
22092
+ // MCP servers (google-ai, notion-workspace, etc.)
22093
+ PATHS2.prompts,
22094
+ // Reusable prompts
22095
+ PATHS2.runtimes,
22096
+ // Language runtimes (node, python, bun, deno)
22097
+ PATHS2.binaries,
22098
+ // Utility binaries (ffmpeg, git, jq, etc.)
22099
+ PATHS2.agents,
22100
+ // AI CLI agents (claude, codex, gemini, copilot)
22101
+ PATHS2.bins,
22102
+ // Shims directory (Studio only)
22103
+ PATHS2.locks,
22104
+ // Lock files
22105
+ PATHS2.db,
22106
+ // Database directory
22107
+ PATHS2.cache
22108
+ // Registry cache
22109
+ ];
22110
+ for (const dir of dirs) {
22111
+ if (!import_fs18.default.existsSync(dir)) {
22112
+ import_fs18.default.mkdirSync(dir, { recursive: true });
22113
+ }
22114
+ }
22115
+ }
22116
+ var PACKAGE_KINDS3 = ["stack", "prompt", "runtime", "binary", "agent"];
22117
+ function parsePackageId2(id) {
22118
+ const match = id.match(/^(stack|prompt|runtime|binary|agent|npm):(.+)$/);
22119
+ if (!match) {
22120
+ throw new Error(`Invalid package ID: ${id} (expected format: kind:name, where kind is one of: ${PACKAGE_KINDS3.join(", ")}, npm)`);
22121
+ }
22122
+ return [match[1], match[2]];
22123
+ }
22124
+ function getPackagePath2(id) {
22125
+ const [kind, name] = parsePackageId2(id);
22126
+ switch (kind) {
22127
+ case "stack":
22128
+ return import_path17.default.join(PATHS2.stacks, name);
22129
+ case "prompt":
22130
+ return import_path17.default.join(PATHS2.prompts, `${name}.md`);
22131
+ case "runtime":
22132
+ return import_path17.default.join(PATHS2.runtimes, name);
22133
+ case "binary":
22134
+ return import_path17.default.join(PATHS2.binaries, name);
22135
+ case "agent":
22136
+ return import_path17.default.join(PATHS2.agents, name);
22137
+ case "npm":
22138
+ const sanitized = name.replace(/\//g, "__").replace(/^@/, "");
22139
+ return import_path17.default.join(PATHS2.binaries, "npm", sanitized);
22140
+ default:
22141
+ throw new Error(`Unknown package kind: ${kind}`);
22142
+ }
22143
+ }
22144
+
22145
+ // src/commands/init.js
22146
+ init_src4();
21157
22147
  var RELEASES_BASE = "https://github.com/learn-rudi/registry/releases/download/v1.0.0";
21158
22148
  var BUNDLED_RUNTIMES = ["node", "python"];
21159
22149
  var ESSENTIAL_BINARIES = ["sqlite", "ripgrep"];
@@ -21165,25 +22155,25 @@ async function cmdInit(args, flags) {
21165
22155
  console.log("\u2550".repeat(60));
21166
22156
  console.log("RUDI Initialization");
21167
22157
  console.log("\u2550".repeat(60));
21168
- console.log(`Home: ${PATHS.home}`);
22158
+ console.log(`Home: ${PATHS2.home}`);
21169
22159
  console.log();
21170
22160
  }
21171
22161
  const actions = { created: [], skipped: [], failed: [] };
21172
22162
  if (!quiet) console.log("1. Checking directory structure...");
21173
- ensureDirectories();
22163
+ ensureDirectories2();
21174
22164
  const dirs = [
21175
- PATHS.stacks,
21176
- PATHS.prompts,
21177
- PATHS.runtimes,
21178
- PATHS.binaries,
21179
- PATHS.agents,
21180
- PATHS.cache,
21181
- import_path17.default.join(PATHS.home, "shims")
22165
+ PATHS2.stacks,
22166
+ PATHS2.prompts,
22167
+ PATHS2.runtimes,
22168
+ PATHS2.binaries,
22169
+ PATHS2.agents,
22170
+ PATHS2.cache,
22171
+ import_path19.default.join(PATHS2.home, "shims")
21182
22172
  ];
21183
22173
  for (const dir of dirs) {
21184
- const dirName = import_path17.default.basename(dir);
21185
- if (!import_fs18.default.existsSync(dir)) {
21186
- import_fs18.default.mkdirSync(dir, { recursive: true });
22174
+ const dirName = import_path19.default.basename(dir);
22175
+ if (!import_fs20.default.existsSync(dir)) {
22176
+ import_fs20.default.mkdirSync(dir, { recursive: true });
21187
22177
  actions.created.push(`dir:${dirName}`);
21188
22178
  if (!quiet) console.log(` + ${dirName}/ (created)`);
21189
22179
  } else {
@@ -21193,8 +22183,8 @@ async function cmdInit(args, flags) {
21193
22183
  }
21194
22184
  if (!skipDownloads) {
21195
22185
  if (!quiet) console.log("\n2. Checking runtimes...");
21196
- const index = await fetchIndex();
21197
- const platform = getPlatformArch();
22186
+ const index = await fetchIndex2();
22187
+ const platform = getPlatformArch2();
21198
22188
  for (const runtimeName of BUNDLED_RUNTIMES) {
21199
22189
  const runtime = index.packages?.runtimes?.official?.find(
21200
22190
  (r) => r.id === `runtime:${runtimeName}` || r.id === runtimeName
@@ -21204,14 +22194,14 @@ async function cmdInit(args, flags) {
21204
22194
  if (!quiet) console.log(` \u26A0 ${runtimeName}: not found in registry`);
21205
22195
  continue;
21206
22196
  }
21207
- const destPath = import_path17.default.join(PATHS.runtimes, runtimeName);
21208
- if (import_fs18.default.existsSync(destPath) && !force) {
22197
+ const destPath = import_path19.default.join(PATHS2.runtimes, runtimeName);
22198
+ if (import_fs20.default.existsSync(destPath) && !force) {
21209
22199
  actions.skipped.push(`runtime:${runtimeName}`);
21210
22200
  if (!quiet) console.log(` \u2713 ${runtimeName}: already installed`);
21211
22201
  continue;
21212
22202
  }
21213
22203
  try {
21214
- await downloadRuntime2(runtime, runtimeName, destPath, platform);
22204
+ await downloadRuntime3(runtime, runtimeName, destPath, platform);
21215
22205
  actions.created.push(`runtime:${runtimeName}`);
21216
22206
  if (!quiet) console.log(` + ${runtimeName}: installed`);
21217
22207
  } catch (error) {
@@ -21229,8 +22219,8 @@ async function cmdInit(args, flags) {
21229
22219
  if (!quiet) console.log(` \u26A0 ${binaryName}: not found in registry`);
21230
22220
  continue;
21231
22221
  }
21232
- const destPath = import_path17.default.join(PATHS.binaries, binaryName);
21233
- if (import_fs18.default.existsSync(destPath) && !force) {
22222
+ const destPath = import_path19.default.join(PATHS2.binaries, binaryName);
22223
+ if (import_fs20.default.existsSync(destPath) && !force) {
21234
22224
  actions.skipped.push(`binary:${binaryName}`);
21235
22225
  if (!quiet) console.log(` \u2713 ${binaryName}: already installed`);
21236
22226
  continue;
@@ -21248,14 +22238,14 @@ async function cmdInit(args, flags) {
21248
22238
  if (!quiet) console.log("\n2-3. Skipping downloads (--skip-downloads)");
21249
22239
  }
21250
22240
  if (!quiet) console.log("\n4. Updating shims...");
21251
- const shimsDir = import_path17.default.join(PATHS.home, "shims");
22241
+ const shimsDir = import_path19.default.join(PATHS2.home, "shims");
21252
22242
  const shimCount = await createShims(shimsDir, quiet);
21253
22243
  if (shimCount > 0) {
21254
22244
  actions.created.push(`shims:${shimCount}`);
21255
22245
  }
21256
22246
  if (!quiet) console.log("\n5. Checking database...");
21257
- const dbPath = import_path17.default.join(PATHS.home, "rudi.db");
21258
- const dbExists = import_fs18.default.existsSync(dbPath);
22247
+ const dbPath = import_path19.default.join(PATHS2.home, "rudi.db");
22248
+ const dbExists = import_fs20.default.existsSync(dbPath);
21259
22249
  try {
21260
22250
  const result = initSchema();
21261
22251
  if (dbExists) {
@@ -21270,14 +22260,14 @@ async function cmdInit(args, flags) {
21270
22260
  if (!quiet) console.log(` \u2717 Database error: ${error.message}`);
21271
22261
  }
21272
22262
  if (!quiet) console.log("\n6. Checking settings...");
21273
- const settingsPath = import_path17.default.join(PATHS.home, "settings.json");
21274
- if (!import_fs18.default.existsSync(settingsPath)) {
22263
+ const settingsPath = import_path19.default.join(PATHS2.home, "settings.json");
22264
+ if (!import_fs20.default.existsSync(settingsPath)) {
21275
22265
  const settings = {
21276
22266
  version: "1.0.0",
21277
22267
  initialized: (/* @__PURE__ */ new Date()).toISOString(),
21278
22268
  theme: "system"
21279
22269
  };
21280
- import_fs18.default.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
22270
+ import_fs20.default.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
21281
22271
  actions.created.push("settings");
21282
22272
  if (!quiet) console.log(" + settings.json created");
21283
22273
  } else {
@@ -21293,7 +22283,7 @@ async function cmdInit(args, flags) {
21293
22283
  }
21294
22284
  console.log("\u2550".repeat(60));
21295
22285
  if (actions.created.includes("settings")) {
21296
- const shimsPath = import_path17.default.join(PATHS.home, "shims");
22286
+ const shimsPath = import_path19.default.join(PATHS2.home, "shims");
21297
22287
  console.log("\nAdd to your shell profile (~/.zshrc or ~/.bashrc):");
21298
22288
  console.log(` export PATH="${shimsPath}:$PATH"`);
21299
22289
  console.log("\nThen run:");
@@ -21303,7 +22293,7 @@ async function cmdInit(args, flags) {
21303
22293
  }
21304
22294
  return actions;
21305
22295
  }
21306
- async function downloadRuntime2(runtime, name, destPath, platform) {
22296
+ async function downloadRuntime3(runtime, name, destPath, platform) {
21307
22297
  let url;
21308
22298
  if (runtime.upstream?.[platform]) {
21309
22299
  url = runtime.upstream[platform];
@@ -21326,15 +22316,15 @@ async function downloadBinary(binary, name, destPath, platform) {
21326
22316
  await downloadAndExtract(url, destPath, name, binary.extract);
21327
22317
  }
21328
22318
  async function downloadAndExtract(url, destPath, name, extractConfig) {
21329
- const tempFile = import_path17.default.join(PATHS.cache, `${name}-download.tar.gz`);
22319
+ const tempFile = import_path19.default.join(PATHS2.cache, `${name}-download.tar.gz`);
21330
22320
  const response = await fetch(url);
21331
22321
  if (!response.ok) {
21332
22322
  throw new Error(`HTTP ${response.status}`);
21333
22323
  }
21334
- if (!import_fs18.default.existsSync(destPath)) {
21335
- import_fs18.default.mkdirSync(destPath, { recursive: true });
22324
+ if (!import_fs20.default.existsSync(destPath)) {
22325
+ import_fs20.default.mkdirSync(destPath, { recursive: true });
21336
22326
  }
21337
- const fileStream = (0, import_fs19.createWriteStream)(tempFile);
22327
+ const fileStream = (0, import_fs21.createWriteStream)(tempFile);
21338
22328
  await (0, import_promises.pipeline)(response.body, fileStream);
21339
22329
  try {
21340
22330
  (0, import_child_process6.execSync)(`tar -xzf "${tempFile}" -C "${destPath}" --strip-components=1`, {
@@ -21343,7 +22333,7 @@ async function downloadAndExtract(url, destPath, name, extractConfig) {
21343
22333
  } catch {
21344
22334
  (0, import_child_process6.execSync)(`tar -xzf "${tempFile}" -C "${destPath}"`, { stdio: "pipe" });
21345
22335
  }
21346
- import_fs18.default.unlinkSync(tempFile);
22336
+ import_fs20.default.unlinkSync(tempFile);
21347
22337
  }
21348
22338
  async function createShims(shimsDir, quiet = false) {
21349
22339
  const shims = [];
@@ -21362,17 +22352,17 @@ async function createShims(shimsDir, quiet = false) {
21362
22352
  ripgrep: "binaries/ripgrep/rg"
21363
22353
  };
21364
22354
  for (const [shimName, targetPath] of Object.entries(runtimeShims)) {
21365
- const fullTarget = import_path17.default.join(PATHS.home, targetPath);
21366
- const shimPath = import_path17.default.join(shimsDir, shimName);
21367
- if (import_fs18.default.existsSync(fullTarget)) {
22355
+ const fullTarget = import_path19.default.join(PATHS2.home, targetPath);
22356
+ const shimPath = import_path19.default.join(shimsDir, shimName);
22357
+ if (import_fs20.default.existsSync(fullTarget)) {
21368
22358
  createShim(shimPath, fullTarget);
21369
22359
  shims.push(shimName);
21370
22360
  }
21371
22361
  }
21372
22362
  for (const [shimName, targetPath] of Object.entries(binaryShims)) {
21373
- const fullTarget = import_path17.default.join(PATHS.home, targetPath);
21374
- const shimPath = import_path17.default.join(shimsDir, shimName);
21375
- if (import_fs18.default.existsSync(fullTarget)) {
22363
+ const fullTarget = import_path19.default.join(PATHS2.home, targetPath);
22364
+ const shimPath = import_path19.default.join(shimsDir, shimName);
22365
+ if (import_fs20.default.existsSync(fullTarget)) {
21376
22366
  createShim(shimPath, fullTarget);
21377
22367
  shims.push(shimName);
21378
22368
  }
@@ -21387,18 +22377,17 @@ async function createShims(shimsDir, quiet = false) {
21387
22377
  return shims.length;
21388
22378
  }
21389
22379
  function createShim(shimPath, targetPath) {
21390
- if (import_fs18.default.existsSync(shimPath)) {
21391
- import_fs18.default.unlinkSync(shimPath);
22380
+ if (import_fs20.default.existsSync(shimPath)) {
22381
+ import_fs20.default.unlinkSync(shimPath);
21392
22382
  }
21393
- import_fs18.default.symlinkSync(targetPath, shimPath);
22383
+ import_fs20.default.symlinkSync(targetPath, shimPath);
21394
22384
  }
21395
22385
 
21396
22386
  // src/commands/update.js
21397
- var import_fs20 = __toESM(require("fs"), 1);
21398
- var import_path18 = __toESM(require("path"), 1);
22387
+ var import_fs22 = __toESM(require("fs"), 1);
22388
+ var import_path20 = __toESM(require("path"), 1);
21399
22389
  var import_child_process7 = require("child_process");
21400
- init_src();
21401
- init_src2();
22390
+ init_src4();
21402
22391
  async function cmdUpdate(args, flags) {
21403
22392
  const pkgId = args[0];
21404
22393
  if (!pkgId) {
@@ -21419,12 +22408,12 @@ async function cmdUpdate(args, flags) {
21419
22408
  }
21420
22409
  }
21421
22410
  async function updatePackage2(pkgId, flags) {
21422
- const [kind, name] = parsePackageId(pkgId);
21423
- const installPath = getPackagePath(pkgId);
21424
- if (!import_fs20.default.existsSync(installPath)) {
22411
+ const [kind, name] = parsePackageId2(pkgId);
22412
+ const installPath = getPackagePath2(pkgId);
22413
+ if (!import_fs22.default.existsSync(installPath)) {
21425
22414
  return { success: false, error: "Package not installed" };
21426
22415
  }
21427
- const pkg = await getPackage(pkgId);
22416
+ const pkg = await getPackage2(pkgId);
21428
22417
  if (!pkg) {
21429
22418
  return { success: false, error: "Package not found in registry" };
21430
22419
  }
@@ -21444,7 +22433,7 @@ async function updatePackage2(pkgId, flags) {
21444
22433
  }
21445
22434
  if (pkg.pipPackage) {
21446
22435
  try {
21447
- const venvPip = import_path18.default.join(installPath, "venv", "bin", "pip");
22436
+ const venvPip = import_path20.default.join(installPath, "venv", "bin", "pip");
21448
22437
  (0, import_child_process7.execSync)(`"${venvPip}" install --upgrade ${pkg.pipPackage}`, {
21449
22438
  stdio: flags.verbose ? "inherit" : "pipe"
21450
22439
  });
@@ -21460,9 +22449,9 @@ async function updatePackage2(pkgId, flags) {
21460
22449
  }
21461
22450
  if (kind === "runtime" && !pkg.npmPackage && !pkg.pipPackage) {
21462
22451
  try {
21463
- const { downloadRuntime: downloadRuntime3 } = await Promise.resolve().then(() => (init_src2(), src_exports));
21464
- import_fs20.default.rmSync(installPath, { recursive: true, force: true });
21465
- await downloadRuntime3(name, pkg.version || "latest", installPath, {
22452
+ const { downloadRuntime: downloadRuntime4 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
22453
+ import_fs22.default.rmSync(installPath, { recursive: true, force: true });
22454
+ await downloadRuntime4(name, pkg.version || "latest", installPath, {
21466
22455
  onProgress: (p) => {
21467
22456
  if (flags.verbose) console.log(` ${p.phase}...`);
21468
22457
  }
@@ -21480,9 +22469,9 @@ async function updateAll2(flags) {
21480
22469
  let updated = 0;
21481
22470
  let failed = 0;
21482
22471
  for (const kind of kinds) {
21483
- const dir = kind === "runtime" ? PATHS.runtimes : kind === "stack" ? PATHS.stacks : PATHS.prompts;
21484
- if (!import_fs20.default.existsSync(dir)) continue;
21485
- const entries = import_fs20.default.readdirSync(dir, { withFileTypes: true });
22472
+ const dir = kind === "runtime" ? PATHS2.runtimes : kind === "stack" ? PATHS2.stacks : PATHS2.prompts;
22473
+ if (!import_fs22.default.existsSync(dir)) continue;
22474
+ const entries = import_fs22.default.readdirSync(dir, { withFileTypes: true });
21486
22475
  for (const entry of entries) {
21487
22476
  if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
21488
22477
  const pkgId = `${kind}:${entry.name}`;
@@ -21501,14 +22490,14 @@ Updated ${updated} package(s)${failed > 0 ? `, ${failed} failed` : ""}`);
21501
22490
  }
21502
22491
  function getInstalledVersion(installPath, npmPackage) {
21503
22492
  try {
21504
- const pkgJsonPath = import_path18.default.join(installPath, "node_modules", npmPackage.replace("@", "").split("/")[0], "package.json");
21505
- if (import_fs20.default.existsSync(pkgJsonPath)) {
21506
- const pkgJson = JSON.parse(import_fs20.default.readFileSync(pkgJsonPath, "utf-8"));
22493
+ const pkgJsonPath = import_path20.default.join(installPath, "node_modules", npmPackage.replace("@", "").split("/")[0], "package.json");
22494
+ if (import_fs22.default.existsSync(pkgJsonPath)) {
22495
+ const pkgJson = JSON.parse(import_fs22.default.readFileSync(pkgJsonPath, "utf-8"));
21507
22496
  return pkgJson.version;
21508
22497
  }
21509
- const rootPkgPath = import_path18.default.join(installPath, "package.json");
21510
- if (import_fs20.default.existsSync(rootPkgPath)) {
21511
- const rootPkg = JSON.parse(import_fs20.default.readFileSync(rootPkgPath, "utf-8"));
22498
+ const rootPkgPath = import_path20.default.join(installPath, "package.json");
22499
+ if (import_fs22.default.existsSync(rootPkgPath)) {
22500
+ const rootPkg = JSON.parse(import_fs22.default.readFileSync(rootPkgPath, "utf-8"));
21512
22501
  const dep = rootPkg.dependencies?.[npmPackage];
21513
22502
  if (dep) return dep.replace(/[\^~]/, "");
21514
22503
  }
@@ -21517,20 +22506,20 @@ function getInstalledVersion(installPath, npmPackage) {
21517
22506
  return null;
21518
22507
  }
21519
22508
  function updateRuntimeMetadata(installPath, updates) {
21520
- const metaPath = import_path18.default.join(installPath, "runtime.json");
22509
+ const metaPath = import_path20.default.join(installPath, "runtime.json");
21521
22510
  try {
21522
22511
  let meta = {};
21523
- if (import_fs20.default.existsSync(metaPath)) {
21524
- meta = JSON.parse(import_fs20.default.readFileSync(metaPath, "utf-8"));
22512
+ if (import_fs22.default.existsSync(metaPath)) {
22513
+ meta = JSON.parse(import_fs22.default.readFileSync(metaPath, "utf-8"));
21525
22514
  }
21526
22515
  meta = { ...meta, ...updates };
21527
- import_fs20.default.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
22516
+ import_fs22.default.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
21528
22517
  } catch {
21529
22518
  }
21530
22519
  }
21531
22520
 
21532
22521
  // src/commands/logs.js
21533
- var import_fs21 = __toESM(require("fs"), 1);
22522
+ var import_fs23 = __toESM(require("fs"), 1);
21534
22523
  function parseTimeAgo(str) {
21535
22524
  const match = str.match(/^(\d+)([smhd])$/);
21536
22525
  if (!match) return null;
@@ -21630,7 +22619,7 @@ function exportLogs(logs, filepath, format) {
21630
22619
  });
21631
22620
  content = JSON.stringify(formatted, null, 2);
21632
22621
  }
21633
- import_fs21.default.writeFileSync(filepath, content, "utf-8");
22622
+ import_fs23.default.writeFileSync(filepath, content, "utf-8");
21634
22623
  return filepath;
21635
22624
  }
21636
22625
  function printStats(stats) {
@@ -21756,11 +22745,10 @@ async function handleLogsCommand(args, flags) {
21756
22745
  }
21757
22746
 
21758
22747
  // src/commands/which.js
21759
- var fs24 = __toESM(require("fs/promises"), 1);
21760
- var path22 = __toESM(require("path"), 1);
22748
+ var fs26 = __toESM(require("fs/promises"), 1);
22749
+ var path26 = __toESM(require("path"), 1);
21761
22750
  var import_child_process8 = require("child_process");
21762
22751
  init_src3();
21763
- init_src();
21764
22752
  async function cmdWhich(args, flags) {
21765
22753
  const stackId = args[0];
21766
22754
  if (!stackId) {
@@ -21827,7 +22815,7 @@ Installed stacks:`);
21827
22815
  if (runtimeInfo.entry) {
21828
22816
  console.log("");
21829
22817
  console.log("Run MCP server directly:");
21830
- const entryPath = path22.join(stackPath, runtimeInfo.entry);
22818
+ const entryPath = path26.join(stackPath, runtimeInfo.entry);
21831
22819
  if (runtimeInfo.runtime === "node") {
21832
22820
  console.log(` echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node ${entryPath}`);
21833
22821
  } else if (runtimeInfo.runtime === "python") {
@@ -21846,27 +22834,27 @@ Installed stacks:`);
21846
22834
  async function detectRuntime(stackPath) {
21847
22835
  const runtimes = ["node", "python"];
21848
22836
  for (const runtime of runtimes) {
21849
- const runtimePath = path22.join(stackPath, runtime);
22837
+ const runtimePath = path26.join(stackPath, runtime);
21850
22838
  try {
21851
- await fs24.access(runtimePath);
22839
+ await fs26.access(runtimePath);
21852
22840
  if (runtime === "node") {
21853
- const distEntry = path22.join(runtimePath, "dist", "index.js");
21854
- const srcEntry = path22.join(runtimePath, "src", "index.ts");
22841
+ const distEntry = path26.join(runtimePath, "dist", "index.js");
22842
+ const srcEntry = path26.join(runtimePath, "src", "index.ts");
21855
22843
  try {
21856
- await fs24.access(distEntry);
22844
+ await fs26.access(distEntry);
21857
22845
  return { runtime: "node", entry: `${runtime}/dist/index.js` };
21858
22846
  } catch {
21859
22847
  try {
21860
- await fs24.access(srcEntry);
22848
+ await fs26.access(srcEntry);
21861
22849
  return { runtime: "node", entry: `${runtime}/src/index.ts` };
21862
22850
  } catch {
21863
22851
  return { runtime: "node", entry: null };
21864
22852
  }
21865
22853
  }
21866
22854
  } else if (runtime === "python") {
21867
- const entry = path22.join(runtimePath, "src", "index.py");
22855
+ const entry = path26.join(runtimePath, "src", "index.py");
21868
22856
  try {
21869
- await fs24.access(entry);
22857
+ await fs26.access(entry);
21870
22858
  return { runtime: "python", entry: `${runtime}/src/index.py` };
21871
22859
  } catch {
21872
22860
  return { runtime: "python", entry: null };
@@ -21882,21 +22870,21 @@ async function checkAuth(stackPath, runtime) {
21882
22870
  const authFiles = [];
21883
22871
  let configured = false;
21884
22872
  if (runtime === "node" || runtime === "python") {
21885
- const runtimePath = path22.join(stackPath, runtime);
21886
- const tokenPath = path22.join(runtimePath, "token.json");
22873
+ const runtimePath = path26.join(stackPath, runtime);
22874
+ const tokenPath = path26.join(runtimePath, "token.json");
21887
22875
  try {
21888
- await fs24.access(tokenPath);
22876
+ await fs26.access(tokenPath);
21889
22877
  authFiles.push(`${runtime}/token.json`);
21890
22878
  configured = true;
21891
22879
  } catch {
21892
- const accountsPath = path22.join(runtimePath, "accounts");
22880
+ const accountsPath = path26.join(runtimePath, "accounts");
21893
22881
  try {
21894
- const accounts = await fs24.readdir(accountsPath);
22882
+ const accounts = await fs26.readdir(accountsPath);
21895
22883
  for (const account of accounts) {
21896
22884
  if (account.startsWith(".")) continue;
21897
- const accountTokenPath = path22.join(accountsPath, account, "token.json");
22885
+ const accountTokenPath = path26.join(accountsPath, account, "token.json");
21898
22886
  try {
21899
- await fs24.access(accountTokenPath);
22887
+ await fs26.access(accountTokenPath);
21900
22888
  authFiles.push(`${runtime}/accounts/${account}/token.json`);
21901
22889
  configured = true;
21902
22890
  } catch {
@@ -21906,9 +22894,9 @@ async function checkAuth(stackPath, runtime) {
21906
22894
  }
21907
22895
  }
21908
22896
  }
21909
- const envPath = path22.join(stackPath, ".env");
22897
+ const envPath = path26.join(stackPath, ".env");
21910
22898
  try {
21911
- const envContent = await fs24.readFile(envPath, "utf-8");
22899
+ const envContent = await fs26.readFile(envPath, "utf-8");
21912
22900
  const hasValues = envContent.split("\n").some((line) => {
21913
22901
  const trimmed = line.trim();
21914
22902
  if (!trimmed || trimmed.startsWith("#")) return false;
@@ -21952,11 +22940,10 @@ function checkIfRunning(stackName) {
21952
22940
  }
21953
22941
 
21954
22942
  // src/commands/auth.js
21955
- var fs25 = __toESM(require("fs/promises"), 1);
21956
- var path23 = __toESM(require("path"), 1);
22943
+ var fs27 = __toESM(require("fs/promises"), 1);
22944
+ var path27 = __toESM(require("path"), 1);
21957
22945
  var import_child_process9 = require("child_process");
21958
22946
  init_src3();
21959
- init_src();
21960
22947
  var net = __toESM(require("net"), 1);
21961
22948
  async function findAvailablePort(basePort = 3456) {
21962
22949
  for (let port = basePort; port < basePort + 10; port++) {
@@ -21986,26 +22973,26 @@ function isPortAvailable(port) {
21986
22973
  async function detectRuntime2(stackPath) {
21987
22974
  const runtimes = ["node", "python"];
21988
22975
  for (const runtime of runtimes) {
21989
- const runtimePath = path23.join(stackPath, runtime);
22976
+ const runtimePath = path27.join(stackPath, runtime);
21990
22977
  try {
21991
- await fs25.access(runtimePath);
22978
+ await fs27.access(runtimePath);
21992
22979
  if (runtime === "node") {
21993
- const authTs = path23.join(runtimePath, "src", "auth.ts");
21994
- const authJs = path23.join(runtimePath, "dist", "auth.js");
22980
+ const authTs = path27.join(runtimePath, "src", "auth.ts");
22981
+ const authJs = path27.join(runtimePath, "dist", "auth.js");
21995
22982
  try {
21996
- await fs25.access(authTs);
22983
+ await fs27.access(authTs);
21997
22984
  return { runtime: "node", authScript: authTs, useTsx: true };
21998
22985
  } catch {
21999
22986
  try {
22000
- await fs25.access(authJs);
22987
+ await fs27.access(authJs);
22001
22988
  return { runtime: "node", authScript: authJs, useTsx: false };
22002
22989
  } catch {
22003
22990
  }
22004
22991
  }
22005
22992
  } else if (runtime === "python") {
22006
- const authPy = path23.join(runtimePath, "src", "auth.py");
22993
+ const authPy = path27.join(runtimePath, "src", "auth.py");
22007
22994
  try {
22008
- await fs25.access(authPy);
22995
+ await fs27.access(authPy);
22009
22996
  return { runtime: "python", authScript: authPy, useTsx: false };
22010
22997
  } catch {
22011
22998
  }
@@ -22055,14 +23042,14 @@ Installed stacks:`);
22055
23042
  console.log(`Using port: ${port}`);
22056
23043
  console.log("");
22057
23044
  let cmd;
22058
- const cwd = path23.dirname(authInfo.authScript);
23045
+ const cwd = path27.dirname(authInfo.authScript);
22059
23046
  if (authInfo.runtime === "node") {
22060
- const distAuth = path23.join(cwd, "..", "dist", "auth.js");
23047
+ const distAuth = path27.join(cwd, "..", "dist", "auth.js");
22061
23048
  let useBuiltInPort = false;
22062
23049
  let tempAuthScript = null;
22063
23050
  try {
22064
- await fs25.access(distAuth);
22065
- const distContent = await fs25.readFile(distAuth, "utf-8");
23051
+ await fs27.access(distAuth);
23052
+ const distContent = await fs27.readFile(distAuth, "utf-8");
22066
23053
  if (distContent.includes("findAvailablePort")) {
22067
23054
  console.log("Using compiled authentication script...");
22068
23055
  cmd = `node ${distAuth}${accountEmail ? ` ${accountEmail}` : ""}`;
@@ -22071,11 +23058,11 @@ Installed stacks:`);
22071
23058
  } catch {
22072
23059
  }
22073
23060
  if (!useBuiltInPort) {
22074
- const authContent = await fs25.readFile(authInfo.authScript, "utf-8");
23061
+ const authContent = await fs27.readFile(authInfo.authScript, "utf-8");
22075
23062
  const tempExt = authInfo.useTsx ? ".ts" : ".mjs";
22076
- tempAuthScript = path23.join(cwd, "..", `auth-temp${tempExt}`);
23063
+ tempAuthScript = path27.join(cwd, "..", `auth-temp${tempExt}`);
22077
23064
  const modifiedContent = authContent.replace(/localhost:3456/g, `localhost:${port}`).replace(/server\.listen\(3456/g, `server.listen(${port}`);
22078
- await fs25.writeFile(tempAuthScript, modifiedContent);
23065
+ await fs27.writeFile(tempAuthScript, modifiedContent);
22079
23066
  if (authInfo.useTsx) {
22080
23067
  cmd = `npx tsx ${tempAuthScript}${accountEmail ? ` ${accountEmail}` : ""}`;
22081
23068
  } else {
@@ -22090,12 +23077,12 @@ Installed stacks:`);
22090
23077
  stdio: "inherit"
22091
23078
  });
22092
23079
  if (tempAuthScript) {
22093
- await fs25.unlink(tempAuthScript);
23080
+ await fs27.unlink(tempAuthScript);
22094
23081
  }
22095
23082
  } catch (error) {
22096
23083
  if (tempAuthScript) {
22097
23084
  try {
22098
- await fs25.unlink(tempAuthScript);
23085
+ await fs27.unlink(tempAuthScript);
22099
23086
  } catch {
22100
23087
  }
22101
23088
  }
@@ -22127,21 +23114,20 @@ Installed stacks:`);
22127
23114
  }
22128
23115
 
22129
23116
  // src/commands/mcp.js
22130
- var fs26 = __toESM(require("fs"), 1);
22131
- var path24 = __toESM(require("path"), 1);
23117
+ var fs28 = __toESM(require("fs"), 1);
23118
+ var path28 = __toESM(require("path"), 1);
22132
23119
  var import_child_process10 = require("child_process");
22133
- init_src();
22134
23120
  function getBundledRuntime(runtime) {
22135
23121
  const platform = process.platform;
22136
23122
  if (runtime === "node") {
22137
- const nodePath = platform === "win32" ? path24.join(PATHS.runtimes, "node", "node.exe") : path24.join(PATHS.runtimes, "node", "bin", "node");
22138
- if (fs26.existsSync(nodePath)) {
23123
+ const nodePath = platform === "win32" ? path28.join(PATHS2.runtimes, "node", "node.exe") : path28.join(PATHS2.runtimes, "node", "bin", "node");
23124
+ if (fs28.existsSync(nodePath)) {
22139
23125
  return nodePath;
22140
23126
  }
22141
23127
  }
22142
23128
  if (runtime === "python") {
22143
- const pythonPath = platform === "win32" ? path24.join(PATHS.runtimes, "python", "python.exe") : path24.join(PATHS.runtimes, "python", "bin", "python3");
22144
- if (fs26.existsSync(pythonPath)) {
23129
+ const pythonPath = platform === "win32" ? path28.join(PATHS2.runtimes, "python", "python.exe") : path28.join(PATHS2.runtimes, "python", "bin", "python3");
23130
+ if (fs28.existsSync(pythonPath)) {
22145
23131
  return pythonPath;
22146
23132
  }
22147
23133
  }
@@ -22149,18 +23135,18 @@ function getBundledRuntime(runtime) {
22149
23135
  }
22150
23136
  function getBundledNpx() {
22151
23137
  const platform = process.platform;
22152
- const npxPath = platform === "win32" ? path24.join(PATHS.runtimes, "node", "npx.cmd") : path24.join(PATHS.runtimes, "node", "bin", "npx");
22153
- if (fs26.existsSync(npxPath)) {
23138
+ const npxPath = platform === "win32" ? path28.join(PATHS2.runtimes, "node", "npx.cmd") : path28.join(PATHS2.runtimes, "node", "bin", "npx");
23139
+ if (fs28.existsSync(npxPath)) {
22154
23140
  return npxPath;
22155
23141
  }
22156
23142
  return null;
22157
23143
  }
22158
23144
  function loadManifest2(stackPath) {
22159
- const manifestPath = path24.join(stackPath, "manifest.json");
22160
- if (!fs26.existsSync(manifestPath)) {
23145
+ const manifestPath = path28.join(stackPath, "manifest.json");
23146
+ if (!fs28.existsSync(manifestPath)) {
22161
23147
  return null;
22162
23148
  }
22163
- return JSON.parse(fs26.readFileSync(manifestPath, "utf-8"));
23149
+ return JSON.parse(fs28.readFileSync(manifestPath, "utf-8"));
22164
23150
  }
22165
23151
  function getRequiredSecrets(manifest) {
22166
23152
  const secrets = manifest?.requires?.secrets || manifest?.secrets || [];
@@ -22193,8 +23179,8 @@ async function cmdMcp(args, flags) {
22193
23179
  console.error("Example: rudi mcp slack");
22194
23180
  process.exit(1);
22195
23181
  }
22196
- const stackPath = path24.join(PATHS.stacks, stackName);
22197
- if (!fs26.existsSync(stackPath)) {
23182
+ const stackPath = path28.join(PATHS2.stacks, stackName);
23183
+ if (!fs28.existsSync(stackPath)) {
22198
23184
  console.error(`Stack not found: ${stackName}`);
22199
23185
  console.error(`Expected at: ${stackPath}`);
22200
23186
  console.error("");
@@ -22243,22 +23229,22 @@ async function cmdMcp(args, flags) {
22243
23229
  }
22244
23230
  return part;
22245
23231
  }
22246
- if (part.startsWith("./") || part.startsWith("../") || !path24.isAbsolute(part)) {
22247
- const resolved = path24.join(stackPath, part);
22248
- if (fs26.existsSync(resolved)) {
23232
+ if (part.startsWith("./") || part.startsWith("../") || !path28.isAbsolute(part)) {
23233
+ const resolved = path28.join(stackPath, part);
23234
+ if (fs28.existsSync(resolved)) {
22249
23235
  return resolved;
22250
23236
  }
22251
23237
  }
22252
23238
  return part;
22253
23239
  });
22254
23240
  const [cmd, ...cmdArgs] = resolvedCommand;
22255
- const bundledNodeBin = path24.join(PATHS.runtimes, "node", "bin");
22256
- const bundledPythonBin = path24.join(PATHS.runtimes, "python", "bin");
22257
- if (fs26.existsSync(bundledNodeBin) || fs26.existsSync(bundledPythonBin)) {
23241
+ const bundledNodeBin = path28.join(PATHS2.runtimes, "node", "bin");
23242
+ const bundledPythonBin = path28.join(PATHS2.runtimes, "python", "bin");
23243
+ if (fs28.existsSync(bundledNodeBin) || fs28.existsSync(bundledPythonBin)) {
22258
23244
  const runtimePaths = [];
22259
- if (fs26.existsSync(bundledNodeBin)) runtimePaths.push(bundledNodeBin);
22260
- if (fs26.existsSync(bundledPythonBin)) runtimePaths.push(bundledPythonBin);
22261
- env.PATH = runtimePaths.join(path24.delimiter) + path24.delimiter + (env.PATH || "");
23245
+ if (fs28.existsSync(bundledNodeBin)) runtimePaths.push(bundledNodeBin);
23246
+ if (fs28.existsSync(bundledPythonBin)) runtimePaths.push(bundledPythonBin);
23247
+ env.PATH = runtimePaths.join(path28.delimiter) + path28.delimiter + (env.PATH || "");
22262
23248
  }
22263
23249
  if (flags.debug) {
22264
23250
  console.error(`[rudi mcp] Stack: ${stackName}`);
@@ -22288,14 +23274,13 @@ async function cmdMcp(args, flags) {
22288
23274
  }
22289
23275
 
22290
23276
  // src/commands/integrate.js
22291
- var fs27 = __toESM(require("fs"), 1);
22292
- var path25 = __toESM(require("path"), 1);
22293
- var import_os5 = __toESM(require("os"), 1);
22294
- init_src();
22295
- var HOME2 = import_os5.default.homedir();
22296
- var ROUTER_SHIM_PATH = path25.join(PATHS.home, "shims", "rudi-router");
23277
+ var fs29 = __toESM(require("fs"), 1);
23278
+ var path29 = __toESM(require("path"), 1);
23279
+ var import_os6 = __toESM(require("os"), 1);
23280
+ var HOME2 = import_os6.default.homedir();
23281
+ var ROUTER_SHIM_PATH = path29.join(PATHS2.home, "shims", "rudi-router");
22297
23282
  function checkRouterShim() {
22298
- if (!fs27.existsSync(ROUTER_SHIM_PATH)) {
23283
+ if (!fs29.existsSync(ROUTER_SHIM_PATH)) {
22299
23284
  throw new Error(
22300
23285
  `Router shim not found at ${ROUTER_SHIM_PATH}
22301
23286
  Run: npm install -g @learnrudi/cli@latest`
@@ -22304,27 +23289,27 @@ Run: npm install -g @learnrudi/cli@latest`
22304
23289
  return ROUTER_SHIM_PATH;
22305
23290
  }
22306
23291
  function backupConfig(configPath) {
22307
- if (!fs27.existsSync(configPath)) return null;
23292
+ if (!fs29.existsSync(configPath)) return null;
22308
23293
  const backupPath = configPath + ".backup." + Date.now();
22309
- fs27.copyFileSync(configPath, backupPath);
23294
+ fs29.copyFileSync(configPath, backupPath);
22310
23295
  return backupPath;
22311
23296
  }
22312
23297
  function readJsonConfig(configPath) {
22313
- if (!fs27.existsSync(configPath)) {
23298
+ if (!fs29.existsSync(configPath)) {
22314
23299
  return {};
22315
23300
  }
22316
23301
  try {
22317
- return JSON.parse(fs27.readFileSync(configPath, "utf-8"));
23302
+ return JSON.parse(fs29.readFileSync(configPath, "utf-8"));
22318
23303
  } catch {
22319
23304
  return {};
22320
23305
  }
22321
23306
  }
22322
23307
  function writeJsonConfig(configPath, config) {
22323
- const dir = path25.dirname(configPath);
22324
- if (!fs27.existsSync(dir)) {
22325
- fs27.mkdirSync(dir, { recursive: true });
23308
+ const dir = path29.dirname(configPath);
23309
+ if (!fs29.existsSync(dir)) {
23310
+ fs29.mkdirSync(dir, { recursive: true });
22326
23311
  }
22327
- fs27.writeFileSync(configPath, JSON.stringify(config, null, 2));
23312
+ fs29.writeFileSync(configPath, JSON.stringify(config, null, 2));
22328
23313
  }
22329
23314
  function buildRouterEntry(agentId) {
22330
23315
  const base = {
@@ -22343,11 +23328,11 @@ async function integrateAgent(agentId, flags) {
22343
23328
  return { success: false, error: "Unknown agent" };
22344
23329
  }
22345
23330
  const configPath = findAgentConfig(agentConfig);
22346
- const targetPath = configPath || path25.join(HOME2, agentConfig.paths[process.platform]?.[0] || agentConfig.paths.darwin[0]);
23331
+ const targetPath = configPath || path29.join(HOME2, agentConfig.paths[process.platform]?.[0] || agentConfig.paths.darwin[0]);
22347
23332
  console.log(`
22348
23333
  ${agentConfig.name}:`);
22349
23334
  console.log(` Config: ${targetPath}`);
22350
- if (fs27.existsSync(targetPath)) {
23335
+ if (fs29.existsSync(targetPath)) {
22351
23336
  const backup = backupConfig(targetPath);
22352
23337
  if (backup && flags.verbose) {
22353
23338
  console.log(` Backup: ${backup}`);
@@ -22358,7 +23343,7 @@ ${agentConfig.name}:`);
22358
23343
  if (!config[key]) {
22359
23344
  config[key] = {};
22360
23345
  }
22361
- const rudiMcpShimPath = path25.join(PATHS.home, "shims", "rudi-mcp");
23346
+ const rudiMcpShimPath = path29.join(PATHS2.home, "shims", "rudi-mcp");
22362
23347
  const removedEntries = [];
22363
23348
  for (const [serverName, serverConfig] of Object.entries(config[key])) {
22364
23349
  if (serverConfig.command === rudiMcpShimPath) {
@@ -22490,52 +23475,51 @@ Wiring up RUDI router...`);
22490
23475
  }
22491
23476
 
22492
23477
  // src/commands/migrate.js
22493
- var fs28 = __toESM(require("fs"), 1);
22494
- var path26 = __toESM(require("path"), 1);
22495
- var import_os6 = __toESM(require("os"), 1);
22496
- init_src();
22497
- var HOME3 = import_os6.default.homedir();
22498
- var OLD_PROMPT_STACK = path26.join(HOME3, ".prompt-stack");
22499
- var SHIM_PATH = path26.join(PATHS.home, "shims", "rudi-mcp");
23478
+ var fs30 = __toESM(require("fs"), 1);
23479
+ var path30 = __toESM(require("path"), 1);
23480
+ var import_os7 = __toESM(require("os"), 1);
23481
+ var HOME3 = import_os7.default.homedir();
23482
+ var OLD_PROMPT_STACK = path30.join(HOME3, ".prompt-stack");
23483
+ var SHIM_PATH = path30.join(PATHS2.home, "shims", "rudi-mcp");
22500
23484
  function getOldStacks() {
22501
- const stacksDir = path26.join(OLD_PROMPT_STACK, "stacks");
22502
- if (!fs28.existsSync(stacksDir)) return [];
22503
- return fs28.readdirSync(stacksDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".")).filter((d) => {
22504
- const hasManifest = fs28.existsSync(path26.join(stacksDir, d.name, "manifest.json"));
22505
- const hasPackage = fs28.existsSync(path26.join(stacksDir, d.name, "package.json"));
23485
+ const stacksDir = path30.join(OLD_PROMPT_STACK, "stacks");
23486
+ if (!fs30.existsSync(stacksDir)) return [];
23487
+ return fs30.readdirSync(stacksDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".")).filter((d) => {
23488
+ const hasManifest = fs30.existsSync(path30.join(stacksDir, d.name, "manifest.json"));
23489
+ const hasPackage = fs30.existsSync(path30.join(stacksDir, d.name, "package.json"));
22506
23490
  return hasManifest || hasPackage;
22507
23491
  }).map((d) => d.name);
22508
23492
  }
22509
23493
  function copyStack(stackName) {
22510
- const oldPath = path26.join(OLD_PROMPT_STACK, "stacks", stackName);
22511
- const newPath = path26.join(PATHS.stacks, stackName);
22512
- if (!fs28.existsSync(oldPath)) {
23494
+ const oldPath = path30.join(OLD_PROMPT_STACK, "stacks", stackName);
23495
+ const newPath = path30.join(PATHS2.stacks, stackName);
23496
+ if (!fs30.existsSync(oldPath)) {
22513
23497
  return { success: false, error: "Source not found" };
22514
23498
  }
22515
- if (fs28.existsSync(newPath)) {
23499
+ if (fs30.existsSync(newPath)) {
22516
23500
  return { success: true, skipped: true, reason: "Already exists" };
22517
23501
  }
22518
- if (!fs28.existsSync(PATHS.stacks)) {
22519
- fs28.mkdirSync(PATHS.stacks, { recursive: true });
23502
+ if (!fs30.existsSync(PATHS2.stacks)) {
23503
+ fs30.mkdirSync(PATHS2.stacks, { recursive: true });
22520
23504
  }
22521
23505
  copyRecursive(oldPath, newPath);
22522
23506
  return { success: true, copied: true };
22523
23507
  }
22524
23508
  function copyRecursive(src, dest) {
22525
- const stat = fs28.statSync(src);
23509
+ const stat = fs30.statSync(src);
22526
23510
  if (stat.isDirectory()) {
22527
- fs28.mkdirSync(dest, { recursive: true });
22528
- for (const child of fs28.readdirSync(src)) {
22529
- copyRecursive(path26.join(src, child), path26.join(dest, child));
23511
+ fs30.mkdirSync(dest, { recursive: true });
23512
+ for (const child of fs30.readdirSync(src)) {
23513
+ copyRecursive(path30.join(src, child), path30.join(dest, child));
22530
23514
  }
22531
23515
  } else {
22532
- fs28.copyFileSync(src, dest);
23516
+ fs30.copyFileSync(src, dest);
22533
23517
  }
22534
23518
  }
22535
23519
  function ensureShim() {
22536
- const shimsDir = path26.dirname(SHIM_PATH);
22537
- if (!fs28.existsSync(shimsDir)) {
22538
- fs28.mkdirSync(shimsDir, { recursive: true });
23520
+ const shimsDir = path30.dirname(SHIM_PATH);
23521
+ if (!fs30.existsSync(shimsDir)) {
23522
+ fs30.mkdirSync(shimsDir, { recursive: true });
22539
23523
  }
22540
23524
  const shimContent = `#!/usr/bin/env bash
22541
23525
  set -euo pipefail
@@ -22545,7 +23529,7 @@ else
22545
23529
  exec npx --yes @learnrudi/cli mcp "$1"
22546
23530
  fi
22547
23531
  `;
22548
- fs28.writeFileSync(SHIM_PATH, shimContent, { mode: 493 });
23532
+ fs30.writeFileSync(SHIM_PATH, shimContent, { mode: 493 });
22549
23533
  }
22550
23534
  function buildNewEntry(stackName, agentId) {
22551
23535
  const base = {
@@ -22569,7 +23553,7 @@ function migrateAgentConfig(agentConfig, installedStacks, flags) {
22569
23553
  if (!configPath) return { skipped: true, reason: "Config not found" };
22570
23554
  let config;
22571
23555
  try {
22572
- config = JSON.parse(fs28.readFileSync(configPath, "utf-8"));
23556
+ config = JSON.parse(fs30.readFileSync(configPath, "utf-8"));
22573
23557
  } catch {
22574
23558
  return { skipped: true, reason: "Could not parse config" };
22575
23559
  }
@@ -22596,9 +23580,9 @@ function migrateAgentConfig(agentConfig, installedStacks, flags) {
22596
23580
  }
22597
23581
  if (updated > 0 || removed > 0) {
22598
23582
  const backupPath = configPath + ".backup." + Date.now();
22599
- fs28.copyFileSync(configPath, backupPath);
23583
+ fs30.copyFileSync(configPath, backupPath);
22600
23584
  config[key] = mcpServers;
22601
- fs28.writeFileSync(configPath, JSON.stringify(config, null, 2));
23585
+ fs30.writeFileSync(configPath, JSON.stringify(config, null, 2));
22602
23586
  }
22603
23587
  return { updated, removed, changes };
22604
23588
  }
@@ -22647,15 +23631,15 @@ async function migrateStatus() {
22647
23631
  console.log(`Old .prompt-stack stacks: ${oldStacks.length}`);
22648
23632
  if (oldStacks.length > 0) {
22649
23633
  for (const name of oldStacks) {
22650
- const existsInRudi = fs28.existsSync(path26.join(PATHS.stacks, name));
23634
+ const existsInRudi = fs30.existsSync(path30.join(PATHS2.stacks, name));
22651
23635
  const status = existsInRudi ? "\u2713 (already in .rudi)" : "\u25CB (needs migration)";
22652
23636
  console.log(` ${status} ${name}`);
22653
23637
  }
22654
23638
  }
22655
- const newStacksDir = PATHS.stacks;
23639
+ const newStacksDir = PATHS2.stacks;
22656
23640
  let newStacks = [];
22657
- if (fs28.existsSync(newStacksDir)) {
22658
- newStacks = fs28.readdirSync(newStacksDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".")).map((d) => d.name);
23641
+ if (fs30.existsSync(newStacksDir)) {
23642
+ newStacks = fs30.readdirSync(newStacksDir, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".")).map((d) => d.name);
22659
23643
  }
22660
23644
  console.log(`
22661
23645
  New .rudi stacks: ${newStacks.length}`);
@@ -22670,7 +23654,7 @@ New .rudi stacks: ${newStacks.length}`);
22670
23654
  if (!configPath) continue;
22671
23655
  let config;
22672
23656
  try {
22673
- config = JSON.parse(fs28.readFileSync(configPath, "utf-8"));
23657
+ config = JSON.parse(fs30.readFileSync(configPath, "utf-8"));
22674
23658
  } catch {
22675
23659
  continue;
22676
23660
  }
@@ -22706,7 +23690,7 @@ async function migrateStacks(flags) {
22706
23690
  `);
22707
23691
  for (const name of oldStacks) {
22708
23692
  if (flags.dryRun) {
22709
- const exists = fs28.existsSync(path26.join(PATHS.stacks, name));
23693
+ const exists = fs30.existsSync(path30.join(PATHS2.stacks, name));
22710
23694
  console.log(` [dry-run] ${name}: ${exists ? "would skip (exists)" : "would copy"}`);
22711
23695
  } else {
22712
23696
  const result = copyStack(name);
@@ -22721,7 +23705,7 @@ async function migrateStacks(flags) {
22721
23705
  }
22722
23706
  if (!flags.dryRun) {
22723
23707
  console.log(`
22724
- Stacks migrated to: ${PATHS.stacks}`);
23708
+ Stacks migrated to: ${PATHS2.stacks}`);
22725
23709
  }
22726
23710
  }
22727
23711
  async function migrateConfigs(flags) {
@@ -22732,8 +23716,8 @@ async function migrateConfigs(flags) {
22732
23716
  `);
22733
23717
  }
22734
23718
  let installedStacks = [];
22735
- if (fs28.existsSync(PATHS.stacks)) {
22736
- installedStacks = fs28.readdirSync(PATHS.stacks, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".")).map((d) => d.name);
23719
+ if (fs30.existsSync(PATHS2.stacks)) {
23720
+ installedStacks = fs30.readdirSync(PATHS2.stacks, { withFileTypes: true }).filter((d) => d.isDirectory() && !d.name.startsWith(".")).map((d) => d.name);
22737
23721
  }
22738
23722
  for (const agentConfig of AGENT_CONFIGS) {
22739
23723
  const configPath = findAgentConfig(agentConfig);
@@ -22901,9 +23885,9 @@ After configuring secrets, run: rudi index`);
22901
23885
  // src/commands/status.js
22902
23886
  init_src3();
22903
23887
  var import_child_process11 = require("child_process");
22904
- var import_fs22 = __toESM(require("fs"), 1);
22905
- var import_path19 = __toESM(require("path"), 1);
22906
- var import_os7 = __toESM(require("os"), 1);
23888
+ var import_fs24 = __toESM(require("fs"), 1);
23889
+ var import_path21 = __toESM(require("path"), 1);
23890
+ var import_os8 = __toESM(require("os"), 1);
22907
23891
  var AGENTS = [
22908
23892
  {
22909
23893
  id: "claude",
@@ -22948,8 +23932,8 @@ var BINARIES = [
22948
23932
  { id: "jq", name: "jq", command: "jq", versionFlag: "--version" }
22949
23933
  ];
22950
23934
  function fileExists(filePath) {
22951
- const resolved = filePath.replace("~", import_os7.default.homedir());
22952
- return import_fs22.default.existsSync(resolved);
23935
+ const resolved = filePath.replace("~", import_os8.default.homedir());
23936
+ return import_fs24.default.existsSync(resolved);
22953
23937
  }
22954
23938
  function checkKeychain(service) {
22955
23939
  if (process.platform !== "darwin") return false;
@@ -22977,13 +23961,13 @@ function getVersion2(command, versionFlag) {
22977
23961
  }
22978
23962
  function findBinary(command, kind = "binary") {
22979
23963
  const rudiPaths = [
22980
- import_path19.default.join(PATHS.agents, command, "node_modules", ".bin", command),
22981
- import_path19.default.join(PATHS.runtimes, command, "bin", command),
22982
- import_path19.default.join(PATHS.binaries, command, command),
22983
- import_path19.default.join(PATHS.binaries, command)
23964
+ import_path21.default.join(PATHS.agents, command, "node_modules", ".bin", command),
23965
+ import_path21.default.join(PATHS.runtimes, command, "bin", command),
23966
+ import_path21.default.join(PATHS.binaries, command, command),
23967
+ import_path21.default.join(PATHS.binaries, command)
22984
23968
  ];
22985
23969
  for (const p of rudiPaths) {
22986
- if (import_fs22.default.existsSync(p)) {
23970
+ if (import_fs24.default.existsSync(p)) {
22987
23971
  return { found: true, path: p, source: "rudi" };
22988
23972
  }
22989
23973
  }
@@ -23001,8 +23985,8 @@ function findBinary(command, kind = "binary") {
23001
23985
  return { found: false, path: null, source: null };
23002
23986
  }
23003
23987
  function getAgentStatus(agent) {
23004
- const rudiPath = import_path19.default.join(PATHS.agents, agent.id, "node_modules", ".bin", agent.id);
23005
- const rudiInstalled = import_fs22.default.existsSync(rudiPath);
23988
+ const rudiPath = import_path21.default.join(PATHS.agents, agent.id, "node_modules", ".bin", agent.id);
23989
+ const rudiInstalled = import_fs24.default.existsSync(rudiPath);
23006
23990
  let globalPath = null;
23007
23991
  let globalInstalled = false;
23008
23992
  if (!rudiInstalled) {
@@ -23084,12 +24068,12 @@ async function getFullStatus() {
23084
24068
  } catch {
23085
24069
  }
23086
24070
  const directories = {
23087
- home: { path: PATHS.home, exists: import_fs22.default.existsSync(PATHS.home) },
23088
- stacks: { path: PATHS.stacks, exists: import_fs22.default.existsSync(PATHS.stacks) },
23089
- agents: { path: PATHS.agents, exists: import_fs22.default.existsSync(PATHS.agents) },
23090
- runtimes: { path: PATHS.runtimes, exists: import_fs22.default.existsSync(PATHS.runtimes) },
23091
- binaries: { path: PATHS.binaries, exists: import_fs22.default.existsSync(PATHS.binaries) },
23092
- db: { path: PATHS.db, exists: import_fs22.default.existsSync(PATHS.db) }
24071
+ home: { path: PATHS.home, exists: import_fs24.default.existsSync(PATHS.home) },
24072
+ stacks: { path: PATHS.stacks, exists: import_fs24.default.existsSync(PATHS.stacks) },
24073
+ agents: { path: PATHS.agents, exists: import_fs24.default.existsSync(PATHS.agents) },
24074
+ runtimes: { path: PATHS.runtimes, exists: import_fs24.default.existsSync(PATHS.runtimes) },
24075
+ binaries: { path: PATHS.binaries, exists: import_fs24.default.existsSync(PATHS.binaries) },
24076
+ db: { path: PATHS.db, exists: import_fs24.default.existsSync(PATHS.db) }
23093
24077
  };
23094
24078
  const summary = {
23095
24079
  agentsInstalled: agents.filter((a) => a.installed).length,
@@ -23197,9 +24181,9 @@ async function cmdStatus(args, flags) {
23197
24181
  // src/commands/check.js
23198
24182
  init_src3();
23199
24183
  var import_child_process12 = require("child_process");
23200
- var import_fs23 = __toESM(require("fs"), 1);
23201
- var import_path20 = __toESM(require("path"), 1);
23202
- var import_os8 = __toESM(require("os"), 1);
24184
+ var import_fs25 = __toESM(require("fs"), 1);
24185
+ var import_path22 = __toESM(require("path"), 1);
24186
+ var import_os9 = __toESM(require("os"), 1);
23203
24187
  var AGENT_CREDENTIALS = {
23204
24188
  claude: { type: "keychain", service: "Claude Code-credentials" },
23205
24189
  codex: { type: "file", path: "~/.codex/auth.json" },
@@ -23207,8 +24191,8 @@ var AGENT_CREDENTIALS = {
23207
24191
  copilot: { type: "file", path: "~/.config/github-copilot/hosts.json" }
23208
24192
  };
23209
24193
  function fileExists2(filePath) {
23210
- const resolved = filePath.replace("~", import_os8.default.homedir());
23211
- return import_fs23.default.existsSync(resolved);
24194
+ const resolved = filePath.replace("~", import_os9.default.homedir());
24195
+ return import_fs25.default.existsSync(resolved);
23212
24196
  }
23213
24197
  function checkKeychain2(service) {
23214
24198
  if (process.platform !== "darwin") return false;
@@ -23234,15 +24218,15 @@ function getVersion3(binaryPath, versionFlag = "--version") {
23234
24218
  }
23235
24219
  }
23236
24220
  function detectKindFromFilesystem(name) {
23237
- const agentPath = import_path20.default.join(PATHS.agents, name, "node_modules", ".bin", name);
23238
- if (import_fs23.default.existsSync(agentPath)) return "agent";
23239
- const runtimePath = import_path20.default.join(PATHS.runtimes, name, "bin", name);
23240
- if (import_fs23.default.existsSync(runtimePath)) return "runtime";
23241
- const binaryPath = import_path20.default.join(PATHS.binaries, name, name);
23242
- const binaryPath2 = import_path20.default.join(PATHS.binaries, name);
23243
- if (import_fs23.default.existsSync(binaryPath) || import_fs23.default.existsSync(binaryPath2)) return "binary";
23244
- const stackPath = import_path20.default.join(PATHS.stacks, name);
23245
- if (import_fs23.default.existsSync(stackPath)) return "stack";
24221
+ const agentPath = import_path22.default.join(PATHS.agents, name, "node_modules", ".bin", name);
24222
+ if (import_fs25.default.existsSync(agentPath)) return "agent";
24223
+ const runtimePath = import_path22.default.join(PATHS.runtimes, name, "bin", name);
24224
+ if (import_fs25.default.existsSync(runtimePath)) return "runtime";
24225
+ const binaryPath = import_path22.default.join(PATHS.binaries, name, name);
24226
+ const binaryPath2 = import_path22.default.join(PATHS.binaries, name);
24227
+ if (import_fs25.default.existsSync(binaryPath) || import_fs25.default.existsSync(binaryPath2)) return "binary";
24228
+ const stackPath = import_path22.default.join(PATHS.stacks, name);
24229
+ if (import_fs25.default.existsSync(stackPath)) return "stack";
23246
24230
  try {
23247
24231
  const globalPath = (0, import_child_process12.execSync)(`which ${name} 2>/dev/null`, { encoding: "utf-8" }).trim();
23248
24232
  if (globalPath) {
@@ -23288,8 +24272,8 @@ async function cmdCheck(args, flags) {
23288
24272
  };
23289
24273
  switch (kind) {
23290
24274
  case "agent": {
23291
- const rudiPath = import_path20.default.join(PATHS.agents, name, "node_modules", ".bin", name);
23292
- const rudiInstalled = import_fs23.default.existsSync(rudiPath);
24275
+ const rudiPath = import_path22.default.join(PATHS.agents, name, "node_modules", ".bin", name);
24276
+ const rudiInstalled = import_fs25.default.existsSync(rudiPath);
23293
24277
  let globalPath = null;
23294
24278
  let globalInstalled = false;
23295
24279
  if (!rudiInstalled) {
@@ -23320,8 +24304,8 @@ async function cmdCheck(args, flags) {
23320
24304
  break;
23321
24305
  }
23322
24306
  case "runtime": {
23323
- const rudiPath = import_path20.default.join(PATHS.runtimes, name, "bin", name);
23324
- if (import_fs23.default.existsSync(rudiPath)) {
24307
+ const rudiPath = import_path22.default.join(PATHS.runtimes, name, "bin", name);
24308
+ if (import_fs25.default.existsSync(rudiPath)) {
23325
24309
  result.installed = true;
23326
24310
  result.path = rudiPath;
23327
24311
  result.version = getVersion3(rudiPath);
@@ -23340,8 +24324,8 @@ async function cmdCheck(args, flags) {
23340
24324
  break;
23341
24325
  }
23342
24326
  case "binary": {
23343
- const rudiPath = import_path20.default.join(PATHS.binaries, name, name);
23344
- if (import_fs23.default.existsSync(rudiPath)) {
24327
+ const rudiPath = import_path22.default.join(PATHS.binaries, name, name);
24328
+ if (import_fs25.default.existsSync(rudiPath)) {
23345
24329
  result.installed = true;
23346
24330
  result.path = rudiPath;
23347
24331
  } else {
@@ -23395,27 +24379,27 @@ async function cmdCheck(args, flags) {
23395
24379
 
23396
24380
  // src/commands/shims.js
23397
24381
  init_src3();
23398
- var import_fs24 = __toESM(require("fs"), 1);
23399
- var import_path21 = __toESM(require("path"), 1);
24382
+ var import_fs26 = __toESM(require("fs"), 1);
24383
+ var import_path23 = __toESM(require("path"), 1);
23400
24384
  function listShims2() {
23401
24385
  const binsDir = PATHS.bins;
23402
- if (!import_fs24.default.existsSync(binsDir)) {
24386
+ if (!import_fs26.default.existsSync(binsDir)) {
23403
24387
  return [];
23404
24388
  }
23405
- const entries = import_fs24.default.readdirSync(binsDir);
24389
+ const entries = import_fs26.default.readdirSync(binsDir);
23406
24390
  return entries.filter((entry) => {
23407
- const fullPath = import_path21.default.join(binsDir, entry);
23408
- const stat = import_fs24.default.lstatSync(fullPath);
24391
+ const fullPath = import_path23.default.join(binsDir, entry);
24392
+ const stat = import_fs26.default.lstatSync(fullPath);
23409
24393
  return stat.isFile() || stat.isSymbolicLink();
23410
24394
  });
23411
24395
  }
23412
24396
  function getShimType(shimPath) {
23413
- const stat = import_fs24.default.lstatSync(shimPath);
24397
+ const stat = import_fs26.default.lstatSync(shimPath);
23414
24398
  if (stat.isSymbolicLink()) {
23415
24399
  return "symlink";
23416
24400
  }
23417
24401
  try {
23418
- const content = import_fs24.default.readFileSync(shimPath, "utf8");
24402
+ const content = import_fs26.default.readFileSync(shimPath, "utf8");
23419
24403
  if (content.includes("#!/usr/bin/env bash")) {
23420
24404
  return "wrapper";
23421
24405
  }
@@ -23426,14 +24410,14 @@ function getShimType(shimPath) {
23426
24410
  function getShimTarget(name, shimPath, type) {
23427
24411
  if (type === "symlink") {
23428
24412
  try {
23429
- return import_fs24.default.readlinkSync(shimPath);
24413
+ return import_fs26.default.readlinkSync(shimPath);
23430
24414
  } catch (err) {
23431
24415
  return null;
23432
24416
  }
23433
24417
  }
23434
24418
  if (type === "wrapper") {
23435
24419
  try {
23436
- const content = import_fs24.default.readFileSync(shimPath, "utf8");
24420
+ const content = import_fs26.default.readFileSync(shimPath, "utf8");
23437
24421
  const match = content.match(/exec "([^"]+)"/);
23438
24422
  return match ? match[1] : null;
23439
24423
  } catch (err) {
@@ -23455,18 +24439,18 @@ function getPackageFromShim(shimName, target) {
23455
24439
  return `${kindMap[kind]}:${pkgName}`;
23456
24440
  }
23457
24441
  const manifestDirs = [
23458
- import_path21.default.join(PATHS.binaries),
23459
- import_path21.default.join(PATHS.runtimes),
23460
- import_path21.default.join(PATHS.agents)
24442
+ import_path23.default.join(PATHS.binaries),
24443
+ import_path23.default.join(PATHS.runtimes),
24444
+ import_path23.default.join(PATHS.agents)
23461
24445
  ];
23462
24446
  for (const dir of manifestDirs) {
23463
- if (!import_fs24.default.existsSync(dir)) continue;
23464
- const packages = import_fs24.default.readdirSync(dir);
24447
+ if (!import_fs26.default.existsSync(dir)) continue;
24448
+ const packages = import_fs26.default.readdirSync(dir);
23465
24449
  for (const pkg of packages) {
23466
- const manifestPath = import_path21.default.join(dir, pkg, "manifest.json");
23467
- if (import_fs24.default.existsSync(manifestPath)) {
24450
+ const manifestPath = import_path23.default.join(dir, pkg, "manifest.json");
24451
+ if (import_fs26.default.existsSync(manifestPath)) {
23468
24452
  try {
23469
- const manifest = JSON.parse(import_fs24.default.readFileSync(manifestPath, "utf8"));
24453
+ const manifest = JSON.parse(import_fs26.default.readFileSync(manifestPath, "utf8"));
23470
24454
  const bins = manifest.bins || manifest.binaries || [manifest.name || pkg];
23471
24455
  if (bins.includes(shimName)) {
23472
24456
  const kind = dir.includes("binaries") ? "binary" : dir.includes("runtimes") ? "runtime" : "agent";
@@ -23514,7 +24498,7 @@ async function cmdShims(args, flags) {
23514
24498
  const results = [];
23515
24499
  let hasIssues = false;
23516
24500
  for (const name of shimNames) {
23517
- const shimPath = import_path21.default.join(PATHS.bins, name);
24501
+ const shimPath = import_path23.default.join(PATHS.bins, name);
23518
24502
  const validation = validateShim(name);
23519
24503
  const type = getShimType(shimPath);
23520
24504
  const target = getShimTarget(name, shimPath, type);
@@ -23567,30 +24551,151 @@ ${valid} valid, ${broken} broken`);
23567
24551
  }
23568
24552
  if (subcommand === "fix") {
23569
24553
  console.log("\n\x1B[33mAttempting to fix broken shims...\x1B[0m\n");
23570
- const { installPackage: installPackage2 } = await Promise.resolve().then(() => (init_src3(), src_exports2));
23571
- const brokenPackages = /* @__PURE__ */ new Set();
23572
- results.forEach((r) => {
23573
- if (!r.valid && r.package) {
23574
- brokenPackages.add(r.package);
24554
+ const brokenWithPkg = results.filter((r) => !r.valid && r.package);
24555
+ const orphaned = results.filter((r) => !r.valid && !r.package);
24556
+ if (orphaned.length > 0) {
24557
+ console.log(`Removing ${orphaned.length} orphaned shims...`);
24558
+ for (const shim of orphaned) {
24559
+ const shimPath = import_path23.default.join(PATHS.bins, shim.name);
24560
+ try {
24561
+ import_fs26.default.unlinkSync(shimPath);
24562
+ console.log(` \x1B[32m\u2713\x1B[0m Removed ${shim.name}`);
24563
+ } catch (err) {
24564
+ console.log(` \x1B[31m\u2717\x1B[0m Failed to remove ${shim.name}: ${err.message}`);
24565
+ }
23575
24566
  }
23576
- });
23577
- if (brokenPackages.size === 0) {
24567
+ console.log("");
24568
+ }
24569
+ const brokenPackages = new Set(brokenWithPkg.map((r) => r.package));
24570
+ if (brokenPackages.size === 0 && orphaned.length === 0) {
23578
24571
  console.log("No broken shims to fix.");
23579
24572
  process.exit(0);
23580
24573
  }
23581
- for (const pkg of brokenPackages) {
23582
- console.log(`Reinstalling ${pkg}...`);
23583
- try {
23584
- await installPackage2(pkg, { force: true });
23585
- console.log(`\x1B[32m\u2713\x1B[0m Fixed ${pkg}`);
23586
- } catch (err) {
23587
- console.log(`\x1B[31m\u2717\x1B[0m Failed to fix ${pkg}: ${err.message}`);
24574
+ if (brokenPackages.size > 0) {
24575
+ const { installPackage: installPackage2 } = await Promise.resolve().then(() => (init_src3(), src_exports));
24576
+ for (const pkg of brokenPackages) {
24577
+ console.log(`Reinstalling ${pkg}...`);
24578
+ try {
24579
+ await installPackage2(pkg, { force: true });
24580
+ console.log(`\x1B[32m\u2713\x1B[0m Fixed ${pkg}`);
24581
+ } catch (err) {
24582
+ console.log(`\x1B[31m\u2717\x1B[0m Failed to fix ${pkg}: ${err.message}`);
24583
+ }
23588
24584
  }
23589
24585
  }
24586
+ console.log("\n\x1B[32m\u2713\x1B[0m Fix complete");
23590
24587
  }
23591
24588
  process.exit(hasIssues ? 1 : 0);
23592
24589
  }
23593
24590
 
24591
+ // src/commands/info.js
24592
+ var import_fs27 = __toESM(require("fs"), 1);
24593
+ var import_path24 = __toESM(require("path"), 1);
24594
+ init_src3();
24595
+ async function cmdInfo(args, flags) {
24596
+ const pkgId = args[0];
24597
+ if (!pkgId) {
24598
+ console.error("Usage: rudi info <package>");
24599
+ console.error("Example: rudi info npm:typescript");
24600
+ console.error(" rudi info binary:supabase");
24601
+ process.exit(1);
24602
+ }
24603
+ try {
24604
+ const [kind, name] = parsePackageId2(pkgId);
24605
+ const installPath = getPackagePath2(pkgId);
24606
+ if (!import_fs27.default.existsSync(installPath)) {
24607
+ console.error(`Package not installed: ${pkgId}`);
24608
+ process.exit(1);
24609
+ }
24610
+ const manifestPath = import_path24.default.join(installPath, "manifest.json");
24611
+ let manifest = null;
24612
+ if (import_fs27.default.existsSync(manifestPath)) {
24613
+ try {
24614
+ manifest = JSON.parse(import_fs27.default.readFileSync(manifestPath, "utf-8"));
24615
+ } catch {
24616
+ console.warn("Warning: Could not parse manifest.json");
24617
+ }
24618
+ }
24619
+ console.log(`
24620
+ Package: ${pkgId}`);
24621
+ console.log("\u2500".repeat(50));
24622
+ console.log(` Name: ${manifest?.name || name}`);
24623
+ console.log(` Kind: ${kind}`);
24624
+ console.log(` Version: ${manifest?.version || "unknown"}`);
24625
+ console.log(` Install Dir: ${installPath}`);
24626
+ const installType = manifest?.installType || (manifest?.npmPackage ? "npm" : manifest?.pipPackage ? "pip" : kind);
24627
+ console.log(` Install Type: ${installType}`);
24628
+ if (manifest?.source) {
24629
+ if (typeof manifest.source === "string") {
24630
+ console.log(` Source: ${manifest.source}`);
24631
+ } else {
24632
+ console.log(` Source: ${manifest.source.type || "unknown"}`);
24633
+ if (manifest.source.spec) {
24634
+ console.log(` Spec: ${manifest.source.spec}`);
24635
+ }
24636
+ }
24637
+ }
24638
+ if (manifest?.npmPackage) {
24639
+ console.log(` npm Package: ${manifest.npmPackage}`);
24640
+ }
24641
+ if (manifest?.pipPackage) {
24642
+ console.log(` pip Package: ${manifest.pipPackage}`);
24643
+ }
24644
+ if (manifest?.hasInstallScripts !== void 0) {
24645
+ console.log(` Has Install Scripts: ${manifest.hasInstallScripts ? "yes" : "no"}`);
24646
+ }
24647
+ if (manifest?.scriptsPolicy) {
24648
+ console.log(` Scripts Policy: ${manifest.scriptsPolicy}`);
24649
+ }
24650
+ if (manifest?.installedAt) {
24651
+ console.log(` Installed: ${new Date(manifest.installedAt).toLocaleString()}`);
24652
+ }
24653
+ const bins = manifest?.bins || manifest?.binaries || [];
24654
+ if (bins.length > 0) {
24655
+ console.log(`
24656
+ Binaries (${bins.length}):`);
24657
+ console.log("\u2500".repeat(50));
24658
+ for (const bin of bins) {
24659
+ const shimPath = import_path24.default.join(PATHS2.bins, bin);
24660
+ const validation = validateShim(bin);
24661
+ const ownership = getShimOwner(bin);
24662
+ let shimStatus = "\u2717 no shim";
24663
+ if (import_fs27.default.existsSync(shimPath)) {
24664
+ if (validation.valid) {
24665
+ shimStatus = `\u2713 ${validation.target}`;
24666
+ } else {
24667
+ shimStatus = `\u26A0 broken: ${validation.error}`;
24668
+ }
24669
+ }
24670
+ console.log(` ${bin}:`);
24671
+ console.log(` Shim: ${shimStatus}`);
24672
+ if (ownership) {
24673
+ const ownerMatch = ownership.owner === pkgId;
24674
+ const ownerStatus = ownerMatch ? "(this package)" : `(owned by ${ownership.owner})`;
24675
+ console.log(` Type: ${ownership.type} ${ownerStatus}`);
24676
+ }
24677
+ }
24678
+ } else {
24679
+ console.log(`
24680
+ Binaries: none`);
24681
+ }
24682
+ const lockName = name.replace(/\//g, "__").replace(/^@/, "");
24683
+ const lockDir = kind === "binary" ? "binaries" : kind === "npm" ? "npms" : kind + "s";
24684
+ const lockPath = import_path24.default.join(PATHS2.locks, lockDir, `${lockName}.lock.yaml`);
24685
+ if (import_fs27.default.existsSync(lockPath)) {
24686
+ console.log(`
24687
+ Lockfile: ${lockPath}`);
24688
+ }
24689
+ console.log("");
24690
+ } catch (error) {
24691
+ console.error(`Error: ${error.message}`);
24692
+ if (flags.verbose) {
24693
+ console.error(error.stack);
24694
+ }
24695
+ process.exit(1);
24696
+ }
24697
+ }
24698
+
23594
24699
  // src/index.js
23595
24700
  var VERSION = "2.0.0";
23596
24701
  async function main() {
@@ -23686,6 +24791,10 @@ async function main() {
23686
24791
  case "shims":
23687
24792
  await cmdShims(args, flags);
23688
24793
  break;
24794
+ case "pkg":
24795
+ case "package":
24796
+ await cmdInfo(args, flags);
24797
+ break;
23689
24798
  // Shortcuts for listing specific package types
23690
24799
  case "stacks":
23691
24800
  await cmdList(["stacks"], flags);