turbollm 1.3.0 → 1.3.2
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/cli.js +27 -38
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -319,12 +319,19 @@ import { promisify as promisify2 } from "util";
|
|
|
319
319
|
|
|
320
320
|
// src/engines/download.ts
|
|
321
321
|
import { createWriteStream, existsSync as existsSync2, mkdirSync as mkdirSync2, readdirSync, rmSync } from "fs";
|
|
322
|
-
import { execFile } from "child_process";
|
|
322
|
+
import { execFile, execFileSync } from "child_process";
|
|
323
323
|
import { join as join2 } from "path";
|
|
324
324
|
import { Readable } from "stream";
|
|
325
325
|
import { pipeline } from "stream/promises";
|
|
326
326
|
import { promisify } from "util";
|
|
327
327
|
var execFileP = promisify(execFile);
|
|
328
|
+
function stripMacOsQuarantine(dir) {
|
|
329
|
+
if (process.platform !== "darwin") return;
|
|
330
|
+
try {
|
|
331
|
+
execFileSync("xattr", ["-r", "-d", "com.apple.quarantine", dir]);
|
|
332
|
+
} catch {
|
|
333
|
+
}
|
|
334
|
+
}
|
|
328
335
|
var LLAMA_BUILD = "b9608";
|
|
329
336
|
var REPO = "ggml-org/llama.cpp";
|
|
330
337
|
var CUDA_VER = "13.3";
|
|
@@ -335,7 +342,10 @@ function availableBackends(tag = LLAMA_BUILD) {
|
|
|
335
342
|
const a = arch();
|
|
336
343
|
const def = (id, label, ...assets) => ({ id, label, assets });
|
|
337
344
|
if (plat() === "darwin") {
|
|
338
|
-
return [
|
|
345
|
+
return [
|
|
346
|
+
def("metal", "Metal (Apple GPU)", `llama-${tag}-bin-macos-${a}.tar.gz`),
|
|
347
|
+
def("cpu", "CPU", `llama-${tag}-bin-macos-${a}.tar.gz`)
|
|
348
|
+
];
|
|
339
349
|
}
|
|
340
350
|
if (plat() === "win32") {
|
|
341
351
|
if (a === "arm64") return [def("cpu", "CPU", `llama-${tag}-bin-win-cpu-arm64.zip`)];
|
|
@@ -464,6 +474,7 @@ async function extractArchive(archive, destDir) {
|
|
|
464
474
|
} else {
|
|
465
475
|
await execFileP("tar", ["-xzf", archive, "-C", destDir]);
|
|
466
476
|
}
|
|
477
|
+
stripMacOsQuarantine(destDir);
|
|
467
478
|
}
|
|
468
479
|
async function provisionBackend(enginesRoot, backend, tag, onProgress, signal) {
|
|
469
480
|
const destDir = join2(enginesRoot, `llama.cpp-${tag}-${backend.id}`);
|
|
@@ -561,32 +572,6 @@ async function latestCommitSha(repo, branch = "", signal) {
|
|
|
561
572
|
const data = await res.json();
|
|
562
573
|
return data.sha ?? "";
|
|
563
574
|
}
|
|
564
|
-
async function provisionForkRelease(enginesRoot, repo, destName, onProgress, signal) {
|
|
565
|
-
const destDir = join2(enginesRoot, destName);
|
|
566
|
-
if (existsSync2(destDir)) {
|
|
567
|
-
const found = findServer(destDir);
|
|
568
|
-
if (found) return found;
|
|
569
|
-
}
|
|
570
|
-
const rel = await latestGithubRelease(repo, signal);
|
|
571
|
-
const asset = pickReleaseAsset(rel.assets ?? []);
|
|
572
|
-
if (!asset) throw new Error("no_release_asset");
|
|
573
|
-
mkdirSync2(destDir, { recursive: true });
|
|
574
|
-
const tmp = join2(enginesRoot, asset.name);
|
|
575
|
-
try {
|
|
576
|
-
onProgress?.({ phase: "downloading", pct: 0 });
|
|
577
|
-
await downloadFile(asset.browser_download_url, tmp, onProgress, signal);
|
|
578
|
-
onProgress?.({ phase: "extracting", pct: -1 });
|
|
579
|
-
await extractArchive(tmp, destDir);
|
|
580
|
-
rmSync(tmp, { force: true });
|
|
581
|
-
} catch (e) {
|
|
582
|
-
rmSync(tmp, { force: true });
|
|
583
|
-
rmSync(destDir, { recursive: true, force: true });
|
|
584
|
-
throw e;
|
|
585
|
-
}
|
|
586
|
-
const bin = findServer(destDir);
|
|
587
|
-
if (!bin) throw new Error("llama-server not found in extracted release archive");
|
|
588
|
-
return bin;
|
|
589
|
-
}
|
|
590
575
|
async function turboquantAssetUrl(repo, platform = process.platform, archStr = process.arch, signal) {
|
|
591
576
|
if (platform === "win32") return null;
|
|
592
577
|
const res = await fetch(`https://api.github.com/repos/${repo}/releases?per_page=100`, {
|
|
@@ -607,7 +592,10 @@ async function provisionTurboquant(enginesRoot, repo, onProgress, signal) {
|
|
|
607
592
|
const destDir = join2(enginesRoot, "turboquant");
|
|
608
593
|
if (existsSync2(destDir)) {
|
|
609
594
|
const found = findServer(destDir);
|
|
610
|
-
if (found)
|
|
595
|
+
if (found) {
|
|
596
|
+
stripMacOsQuarantine(destDir);
|
|
597
|
+
return found;
|
|
598
|
+
}
|
|
611
599
|
}
|
|
612
600
|
const url = await turboquantAssetUrl(repo, process.platform, process.arch, signal);
|
|
613
601
|
if (!url) throw new Error("no_release_asset");
|
|
@@ -1783,7 +1771,8 @@ function isTimeout(err3) {
|
|
|
1783
1771
|
function runCaptured(bin, arg) {
|
|
1784
1772
|
return new Promise((resolve2) => {
|
|
1785
1773
|
try {
|
|
1786
|
-
|
|
1774
|
+
const timeoutMs = process.platform === "darwin" ? 6e4 : 15e3;
|
|
1775
|
+
execFile5(bin, [arg], { cwd: dirname3(bin), timeout: timeoutMs, windowsHide: true, maxBuffer: 4 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
1787
1776
|
resolve2({ out: (stdout || "") + (stderr || ""), err: error });
|
|
1788
1777
|
});
|
|
1789
1778
|
} catch (e) {
|
|
@@ -1807,7 +1796,8 @@ async function probe(bin) {
|
|
|
1807
1796
|
const h = await runCaptured(bin, "--help");
|
|
1808
1797
|
if (v.err && h.err) {
|
|
1809
1798
|
if (isTimeout(v.err) && isTimeout(h.err)) {
|
|
1810
|
-
|
|
1799
|
+
const timeoutSec = process.platform === "darwin" ? 60 : 15;
|
|
1800
|
+
throw new ProbeError("probe_timeout", `The binary did not respond within ${timeoutSec} seconds.`);
|
|
1811
1801
|
}
|
|
1812
1802
|
let msg2 = "Could not run the binary (--version and --help both failed).";
|
|
1813
1803
|
const tail = lastLine(v.out);
|
|
@@ -2504,7 +2494,7 @@ import { rmSync as rmSync5 } from "fs";
|
|
|
2504
2494
|
import { join as join9 } from "path";
|
|
2505
2495
|
|
|
2506
2496
|
// src/sysinfo/sysinfo.ts
|
|
2507
|
-
import { execFileSync } from "child_process";
|
|
2497
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
2508
2498
|
import os from "os";
|
|
2509
2499
|
import fs from "fs";
|
|
2510
2500
|
var cached = null;
|
|
@@ -2535,7 +2525,7 @@ function classifyVendor(name) {
|
|
|
2535
2525
|
}
|
|
2536
2526
|
function detectGpus() {
|
|
2537
2527
|
try {
|
|
2538
|
-
const out =
|
|
2528
|
+
const out = execFileSync2("nvidia-smi", ["--query-gpu=name,memory.total", "--format=csv,noheader,nounits"], {
|
|
2539
2529
|
timeout: 8e3,
|
|
2540
2530
|
windowsHide: true
|
|
2541
2531
|
}).toString();
|
|
@@ -2548,7 +2538,7 @@ function detectGpus() {
|
|
|
2548
2538
|
}
|
|
2549
2539
|
if (process.platform === "darwin") {
|
|
2550
2540
|
try {
|
|
2551
|
-
const out =
|
|
2541
|
+
const out = execFileSync2("system_profiler", ["SPDisplaysDataType"], { timeout: 8e3 }).toString();
|
|
2552
2542
|
const m = out.match(/Chipset Model:\s*(.+)/);
|
|
2553
2543
|
if (m && /Apple/.test(out)) {
|
|
2554
2544
|
return [{ name: m[1].trim(), vramMb: Math.round(os.totalmem() / 1e6 * 0.65), vendor: "apple" }];
|
|
@@ -2565,7 +2555,7 @@ function detectGpus() {
|
|
|
2565
2555
|
}
|
|
2566
2556
|
function enumWindowsGpus() {
|
|
2567
2557
|
const ps = 'Get-CimInstance Win32_VideoController | ForEach-Object { "$($_.Name)|$($_.AdapterRAM)" }';
|
|
2568
|
-
const out =
|
|
2558
|
+
const out = execFileSync2("powershell", ["-NoProfile", "-NonInteractive", "-Command", ps], {
|
|
2569
2559
|
timeout: 8e3,
|
|
2570
2560
|
windowsHide: true
|
|
2571
2561
|
}).toString();
|
|
@@ -2577,7 +2567,7 @@ function enumWindowsGpus() {
|
|
|
2577
2567
|
}).filter((g) => g.name && g.vendor !== "unknown");
|
|
2578
2568
|
}
|
|
2579
2569
|
function enumLinuxGpus() {
|
|
2580
|
-
const out =
|
|
2570
|
+
const out = execFileSync2("sh", ["-c", "lspci -mm 2>/dev/null | grep -iE 'VGA|3D|Display'"], {
|
|
2581
2571
|
timeout: 8e3
|
|
2582
2572
|
}).toString();
|
|
2583
2573
|
return out.trim().split("\n").filter(Boolean).map((line) => {
|
|
@@ -2660,10 +2650,9 @@ async function applyForkUpdate(d, engine, root, signal) {
|
|
|
2660
2650
|
if (oldEng && d.registry.active()?.id === oldEng.id) await d.manager.stopAndWait();
|
|
2661
2651
|
const tqDir = join9(root, "turboquant");
|
|
2662
2652
|
rmSync5(tqDir, { recursive: true, force: true });
|
|
2663
|
-
const bin = await
|
|
2653
|
+
const bin = await provisionTurboquant(
|
|
2664
2654
|
root,
|
|
2665
2655
|
"AtomicBot-ai/atomic-llama-cpp-turboquant",
|
|
2666
|
-
"turboquant",
|
|
2667
2656
|
(p) => d.provision.progress(p.phase, p.pct, p.part, p.parts),
|
|
2668
2657
|
signal
|
|
2669
2658
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "turbollm",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "TurboLLM — local LLM platform: run any inference engine auto-tuned to your GPU, with a web UI and OpenAI/Anthropic-compatible API. Point Claude Code at your own machine in one command.",
|
|
5
5
|
"license": "FSL-1.1-ALv2",
|
|
6
6
|
"author": "Mohit Soni",
|