@learnrudi/cli 1.9.11 → 1.9.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -662,37 +662,64 @@ async function downloadDirectoryFromGitHub(dirUrl, destDir, onProgress) {
662
662
  async function downloadRuntime(runtime, version, destPath, options = {}) {
663
663
  const { onProgress } = options;
664
664
  const platformArch = getPlatformArch2();
665
- const shortVersion = version.replace(/\.x$/, "").replace(/\.0$/, "");
666
- const filename = `${runtime}-${shortVersion}-${platformArch}.tar.gz`;
667
- const url = `${RUNTIMES_DOWNLOAD_BASE}/${RUNTIMES_RELEASE_VERSION}/${filename}`;
668
- onProgress?.({ phase: "downloading", runtime, version, url });
665
+ const { execSync: execSync10 } = await import("child_process");
666
+ const runtimeManifest = await loadRuntimeManifest(runtime);
667
+ const customDownload = runtimeManifest?.download?.[platformArch];
669
668
  const tempDir = import_path3.default.join(PATHS2.cache, "downloads");
670
669
  if (!import_fs2.default.existsSync(tempDir)) {
671
670
  import_fs2.default.mkdirSync(tempDir, { recursive: true });
672
671
  }
673
- const tempFile = import_path3.default.join(tempDir, filename);
672
+ if (import_fs2.default.existsSync(destPath)) {
673
+ import_fs2.default.rmSync(destPath, { recursive: true });
674
+ }
675
+ import_fs2.default.mkdirSync(destPath, { recursive: true });
676
+ let url;
677
+ let downloadType;
678
+ if (customDownload) {
679
+ url = typeof customDownload === "string" ? customDownload : customDownload.url;
680
+ downloadType = customDownload.type || "tar.gz";
681
+ } else {
682
+ const shortVersion = version.replace(/\.x$/, "").replace(/\.0$/, "");
683
+ const filename = `${runtime}-${shortVersion}-${platformArch}.tar.gz`;
684
+ url = `${RUNTIMES_DOWNLOAD_BASE}/${RUNTIMES_RELEASE_VERSION}/${filename}`;
685
+ downloadType = "tar.gz";
686
+ }
687
+ onProgress?.({ phase: "downloading", runtime, version, url });
688
+ const tempFile = import_path3.default.join(tempDir, `${runtime}-${version}-${platformArch}.download`);
674
689
  try {
675
- const response = await fetch(url, {
676
- headers: {
677
- "User-Agent": "rudi-cli/2.0",
678
- "Accept": "application/octet-stream"
690
+ if (url.includes("github.com")) {
691
+ execSync10(`curl -sL "${url}" -o "${tempFile}"`, { stdio: "pipe" });
692
+ } else {
693
+ const response = await fetch(url, {
694
+ headers: {
695
+ "User-Agent": "rudi-cli/2.0",
696
+ "Accept": "application/octet-stream"
697
+ }
698
+ });
699
+ if (!response.ok) {
700
+ throw new Error(`Failed to download ${runtime}: HTTP ${response.status}`);
679
701
  }
680
- });
681
- if (!response.ok) {
682
- throw new Error(`Failed to download ${runtime}: HTTP ${response.status}`);
702
+ const buffer = await response.arrayBuffer();
703
+ import_fs2.default.writeFileSync(tempFile, Buffer.from(buffer));
683
704
  }
684
- const buffer = await response.arrayBuffer();
685
- import_fs2.default.writeFileSync(tempFile, Buffer.from(buffer));
686
705
  onProgress?.({ phase: "extracting", runtime, version });
687
- if (import_fs2.default.existsSync(destPath)) {
688
- import_fs2.default.rmSync(destPath, { recursive: true });
706
+ if (downloadType === "binary") {
707
+ const binaryName = runtimeManifest?.binary || runtime;
708
+ const binaryPath = import_path3.default.join(destPath, binaryName);
709
+ import_fs2.default.renameSync(tempFile, binaryPath);
710
+ import_fs2.default.chmodSync(binaryPath, 493);
711
+ } else if (downloadType === "tar.gz" || downloadType === "tgz") {
712
+ execSync10(`tar -xzf "${tempFile}" -C "${destPath}" --strip-components=1`, { stdio: "pipe" });
713
+ import_fs2.default.unlinkSync(tempFile);
714
+ } else if (downloadType === "tar.xz") {
715
+ execSync10(`tar -xJf "${tempFile}" -C "${destPath}" --strip-components=1`, { stdio: "pipe" });
716
+ import_fs2.default.unlinkSync(tempFile);
717
+ } else if (downloadType === "zip") {
718
+ execSync10(`unzip -o "${tempFile}" -d "${destPath}"`, { stdio: "pipe" });
719
+ import_fs2.default.unlinkSync(tempFile);
720
+ } else {
721
+ throw new Error(`Unsupported download type: ${downloadType}`);
689
722
  }
690
- import_fs2.default.mkdirSync(destPath, { recursive: true });
691
- const { execSync: execSync10 } = await import("child_process");
692
- execSync10(`tar -xzf "${tempFile}" -C "${destPath}" --strip-components=1`, {
693
- stdio: "pipe"
694
- });
695
- import_fs2.default.unlinkSync(tempFile);
696
723
  import_fs2.default.writeFileSync(
697
724
  import_path3.default.join(destPath, "runtime.json"),
698
725
  JSON.stringify({
@@ -700,7 +727,9 @@ async function downloadRuntime(runtime, version, destPath, options = {}) {
700
727
  version,
701
728
  platformArch,
702
729
  downloadedAt: (/* @__PURE__ */ new Date()).toISOString(),
703
- source: url
730
+ source: url,
731
+ ...runtimeManifest?.commands && { commands: runtimeManifest.commands },
732
+ ...runtimeManifest?.postInstall && { postInstall: runtimeManifest.postInstall }
704
733
  }, null, 2)
705
734
  );
706
735
  onProgress?.({ phase: "complete", runtime, version, path: destPath });
@@ -882,6 +911,33 @@ async function extractBinaryFromPath(extractedPath, binaryPattern, destPath) {
882
911
  }
883
912
  }
884
913
  }
914
+ async function loadRuntimeManifest(runtimeName) {
915
+ for (const basePath of getLocalRegistryPaths()) {
916
+ const registryDir = import_path3.default.dirname(basePath);
917
+ const manifestPath = import_path3.default.join(registryDir, "catalog", "runtimes", `${runtimeName}.json`);
918
+ if (import_fs2.default.existsSync(manifestPath)) {
919
+ try {
920
+ return JSON.parse(import_fs2.default.readFileSync(manifestPath, "utf-8"));
921
+ } catch {
922
+ continue;
923
+ }
924
+ }
925
+ }
926
+ try {
927
+ const url = `https://raw.githubusercontent.com/learn-rudi/registry/main/catalog/runtimes/${runtimeName}.json`;
928
+ const response = await fetch(url, {
929
+ headers: {
930
+ "User-Agent": "rudi-cli/2.0",
931
+ "Accept": "application/json"
932
+ }
933
+ });
934
+ if (response.ok) {
935
+ return await response.json();
936
+ }
937
+ } catch {
938
+ }
939
+ return null;
940
+ }
885
941
  async function loadToolManifest(toolName) {
886
942
  for (const basePath of getLocalRegistryPaths()) {
887
943
  const registryDir = import_path3.default.dirname(basePath);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "1.0.0",
3
- "generated": "2026-01-09T20:03:27.053Z",
3
+ "generated": "2026-01-09T20:10:12.259Z",
4
4
  "packages": {
5
5
  "runtimes": [
6
6
  {
@@ -182,21 +182,6 @@
182
182
  "args": null
183
183
  }
184
184
  ]
185
- },
186
- {
187
- "id": "ollama",
188
- "name": "Ollama",
189
- "kind": "agent",
190
- "installDir": "ollama",
191
- "basePath": "agents",
192
- "installType": "binary",
193
- "commands": [
194
- {
195
- "name": "ollama",
196
- "bin": "ollama",
197
- "args": null
198
- }
199
- ]
200
185
  }
201
186
  ],
202
187
  "binaries": []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@learnrudi/cli",
3
- "version": "1.9.11",
3
+ "version": "1.9.12",
4
4
  "description": "RUDI CLI - Install and manage MCP stacks, runtimes, and AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -16,14 +16,14 @@
16
16
  "better-sqlite3": "^12.5.0",
17
17
  "@learnrudi/core": "1.0.5",
18
18
  "@learnrudi/db": "1.0.2",
19
- "@learnrudi/embeddings": "0.1.0",
20
19
  "@learnrudi/env": "1.0.1",
20
+ "@learnrudi/embeddings": "0.1.0",
21
21
  "@learnrudi/manifest": "1.0.0",
22
- "@learnrudi/runner": "1.0.1",
22
+ "@learnrudi/mcp": "1.0.0",
23
23
  "@learnrudi/registry-client": "1.0.5",
24
- "@learnrudi/secrets": "1.0.1",
24
+ "@learnrudi/runner": "1.0.1",
25
25
  "@learnrudi/utils": "1.0.0",
26
- "@learnrudi/mcp": "1.0.0"
26
+ "@learnrudi/secrets": "1.0.1"
27
27
  },
28
28
  "devDependencies": {
29
29
  "esbuild": "^0.27.2"