@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/README.md +145 -53
- package/dist/index.cjs +1645 -536
- package/dist/packages-manifest.json +1 -1
- package/package.json +10 -10
- package/scripts/postinstall.js +14 -4
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
|
-
|
|
102
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
"
|
|
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,
|
|
1115
|
-
const ctrl = callVisitor(key, node, visitor,
|
|
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,
|
|
1118
|
-
return visit_(key, ctrl, visitor,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
1136
|
-
const ck = visit_("key", node.key, visitor,
|
|
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,
|
|
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,
|
|
1163
|
-
const ctrl = await callVisitor(key, node, visitor,
|
|
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,
|
|
1166
|
-
return visitAsync_(key, ctrl, visitor,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
1184
|
-
const ck = await visitAsync_("key", node.key, visitor,
|
|
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,
|
|
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,
|
|
1212
|
+
function callVisitor(key, node, visitor, path35) {
|
|
1217
1213
|
if (typeof visitor === "function")
|
|
1218
|
-
return visitor(key, node,
|
|
1214
|
+
return visitor(key, node, path35);
|
|
1219
1215
|
if (identity.isMap(node))
|
|
1220
|
-
return visitor.Map?.(key, node,
|
|
1216
|
+
return visitor.Map?.(key, node, path35);
|
|
1221
1217
|
if (identity.isSeq(node))
|
|
1222
|
-
return visitor.Seq?.(key, node,
|
|
1218
|
+
return visitor.Seq?.(key, node, path35);
|
|
1223
1219
|
if (identity.isPair(node))
|
|
1224
|
-
return visitor.Pair?.(key, node,
|
|
1220
|
+
return visitor.Pair?.(key, node, path35);
|
|
1225
1221
|
if (identity.isScalar(node))
|
|
1226
|
-
return visitor.Scalar?.(key, node,
|
|
1222
|
+
return visitor.Scalar?.(key, node, path35);
|
|
1227
1223
|
if (identity.isAlias(node))
|
|
1228
|
-
return visitor.Alias?.(key, node,
|
|
1224
|
+
return visitor.Alias?.(key, node, path35);
|
|
1229
1225
|
return void 0;
|
|
1230
1226
|
}
|
|
1231
|
-
function replaceNode(key,
|
|
1232
|
-
const parent =
|
|
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,
|
|
1836
|
+
function collectionFromPath(schema, path35, value) {
|
|
1841
1837
|
let v = value;
|
|
1842
|
-
for (let i =
|
|
1843
|
-
const k =
|
|
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 = (
|
|
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(
|
|
1893
|
-
if (isEmptyPath(
|
|
1888
|
+
addIn(path35, value) {
|
|
1889
|
+
if (isEmptyPath(path35))
|
|
1894
1890
|
this.add(value);
|
|
1895
1891
|
else {
|
|
1896
|
-
const [key, ...rest] =
|
|
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(
|
|
1911
|
-
const [key, ...rest] =
|
|
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(
|
|
1926
|
-
const [key, ...rest] =
|
|
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(
|
|
1945
|
-
const [key, ...rest] =
|
|
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(
|
|
1956
|
-
const [key, ...rest] =
|
|
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(
|
|
4456
|
+
addIn(path35, value) {
|
|
4461
4457
|
if (assertCollection(this.contents))
|
|
4462
|
-
this.contents.addIn(
|
|
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(
|
|
4538
|
-
if (Collection.isEmptyPath(
|
|
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(
|
|
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(
|
|
4560
|
-
if (Collection.isEmptyPath(
|
|
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(
|
|
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(
|
|
4574
|
-
if (Collection.isEmptyPath(
|
|
4569
|
+
hasIn(path35) {
|
|
4570
|
+
if (Collection.isEmptyPath(path35))
|
|
4575
4571
|
return this.contents !== void 0;
|
|
4576
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
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(
|
|
4594
|
-
if (Collection.isEmptyPath(
|
|
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(
|
|
4593
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path35), value);
|
|
4598
4594
|
} else if (assertCollection(this.contents)) {
|
|
4599
|
-
this.contents.setIn(
|
|
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,
|
|
6547
|
+
visit.itemAtPath = (cst, path35) => {
|
|
6552
6548
|
let item = cst;
|
|
6553
|
-
for (const [field, index] of
|
|
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,
|
|
6563
|
-
const parent = visit.itemAtPath(cst,
|
|
6564
|
-
const field =
|
|
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(
|
|
6571
|
-
let ctrl = visitor(item,
|
|
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(
|
|
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,
|
|
6585
|
+
ctrl = ctrl(item, path35);
|
|
6590
6586
|
}
|
|
6591
6587
|
}
|
|
6592
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
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
|
|
7873
|
+
const fs35 = this.flowScalar(this.type);
|
|
7878
7874
|
if (atNextItem || it.value) {
|
|
7879
|
-
map.items.push({ start, key:
|
|
7875
|
+
map.items.push({ start, key: fs35, sep: [] });
|
|
7880
7876
|
this.onKeyLine = true;
|
|
7881
7877
|
} else if (it.sep) {
|
|
7882
|
-
this.stack.push(
|
|
7878
|
+
this.stack.push(fs35);
|
|
7883
7879
|
} else {
|
|
7884
|
-
Object.assign(it, { key:
|
|
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
|
|
8008
|
+
const fs35 = this.flowScalar(this.type);
|
|
8013
8009
|
if (!it || it.value)
|
|
8014
|
-
fc.items.push({ start: [], key:
|
|
8010
|
+
fc.items.push({ start: [], key: fs35, sep: [] });
|
|
8015
8011
|
else if (it.sep)
|
|
8016
|
-
this.stack.push(
|
|
8012
|
+
this.stack.push(fs35);
|
|
8017
8013
|
else
|
|
8018
|
-
Object.assign(it, { key:
|
|
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
|
-
//
|
|
8322
|
+
// packages/core/src/lockfile.js
|
|
8327
8323
|
async function writeLockfile(resolved) {
|
|
8328
|
-
const
|
|
8329
|
-
const
|
|
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
|
-
"
|
|
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
|
-
//
|
|
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
|
-
"
|
|
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
|
-
//
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
8665
|
-
|
|
8666
|
-
|
|
8667
|
-
|
|
8668
|
-
|
|
8669
|
-
|
|
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
|
|
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
|
-
"
|
|
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
|
-
//
|
|
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
|
-
"
|
|
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
|
-
//
|
|
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
|
-
"
|
|
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
|
-
//
|
|
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
|
-
"
|
|
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
|
-
//
|
|
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
|
-
"
|
|
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
|
-
//
|
|
9987
|
-
var
|
|
9988
|
-
__export(
|
|
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
|
-
"
|
|
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(
|
|
13269
|
-
let input =
|
|
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 [
|
|
13469
|
-
wsComponent.path =
|
|
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,
|
|
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,
|
|
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
|
-
//
|
|
16836
|
-
|
|
16837
|
-
|
|
16838
|
-
|
|
16839
|
-
|
|
16840
|
-
|
|
16841
|
-
|
|
16842
|
-
|
|
16843
|
-
|
|
16844
|
-
|
|
16845
|
-
|
|
16846
|
-
|
|
16847
|
-
|
|
16848
|
-
|
|
16849
|
-
|
|
16850
|
-
|
|
16851
|
-
|
|
16852
|
-
|
|
16853
|
-
|
|
16854
|
-
|
|
16855
|
-
|
|
16856
|
-
|
|
16857
|
-
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
16861
|
-
|
|
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
|
-
}
|
|
16864
|
-
|
|
16865
|
-
|
|
16866
|
-
|
|
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
|
|
16872
|
-
|
|
16873
|
-
|
|
16874
|
-
|
|
16875
|
-
|
|
16876
|
-
|
|
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
|
|
16879
|
-
|
|
16880
|
-
|
|
16881
|
-
|
|
16882
|
-
|
|
16883
|
-
|
|
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
|
-
|
|
16887
|
-
|
|
16888
|
-
|
|
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
|
|
16891
|
-
|
|
16892
|
-
|
|
16893
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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 (
|
|
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 (
|
|
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 =
|
|
17932
|
-
if (!
|
|
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
|
-
//
|
|
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+
|
|
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
|
|
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(
|
|
19082
|
+
if (!import_fs9.default.existsSync(SECRETS_PATH3)) {
|
|
18195
19083
|
return {};
|
|
18196
19084
|
}
|
|
18197
19085
|
try {
|
|
18198
|
-
const content = import_fs9.default.readFileSync(
|
|
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
|
-
//
|
|
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:
|
|
18256
|
-
if (!
|
|
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(
|
|
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
|
-
//
|
|
18366
|
-
var
|
|
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,
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
21030
|
+
// packages/db/src/import.js
|
|
20143
21031
|
init_src();
|
|
20144
21032
|
var RUDI_HOME2 = PATHS.home;
|
|
20145
21033
|
|
|
20146
|
-
//
|
|
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
|
|
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,
|
|
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
|
|
21151
|
-
var
|
|
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
|
|
22041
|
+
var import_fs21 = require("fs");
|
|
21154
22042
|
var import_child_process6 = require("child_process");
|
|
21155
|
-
|
|
21156
|
-
|
|
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: ${
|
|
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
|
-
|
|
22163
|
+
ensureDirectories2();
|
|
21174
22164
|
const dirs = [
|
|
21175
|
-
|
|
21176
|
-
|
|
21177
|
-
|
|
21178
|
-
|
|
21179
|
-
|
|
21180
|
-
|
|
21181
|
-
|
|
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 =
|
|
21185
|
-
if (!
|
|
21186
|
-
|
|
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
|
|
21197
|
-
const platform =
|
|
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 =
|
|
21208
|
-
if (
|
|
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
|
|
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 =
|
|
21233
|
-
if (
|
|
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 =
|
|
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 =
|
|
21258
|
-
const dbExists =
|
|
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 =
|
|
21274
|
-
if (!
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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 =
|
|
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 (!
|
|
21335
|
-
|
|
22324
|
+
if (!import_fs20.default.existsSync(destPath)) {
|
|
22325
|
+
import_fs20.default.mkdirSync(destPath, { recursive: true });
|
|
21336
22326
|
}
|
|
21337
|
-
const fileStream = (0,
|
|
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
|
-
|
|
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 =
|
|
21366
|
-
const shimPath =
|
|
21367
|
-
if (
|
|
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 =
|
|
21374
|
-
const shimPath =
|
|
21375
|
-
if (
|
|
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 (
|
|
21391
|
-
|
|
22380
|
+
if (import_fs20.default.existsSync(shimPath)) {
|
|
22381
|
+
import_fs20.default.unlinkSync(shimPath);
|
|
21392
22382
|
}
|
|
21393
|
-
|
|
22383
|
+
import_fs20.default.symlinkSync(targetPath, shimPath);
|
|
21394
22384
|
}
|
|
21395
22385
|
|
|
21396
22386
|
// src/commands/update.js
|
|
21397
|
-
var
|
|
21398
|
-
var
|
|
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
|
-
|
|
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] =
|
|
21423
|
-
const installPath =
|
|
21424
|
-
if (!
|
|
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
|
|
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 =
|
|
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:
|
|
21464
|
-
|
|
21465
|
-
await
|
|
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" ?
|
|
21484
|
-
if (!
|
|
21485
|
-
const entries =
|
|
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 =
|
|
21505
|
-
if (
|
|
21506
|
-
const pkgJson = JSON.parse(
|
|
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 =
|
|
21510
|
-
if (
|
|
21511
|
-
const rootPkg = JSON.parse(
|
|
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 =
|
|
22509
|
+
const metaPath = import_path20.default.join(installPath, "runtime.json");
|
|
21521
22510
|
try {
|
|
21522
22511
|
let meta = {};
|
|
21523
|
-
if (
|
|
21524
|
-
meta = JSON.parse(
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
21760
|
-
var
|
|
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 =
|
|
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 =
|
|
22837
|
+
const runtimePath = path26.join(stackPath, runtime);
|
|
21850
22838
|
try {
|
|
21851
|
-
await
|
|
22839
|
+
await fs26.access(runtimePath);
|
|
21852
22840
|
if (runtime === "node") {
|
|
21853
|
-
const distEntry =
|
|
21854
|
-
const srcEntry =
|
|
22841
|
+
const distEntry = path26.join(runtimePath, "dist", "index.js");
|
|
22842
|
+
const srcEntry = path26.join(runtimePath, "src", "index.ts");
|
|
21855
22843
|
try {
|
|
21856
|
-
await
|
|
22844
|
+
await fs26.access(distEntry);
|
|
21857
22845
|
return { runtime: "node", entry: `${runtime}/dist/index.js` };
|
|
21858
22846
|
} catch {
|
|
21859
22847
|
try {
|
|
21860
|
-
await
|
|
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 =
|
|
22855
|
+
const entry = path26.join(runtimePath, "src", "index.py");
|
|
21868
22856
|
try {
|
|
21869
|
-
await
|
|
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 =
|
|
21886
|
-
const tokenPath =
|
|
22873
|
+
const runtimePath = path26.join(stackPath, runtime);
|
|
22874
|
+
const tokenPath = path26.join(runtimePath, "token.json");
|
|
21887
22875
|
try {
|
|
21888
|
-
await
|
|
22876
|
+
await fs26.access(tokenPath);
|
|
21889
22877
|
authFiles.push(`${runtime}/token.json`);
|
|
21890
22878
|
configured = true;
|
|
21891
22879
|
} catch {
|
|
21892
|
-
const accountsPath =
|
|
22880
|
+
const accountsPath = path26.join(runtimePath, "accounts");
|
|
21893
22881
|
try {
|
|
21894
|
-
const accounts = await
|
|
22882
|
+
const accounts = await fs26.readdir(accountsPath);
|
|
21895
22883
|
for (const account of accounts) {
|
|
21896
22884
|
if (account.startsWith(".")) continue;
|
|
21897
|
-
const accountTokenPath =
|
|
22885
|
+
const accountTokenPath = path26.join(accountsPath, account, "token.json");
|
|
21898
22886
|
try {
|
|
21899
|
-
await
|
|
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 =
|
|
22897
|
+
const envPath = path26.join(stackPath, ".env");
|
|
21910
22898
|
try {
|
|
21911
|
-
const envContent = await
|
|
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
|
|
21956
|
-
var
|
|
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 =
|
|
22976
|
+
const runtimePath = path27.join(stackPath, runtime);
|
|
21990
22977
|
try {
|
|
21991
|
-
await
|
|
22978
|
+
await fs27.access(runtimePath);
|
|
21992
22979
|
if (runtime === "node") {
|
|
21993
|
-
const authTs =
|
|
21994
|
-
const authJs =
|
|
22980
|
+
const authTs = path27.join(runtimePath, "src", "auth.ts");
|
|
22981
|
+
const authJs = path27.join(runtimePath, "dist", "auth.js");
|
|
21995
22982
|
try {
|
|
21996
|
-
await
|
|
22983
|
+
await fs27.access(authTs);
|
|
21997
22984
|
return { runtime: "node", authScript: authTs, useTsx: true };
|
|
21998
22985
|
} catch {
|
|
21999
22986
|
try {
|
|
22000
|
-
await
|
|
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 =
|
|
22993
|
+
const authPy = path27.join(runtimePath, "src", "auth.py");
|
|
22007
22994
|
try {
|
|
22008
|
-
await
|
|
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 =
|
|
23045
|
+
const cwd = path27.dirname(authInfo.authScript);
|
|
22059
23046
|
if (authInfo.runtime === "node") {
|
|
22060
|
-
const distAuth =
|
|
23047
|
+
const distAuth = path27.join(cwd, "..", "dist", "auth.js");
|
|
22061
23048
|
let useBuiltInPort = false;
|
|
22062
23049
|
let tempAuthScript = null;
|
|
22063
23050
|
try {
|
|
22064
|
-
await
|
|
22065
|
-
const distContent = await
|
|
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
|
|
23061
|
+
const authContent = await fs27.readFile(authInfo.authScript, "utf-8");
|
|
22075
23062
|
const tempExt = authInfo.useTsx ? ".ts" : ".mjs";
|
|
22076
|
-
tempAuthScript =
|
|
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
|
|
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
|
|
23080
|
+
await fs27.unlink(tempAuthScript);
|
|
22094
23081
|
}
|
|
22095
23082
|
} catch (error) {
|
|
22096
23083
|
if (tempAuthScript) {
|
|
22097
23084
|
try {
|
|
22098
|
-
await
|
|
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
|
|
22131
|
-
var
|
|
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" ?
|
|
22138
|
-
if (
|
|
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" ?
|
|
22144
|
-
if (
|
|
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" ?
|
|
22153
|
-
if (
|
|
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 =
|
|
22160
|
-
if (!
|
|
23145
|
+
const manifestPath = path28.join(stackPath, "manifest.json");
|
|
23146
|
+
if (!fs28.existsSync(manifestPath)) {
|
|
22161
23147
|
return null;
|
|
22162
23148
|
}
|
|
22163
|
-
return JSON.parse(
|
|
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 =
|
|
22197
|
-
if (!
|
|
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("../") || !
|
|
22247
|
-
const resolved =
|
|
22248
|
-
if (
|
|
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 =
|
|
22256
|
-
const bundledPythonBin =
|
|
22257
|
-
if (
|
|
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 (
|
|
22260
|
-
if (
|
|
22261
|
-
env.PATH = runtimePaths.join(
|
|
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
|
|
22292
|
-
var
|
|
22293
|
-
var
|
|
22294
|
-
|
|
22295
|
-
var
|
|
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 (!
|
|
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 (!
|
|
23292
|
+
if (!fs29.existsSync(configPath)) return null;
|
|
22308
23293
|
const backupPath = configPath + ".backup." + Date.now();
|
|
22309
|
-
|
|
23294
|
+
fs29.copyFileSync(configPath, backupPath);
|
|
22310
23295
|
return backupPath;
|
|
22311
23296
|
}
|
|
22312
23297
|
function readJsonConfig(configPath) {
|
|
22313
|
-
if (!
|
|
23298
|
+
if (!fs29.existsSync(configPath)) {
|
|
22314
23299
|
return {};
|
|
22315
23300
|
}
|
|
22316
23301
|
try {
|
|
22317
|
-
return JSON.parse(
|
|
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 =
|
|
22324
|
-
if (!
|
|
22325
|
-
|
|
23308
|
+
const dir = path29.dirname(configPath);
|
|
23309
|
+
if (!fs29.existsSync(dir)) {
|
|
23310
|
+
fs29.mkdirSync(dir, { recursive: true });
|
|
22326
23311
|
}
|
|
22327
|
-
|
|
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 ||
|
|
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 (
|
|
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 =
|
|
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
|
|
22494
|
-
var
|
|
22495
|
-
var
|
|
22496
|
-
|
|
22497
|
-
var
|
|
22498
|
-
var
|
|
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 =
|
|
22502
|
-
if (!
|
|
22503
|
-
return
|
|
22504
|
-
const hasManifest =
|
|
22505
|
-
const hasPackage =
|
|
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 =
|
|
22511
|
-
const newPath =
|
|
22512
|
-
if (!
|
|
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 (
|
|
23499
|
+
if (fs30.existsSync(newPath)) {
|
|
22516
23500
|
return { success: true, skipped: true, reason: "Already exists" };
|
|
22517
23501
|
}
|
|
22518
|
-
if (!
|
|
22519
|
-
|
|
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 =
|
|
23509
|
+
const stat = fs30.statSync(src);
|
|
22526
23510
|
if (stat.isDirectory()) {
|
|
22527
|
-
|
|
22528
|
-
for (const child of
|
|
22529
|
-
copyRecursive(
|
|
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
|
-
|
|
23516
|
+
fs30.copyFileSync(src, dest);
|
|
22533
23517
|
}
|
|
22534
23518
|
}
|
|
22535
23519
|
function ensureShim() {
|
|
22536
|
-
const shimsDir =
|
|
22537
|
-
if (!
|
|
22538
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
23583
|
+
fs30.copyFileSync(configPath, backupPath);
|
|
22600
23584
|
config[key] = mcpServers;
|
|
22601
|
-
|
|
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 =
|
|
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 =
|
|
23639
|
+
const newStacksDir = PATHS2.stacks;
|
|
22656
23640
|
let newStacks = [];
|
|
22657
|
-
if (
|
|
22658
|
-
newStacks =
|
|
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(
|
|
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 =
|
|
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: ${
|
|
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 (
|
|
22736
|
-
installedStacks =
|
|
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
|
|
22905
|
-
var
|
|
22906
|
-
var
|
|
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("~",
|
|
22952
|
-
return
|
|
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
|
-
|
|
22981
|
-
|
|
22982
|
-
|
|
22983
|
-
|
|
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 (
|
|
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 =
|
|
23005
|
-
const rudiInstalled =
|
|
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:
|
|
23088
|
-
stacks: { path: PATHS.stacks, exists:
|
|
23089
|
-
agents: { path: PATHS.agents, exists:
|
|
23090
|
-
runtimes: { path: PATHS.runtimes, exists:
|
|
23091
|
-
binaries: { path: PATHS.binaries, exists:
|
|
23092
|
-
db: { path: PATHS.db, exists:
|
|
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
|
|
23201
|
-
var
|
|
23202
|
-
var
|
|
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("~",
|
|
23211
|
-
return
|
|
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 =
|
|
23238
|
-
if (
|
|
23239
|
-
const runtimePath =
|
|
23240
|
-
if (
|
|
23241
|
-
const binaryPath =
|
|
23242
|
-
const binaryPath2 =
|
|
23243
|
-
if (
|
|
23244
|
-
const stackPath =
|
|
23245
|
-
if (
|
|
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 =
|
|
23292
|
-
const rudiInstalled =
|
|
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 =
|
|
23324
|
-
if (
|
|
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 =
|
|
23344
|
-
if (
|
|
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
|
|
23399
|
-
var
|
|
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 (!
|
|
24386
|
+
if (!import_fs26.default.existsSync(binsDir)) {
|
|
23403
24387
|
return [];
|
|
23404
24388
|
}
|
|
23405
|
-
const entries =
|
|
24389
|
+
const entries = import_fs26.default.readdirSync(binsDir);
|
|
23406
24390
|
return entries.filter((entry) => {
|
|
23407
|
-
const fullPath =
|
|
23408
|
-
const stat =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
-
|
|
23459
|
-
|
|
23460
|
-
|
|
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 (!
|
|
23464
|
-
const packages =
|
|
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 =
|
|
23467
|
-
if (
|
|
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(
|
|
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 =
|
|
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
|
|
23571
|
-
const
|
|
23572
|
-
|
|
23573
|
-
|
|
23574
|
-
|
|
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
|
-
|
|
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
|
-
|
|
23582
|
-
|
|
23583
|
-
|
|
23584
|
-
|
|
23585
|
-
|
|
23586
|
-
|
|
23587
|
-
|
|
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);
|