offgrid-ai 0.8.4 → 0.8.6
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 +9 -5
- package/package.json +1 -1
- package/src/benchmark.mjs +39 -0
- package/src/postinstall.mjs +0 -6
package/README.md
CHANGED
|
@@ -29,24 +29,28 @@ offgrid-ai stop # stop a running server
|
|
|
29
29
|
|
|
30
30
|
## Install
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
### Recommended: one command installer
|
|
33
|
+
|
|
34
|
+
Installs Node.js if you don't have it, then installs offgrid-ai and adds it to your PATH. Prints a welcome message so you know it worked.
|
|
33
35
|
|
|
34
36
|
```bash
|
|
35
37
|
curl -fsSL https://raw.githubusercontent.com/eeshansrivastava89/offgrid-ai/main/install.sh | bash
|
|
36
38
|
```
|
|
37
39
|
|
|
38
|
-
Or
|
|
40
|
+
Or review the install script first:
|
|
39
41
|
|
|
40
42
|
```bash
|
|
41
|
-
|
|
43
|
+
curl -fsSL https://raw.githubusercontent.com/eeshansrivastava89/offgrid-ai/main/install.sh | less
|
|
42
44
|
```
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
### Already have Node.js?
|
|
45
47
|
|
|
46
48
|
```bash
|
|
47
|
-
|
|
49
|
+
npm install -g offgrid-ai@latest --prefer-online
|
|
48
50
|
```
|
|
49
51
|
|
|
52
|
+
This works without extra flags, but npm hides postinstall output by default, so you won't see the welcome message. Open a new terminal window or run `source ~/.zshrc` and then `offgrid-ai`.
|
|
53
|
+
|
|
50
54
|
## How it works
|
|
51
55
|
|
|
52
56
|
1. **Auto-detect everything.** Scans for GGUF models in LM Studio and Hugging Face cache directories, and checks managed backends like Ollama/oMLX through their local APIs. Reads model metadata (quantization, context size, vision, thinking mode) directly from GGUF files. No presets, no manual configuration.
|
package/package.json
CHANGED
package/src/benchmark.mjs
CHANGED
|
@@ -727,6 +727,44 @@ async function queryOllamaMetrics(profile) {
|
|
|
727
727
|
};
|
|
728
728
|
}
|
|
729
729
|
|
|
730
|
+
// ── Unload model from server memory after benchmark ────────────────────────
|
|
731
|
+
|
|
732
|
+
export async function unloadModelFromServer(profile) {
|
|
733
|
+
const backend = backendFor(profile.backend);
|
|
734
|
+
|
|
735
|
+
if (backend.id === "ollama") {
|
|
736
|
+
const apiBaseUrl = (profile.baseUrl
|
|
737
|
+
? profile.baseUrl.replace(/\/v1\/?$/u, "")
|
|
738
|
+
: backend.apiBaseUrl).replace(/\/$/u, "");
|
|
739
|
+
|
|
740
|
+
try {
|
|
741
|
+
await fetch(`${apiBaseUrl}/api/generate`, {
|
|
742
|
+
method: "POST",
|
|
743
|
+
headers: { "Content-Type": "application/json" },
|
|
744
|
+
body: JSON.stringify({ model: profile.modelAlias, prompt: "", stream: false, keep_alive: 0 }),
|
|
745
|
+
signal: AbortSignal.timeout(10000),
|
|
746
|
+
});
|
|
747
|
+
return { unloaded: true, backend: backend.id };
|
|
748
|
+
} catch (err) {
|
|
749
|
+
return { unloaded: false, backend: backend.id, error: err.message };
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
if (backend.id === "llama-cpp" || backend.id === "llama-cpp-mtp") {
|
|
754
|
+
// llama.cpp unloads when the server process exits; no HTTP unload API exists.
|
|
755
|
+
// If offgrid-ai started the server, stopProfile already handled it.
|
|
756
|
+
return { unloaded: false, backend: backend.id, reason: "stop server to unload" };
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
if (backend.id === "omlx") {
|
|
760
|
+
// oMLX does not expose a model-unload endpoint. The model stays resident
|
|
761
|
+
// until the oMLX server process is stopped.
|
|
762
|
+
return { unloaded: false, backend: backend.id, reason: "no unload API available" };
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
return { unloaded: false, backend: backend.id, reason: "unsupported backend" };
|
|
766
|
+
}
|
|
767
|
+
|
|
730
768
|
// ── Finalize benchmark run metadata ──────────────────────────────────────
|
|
731
769
|
|
|
732
770
|
export async function finalizeBenchmarkRun(runDirectory, runResult, speedMetrics) {
|
|
@@ -869,6 +907,7 @@ export async function runPreparedBenchmark(profile, runDirectory, options = {})
|
|
|
869
907
|
console.log(result.stopped ? pc.green(`[stop] ${result.message}`) : pc.dim(`[stop] ${result.message}`));
|
|
870
908
|
}
|
|
871
909
|
}
|
|
910
|
+
await unloadModelFromServer(profile).catch(() => {});
|
|
872
911
|
}
|
|
873
912
|
|
|
874
913
|
return metadata;
|
package/src/postinstall.mjs
CHANGED
|
@@ -26,12 +26,6 @@ if (isHermesPrefix(prefix, process.env.HOME)) {
|
|
|
26
26
|
const npmBin = join(prefix, "bin");
|
|
27
27
|
const marker = "# Added by offgrid-ai installer";
|
|
28
28
|
const pathLine = `export PATH="${npmBin}:$PATH"`;
|
|
29
|
-
const currentPath = process.env.PATH ?? "";
|
|
30
|
-
|
|
31
|
-
if (currentPath.split(":").includes(npmBin)) {
|
|
32
|
-
console.log(`offgrid-ai is already on PATH (${npmBin})`);
|
|
33
|
-
process.exit(0);
|
|
34
|
-
}
|
|
35
29
|
|
|
36
30
|
const home = process.env.HOME;
|
|
37
31
|
if (!home) {
|