offgrid-ai 0.2.8 → 0.2.9
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/package.json +1 -1
- package/src/cli.mjs +51 -17
package/package.json
CHANGED
package/src/cli.mjs
CHANGED
|
@@ -60,14 +60,40 @@ export async function mainFlow() {
|
|
|
60
60
|
// Fall through — they can still use managed backends
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
// 4. No models found at all (but backends exist)
|
|
63
|
+
// 4. No models found at all (but backends may exist)
|
|
64
64
|
if (!hasAnyModels && profiles.length === 0) {
|
|
65
65
|
if (!process.stdin.isTTY) {
|
|
66
|
-
throw new Error("No models found. Download
|
|
66
|
+
throw new Error("No models found. Download a model, then run offgrid-ai.");
|
|
67
67
|
}
|
|
68
68
|
console.log(pc.yellow("No models found."));
|
|
69
|
-
console.log(pc.dim("
|
|
70
|
-
|
|
69
|
+
console.log(pc.dim("You need to download a model to use offgrid-ai.\n"));
|
|
70
|
+
// Detect which backends are installed
|
|
71
|
+
const ollamaInstalled = await hasOllamaInstalled();
|
|
72
|
+
const omlxInstalled = await hasOmlxInstalled();
|
|
73
|
+
const lmStudioInstalled = existsSync("/Applications/LM Studio.app");
|
|
74
|
+
const hasBackends = llamaBinary || ollamaInstalled || omlxInstalled || lmStudioInstalled;
|
|
75
|
+
if (hasBackends) {
|
|
76
|
+
console.log(pc.bold("Backend status:"));
|
|
77
|
+
console.log(` ${lmStudioInstalled ? pc.green("✓") : pc.red("✗")} LM Studio ${lmStudioInstalled ? "— installed" : "— not installed"}`);
|
|
78
|
+
console.log(` ${ollamaInstalled ? pc.green("✓") : pc.red("✗")} Ollama ${ollamaInstalled ? "— installed" : "— not installed"}`);
|
|
79
|
+
console.log(` ${omlxInstalled ? pc.green("✓") : pc.red("✗")} oMLX ${omlxInstalled ? "— installed" : "— not installed"}`);
|
|
80
|
+
console.log(` ${llamaBinary ? pc.green("✓") : pc.red("✗")} llama-server ${llamaBinary ? "— installed" : "— not installed"}`);
|
|
81
|
+
console.log();
|
|
82
|
+
const model = recommendedModel();
|
|
83
|
+
console.log(pc.bold("Next step — download a model:"));
|
|
84
|
+
if (lmStudioInstalled) {
|
|
85
|
+
console.log(" Open LM Studio → browse models → download");
|
|
86
|
+
console.log(pc.dim(` Recommended: ${model.label}`));
|
|
87
|
+
}
|
|
88
|
+
if (ollamaInstalled) {
|
|
89
|
+
console.log(pc.bold(` ollama pull ${model.ollama}`));
|
|
90
|
+
}
|
|
91
|
+
if (omlxInstalled) {
|
|
92
|
+
console.log(pc.bold(" omlx start"));
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
console.log(pc.dim("Run offgrid-ai to install a backend and download a model."));
|
|
96
|
+
}
|
|
71
97
|
return;
|
|
72
98
|
}
|
|
73
99
|
|
|
@@ -629,9 +655,8 @@ async function onboardFlow() {
|
|
|
629
655
|
try {
|
|
630
656
|
await run("brew", ["install", "--cask", "lm-studio"], "LM Studio");
|
|
631
657
|
console.log(pc.green("✓ LM Studio installed"));
|
|
632
|
-
console.log(pc.yellow("\nOpen LM Studio
|
|
658
|
+
console.log(pc.yellow("\nOpen LM Studio and download a model to get started."));
|
|
633
659
|
console.log(pc.dim(`Recommended for your machine: ${model.label}`));
|
|
634
|
-
console.log(pc.bold(` lms get ${model.lms}`));
|
|
635
660
|
console.log(pc.dim("Then run offgrid-ai again to pick and run a model."));
|
|
636
661
|
} catch {
|
|
637
662
|
console.log(pc.red("✗ LM Studio installation failed."));
|
|
@@ -693,18 +718,7 @@ async function onboardFlow() {
|
|
|
693
718
|
}
|
|
694
719
|
if (installed.length > 0) {
|
|
695
720
|
console.log(pc.green(`\n✓ Installed: ${installed.join(", ")}`));
|
|
696
|
-
console.log(pc.yellow("\nDownload a model to get started:"));
|
|
697
721
|
console.log(pc.dim(`Recommended for your machine (${(totalmem() / (1024 ** 3)).toFixed(0)}GB RAM): ${model.label}`));
|
|
698
|
-
if (installed.includes("LM Studio")) {
|
|
699
|
-
console.log(pc.bold(` LM Studio → lms get ${model.lms}`));
|
|
700
|
-
}
|
|
701
|
-
if (installed.includes("Ollama")) {
|
|
702
|
-
console.log(pc.bold(` Ollama → ollama pull ${model.ollama}`));
|
|
703
|
-
}
|
|
704
|
-
if (installed.includes("oMLX")) {
|
|
705
|
-
console.log(pc.bold(" oMLX → omlx start"));
|
|
706
|
-
}
|
|
707
|
-
console.log(pc.dim("Then run offgrid-ai again to pick and run a model."));
|
|
708
722
|
}
|
|
709
723
|
} else {
|
|
710
724
|
console.log(pc.dim("Run offgrid-ai again when you've set up a model backend."));
|
|
@@ -814,6 +828,26 @@ async function removeSelf() {
|
|
|
814
828
|
}
|
|
815
829
|
}
|
|
816
830
|
|
|
831
|
+
// ── Backend install detection (for status display) ────────────────────────
|
|
832
|
+
|
|
833
|
+
async function hasOllamaInstalled() {
|
|
834
|
+
try {
|
|
835
|
+
const { promisify } = await import("node:util");
|
|
836
|
+
const { execFile } = await import("node:child_process");
|
|
837
|
+
await promisify(execFile)("which", ["ollama"]);
|
|
838
|
+
return true;
|
|
839
|
+
} catch { return false; }
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
async function hasOmlxInstalled() {
|
|
843
|
+
try {
|
|
844
|
+
const { promisify } = await import("node:util");
|
|
845
|
+
const { execFile } = await import("node:child_process");
|
|
846
|
+
await promisify(execFile)("which", ["omlx"]);
|
|
847
|
+
return true;
|
|
848
|
+
} catch { return false; }
|
|
849
|
+
}
|
|
850
|
+
|
|
817
851
|
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
818
852
|
|
|
819
853
|
async function scanManagedModels() {
|