pudu-ai 0.2.14 → 0.2.16
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/index.js +257 -75
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,4 +1,178 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res, err) => function __init() {
|
|
5
|
+
if (err) throw err[0];
|
|
6
|
+
try {
|
|
7
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
8
|
+
} catch (e) {
|
|
9
|
+
throw err = [e], e;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
var __export = (target, all) => {
|
|
13
|
+
for (var name in all)
|
|
14
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// src/shared/process.ts
|
|
18
|
+
import { execa } from "execa";
|
|
19
|
+
function installSignalHandlers() {
|
|
20
|
+
if (installed) return;
|
|
21
|
+
installed = true;
|
|
22
|
+
const stop = () => {
|
|
23
|
+
void killAll("SIGTERM");
|
|
24
|
+
};
|
|
25
|
+
process.once("SIGINT", stop);
|
|
26
|
+
process.once("SIGTERM", stop);
|
|
27
|
+
}
|
|
28
|
+
function spawnTracked(file, args2 = [], options = {}) {
|
|
29
|
+
installSignalHandlers();
|
|
30
|
+
const subprocess = execa(file, args2, {
|
|
31
|
+
reject: false,
|
|
32
|
+
timeout: options.timeout ?? 3e4,
|
|
33
|
+
...options
|
|
34
|
+
});
|
|
35
|
+
children.add(subprocess);
|
|
36
|
+
void subprocess.finally(() => {
|
|
37
|
+
children.delete(subprocess);
|
|
38
|
+
});
|
|
39
|
+
return subprocess;
|
|
40
|
+
}
|
|
41
|
+
function toText(value) {
|
|
42
|
+
if (typeof value === "string") return value;
|
|
43
|
+
if (value instanceof Uint8Array) return Buffer.from(value).toString("utf8");
|
|
44
|
+
if (Array.isArray(value)) return value.map(String).join("\n");
|
|
45
|
+
if (value == null) return "";
|
|
46
|
+
return String(value);
|
|
47
|
+
}
|
|
48
|
+
async function runCommand(file, args2 = [], options = {}) {
|
|
49
|
+
const result = await spawnTracked(file, args2, options);
|
|
50
|
+
return {
|
|
51
|
+
stdout: toText(result.stdout),
|
|
52
|
+
stderr: toText(result.stderr),
|
|
53
|
+
exitCode: result.exitCode,
|
|
54
|
+
timedOut: Boolean(result.timedOut)
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async function killAll(signal = "SIGTERM") {
|
|
58
|
+
for (const child of [...children]) {
|
|
59
|
+
child.kill(signal);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
var children, installed;
|
|
63
|
+
var init_process = __esm({
|
|
64
|
+
"src/shared/process.ts"() {
|
|
65
|
+
"use strict";
|
|
66
|
+
children = /* @__PURE__ */ new Set();
|
|
67
|
+
installed = false;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// src/shared/which.ts
|
|
72
|
+
import { access } from "node:fs/promises";
|
|
73
|
+
import { constants } from "node:fs";
|
|
74
|
+
import path2 from "node:path";
|
|
75
|
+
async function commandExists(name) {
|
|
76
|
+
if (name.includes("/") || name.includes("\\")) {
|
|
77
|
+
try {
|
|
78
|
+
await access(name, constants.X_OK);
|
|
79
|
+
return name;
|
|
80
|
+
} catch {
|
|
81
|
+
return void 0;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const pathEnv = process.env.PATH ?? "";
|
|
85
|
+
const parts = pathEnv.split(path2.delimiter);
|
|
86
|
+
for (const dir of parts) {
|
|
87
|
+
const candidate = path2.join(dir, name);
|
|
88
|
+
try {
|
|
89
|
+
await access(candidate, constants.X_OK);
|
|
90
|
+
return candidate;
|
|
91
|
+
} catch {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return void 0;
|
|
96
|
+
}
|
|
97
|
+
var init_which = __esm({
|
|
98
|
+
"src/shared/which.ts"() {
|
|
99
|
+
"use strict";
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// src/integrations/brew.ts
|
|
104
|
+
var brew_exports = {};
|
|
105
|
+
__export(brew_exports, {
|
|
106
|
+
brewInstallCask: () => brewInstallCask,
|
|
107
|
+
dockerReady: () => dockerReady,
|
|
108
|
+
ensureBrew: () => ensureBrew,
|
|
109
|
+
resolveBrew: () => resolveBrew,
|
|
110
|
+
startDockerDesktop: () => startDockerDesktop,
|
|
111
|
+
waitForDocker: () => waitForDocker
|
|
112
|
+
});
|
|
113
|
+
async function resolveBrew() {
|
|
114
|
+
for (const bin of BREW_CANDIDATES) {
|
|
115
|
+
const found = await commandExists(bin);
|
|
116
|
+
if (found) return found;
|
|
117
|
+
}
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
async function dockerReady() {
|
|
121
|
+
const docker = await commandExists("docker");
|
|
122
|
+
if (!docker) return false;
|
|
123
|
+
const info = await runCommand("docker", ["info"], { timeout: 8e3 });
|
|
124
|
+
return info.exitCode === 0;
|
|
125
|
+
}
|
|
126
|
+
async function ensureBrew() {
|
|
127
|
+
const existing = await resolveBrew();
|
|
128
|
+
if (existing) return { ok: true, brew: existing, log: existing };
|
|
129
|
+
const install = await runCommand(
|
|
130
|
+
"/bin/bash",
|
|
131
|
+
["-c", 'NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"'],
|
|
132
|
+
{ timeout: 15 * 6e4 }
|
|
133
|
+
);
|
|
134
|
+
const after = await resolveBrew();
|
|
135
|
+
if (after) return { ok: true, brew: after, log: after };
|
|
136
|
+
return {
|
|
137
|
+
ok: false,
|
|
138
|
+
log: install.stderr || "Homebrew missing. Install: https://brew.sh"
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
async function brewInstallCask(name) {
|
|
142
|
+
const brew = await resolveBrew();
|
|
143
|
+
if (!brew) {
|
|
144
|
+
const ensured = await ensureBrew();
|
|
145
|
+
if (!ensured.ok || !ensured.brew) return { ok: false, log: ensured.log };
|
|
146
|
+
const result2 = await runCommand(ensured.brew, ["install", "--cask", name], { timeout: 15 * 6e4 });
|
|
147
|
+
return { ok: result2.exitCode === 0, log: result2.stderr || result2.stdout };
|
|
148
|
+
}
|
|
149
|
+
const result = await runCommand(brew, ["install", "--cask", name], { timeout: 15 * 6e4 });
|
|
150
|
+
if (result.exitCode === 0) return { ok: true, log: result.stdout };
|
|
151
|
+
const formula = await runCommand(brew, ["install", name], { timeout: 15 * 6e4 });
|
|
152
|
+
return { ok: formula.exitCode === 0, log: formula.stderr || formula.stdout };
|
|
153
|
+
}
|
|
154
|
+
async function startDockerDesktop() {
|
|
155
|
+
if (process.platform === "darwin") {
|
|
156
|
+
await runCommand("open", ["-a", "Docker"], { timeout: 15e3 });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function waitForDocker(ms = 9e4) {
|
|
160
|
+
const start = Date.now();
|
|
161
|
+
while (Date.now() - start < ms) {
|
|
162
|
+
if (await dockerReady()) return true;
|
|
163
|
+
await new Promise((resolve) => setTimeout(resolve, 2500));
|
|
164
|
+
}
|
|
165
|
+
return dockerReady();
|
|
166
|
+
}
|
|
167
|
+
var BREW_CANDIDATES;
|
|
168
|
+
var init_brew = __esm({
|
|
169
|
+
"src/integrations/brew.ts"() {
|
|
170
|
+
"use strict";
|
|
171
|
+
init_which();
|
|
172
|
+
init_process();
|
|
173
|
+
BREW_CANDIDATES = ["/opt/homebrew/bin/brew", "/usr/local/bin/brew", "brew"];
|
|
174
|
+
}
|
|
175
|
+
});
|
|
2
176
|
|
|
3
177
|
// src/cli/parse-args.ts
|
|
4
178
|
function parseArgs(argv) {
|
|
@@ -118,56 +292,9 @@ async function addModelPath(dir) {
|
|
|
118
292
|
import os5 from "node:os";
|
|
119
293
|
|
|
120
294
|
// src/platform/macos/hardware.ts
|
|
295
|
+
init_process();
|
|
121
296
|
import os2 from "node:os";
|
|
122
297
|
|
|
123
|
-
// src/shared/process.ts
|
|
124
|
-
import { execa } from "execa";
|
|
125
|
-
var children = /* @__PURE__ */ new Set();
|
|
126
|
-
var installed = false;
|
|
127
|
-
function installSignalHandlers() {
|
|
128
|
-
if (installed) return;
|
|
129
|
-
installed = true;
|
|
130
|
-
const stop = () => {
|
|
131
|
-
void killAll("SIGTERM");
|
|
132
|
-
};
|
|
133
|
-
process.once("SIGINT", stop);
|
|
134
|
-
process.once("SIGTERM", stop);
|
|
135
|
-
}
|
|
136
|
-
function spawnTracked(file, args2 = [], options = {}) {
|
|
137
|
-
installSignalHandlers();
|
|
138
|
-
const subprocess = execa(file, args2, {
|
|
139
|
-
reject: false,
|
|
140
|
-
timeout: options.timeout ?? 3e4,
|
|
141
|
-
...options
|
|
142
|
-
});
|
|
143
|
-
children.add(subprocess);
|
|
144
|
-
void subprocess.finally(() => {
|
|
145
|
-
children.delete(subprocess);
|
|
146
|
-
});
|
|
147
|
-
return subprocess;
|
|
148
|
-
}
|
|
149
|
-
function toText(value) {
|
|
150
|
-
if (typeof value === "string") return value;
|
|
151
|
-
if (value instanceof Uint8Array) return Buffer.from(value).toString("utf8");
|
|
152
|
-
if (Array.isArray(value)) return value.map(String).join("\n");
|
|
153
|
-
if (value == null) return "";
|
|
154
|
-
return String(value);
|
|
155
|
-
}
|
|
156
|
-
async function runCommand(file, args2 = [], options = {}) {
|
|
157
|
-
const result = await spawnTracked(file, args2, options);
|
|
158
|
-
return {
|
|
159
|
-
stdout: toText(result.stdout),
|
|
160
|
-
stderr: toText(result.stderr),
|
|
161
|
-
exitCode: result.exitCode,
|
|
162
|
-
timedOut: Boolean(result.timedOut)
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
async function killAll(signal = "SIGTERM") {
|
|
166
|
-
for (const child of [...children]) {
|
|
167
|
-
child.kill(signal);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
298
|
// src/shared/bytes.ts
|
|
172
299
|
var GiB = 1024 ** 3;
|
|
173
300
|
var MiB = 1024 ** 2;
|
|
@@ -377,32 +504,9 @@ async function detectHardware() {
|
|
|
377
504
|
import os7 from "node:os";
|
|
378
505
|
import path5 from "node:path";
|
|
379
506
|
|
|
380
|
-
// src/
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
import path2 from "node:path";
|
|
384
|
-
async function commandExists(name) {
|
|
385
|
-
if (name.includes("/") || name.includes("\\")) {
|
|
386
|
-
try {
|
|
387
|
-
await access(name, constants.X_OK);
|
|
388
|
-
return name;
|
|
389
|
-
} catch {
|
|
390
|
-
return void 0;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
const pathEnv = process.env.PATH ?? "";
|
|
394
|
-
const parts = pathEnv.split(path2.delimiter);
|
|
395
|
-
for (const dir of parts) {
|
|
396
|
-
const candidate = path2.join(dir, name);
|
|
397
|
-
try {
|
|
398
|
-
await access(candidate, constants.X_OK);
|
|
399
|
-
return candidate;
|
|
400
|
-
} catch {
|
|
401
|
-
continue;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
return void 0;
|
|
405
|
-
}
|
|
507
|
+
// src/adapters/ollama/index.ts
|
|
508
|
+
init_process();
|
|
509
|
+
init_which();
|
|
406
510
|
|
|
407
511
|
// src/adapters/ollama/parse.ts
|
|
408
512
|
function parseOllamaList(output) {
|
|
@@ -485,6 +589,7 @@ import path4 from "node:path";
|
|
|
485
589
|
import { access as access2 } from "node:fs/promises";
|
|
486
590
|
|
|
487
591
|
// src/adapters/llamacpp/index.ts
|
|
592
|
+
init_which();
|
|
488
593
|
import { readdir, stat } from "node:fs/promises";
|
|
489
594
|
import path3 from "node:path";
|
|
490
595
|
var BINARIES = ["llama-bench", "llama-cli", "llama-server"];
|
|
@@ -623,6 +728,7 @@ async function discoverLocalModels() {
|
|
|
623
728
|
}
|
|
624
729
|
|
|
625
730
|
// src/adapters/mlx/index.ts
|
|
731
|
+
init_which();
|
|
626
732
|
var mlxAdapter = {
|
|
627
733
|
id: "mlx",
|
|
628
734
|
label: "MLX",
|
|
@@ -644,6 +750,7 @@ var mlxAdapter = {
|
|
|
644
750
|
};
|
|
645
751
|
|
|
646
752
|
// src/runtimes/registry.ts
|
|
753
|
+
init_which();
|
|
647
754
|
var runtimes = [ollamaAdapter, llamaCppAdapter, lmStudioAdapter, mlxAdapter];
|
|
648
755
|
async function detectRuntimes() {
|
|
649
756
|
const llamaBench = Boolean(await commandExists("llama-bench"));
|
|
@@ -658,6 +765,11 @@ async function detectRuntimes() {
|
|
|
658
765
|
label: "llama-bench",
|
|
659
766
|
detected: llamaBench
|
|
660
767
|
});
|
|
768
|
+
statuses.push({
|
|
769
|
+
id: "docker",
|
|
770
|
+
label: "Docker",
|
|
771
|
+
detected: Boolean(await commandExists("docker"))
|
|
772
|
+
});
|
|
661
773
|
return statuses;
|
|
662
774
|
}
|
|
663
775
|
|
|
@@ -840,6 +952,13 @@ var en = {
|
|
|
840
952
|
compareNeedBench: "Need 2+ measured models. Press [B] to benchmark first.",
|
|
841
953
|
reqOllama: "install: https://ollama.com/download or brew install ollama",
|
|
842
954
|
reqLmStudio: "install: https://lmstudio.ai",
|
|
955
|
+
reqDocker: "install: https://docs.docker.com/get-docker/ or brew install --cask docker",
|
|
956
|
+
dockerHint: "press 4 to run ollama/ollama in Docker",
|
|
957
|
+
dockerStarting: "Starting ollama/ollama container\u2026",
|
|
958
|
+
dockerRunOk: "Docker Ollama is up on port 11434 (name: pudu-ollama).",
|
|
959
|
+
dockerRunFail: "Docker daemon is not running. Open Docker Desktop, wait until it is idle, press 4 again.",
|
|
960
|
+
dockerBrewInstall: "Installing Docker with Homebrew (brew install --cask docker)\u2026",
|
|
961
|
+
dockerDesktopWait: "Starting Docker Desktop and waiting for the daemon\u2026",
|
|
843
962
|
aboutHistory: "Shows local benchmark files in ~/.pudu-ai/benchmarks. Use it to replay what this machine actually did.",
|
|
844
963
|
aboutDoctor: "Checks Node, Apple Silicon/Metal, Ollama, llama-bench, and the CanIRun API. Use it to see what is missing before a bench or launch.",
|
|
845
964
|
aboutReport: "Writes the latest measured run as Markdown. Use it to paste results into GitHub or notes.",
|
|
@@ -1029,6 +1148,13 @@ var es = {
|
|
|
1029
1148
|
compareNeedBench: "Hacen falta 2+ modelos medidos. Pulsa [B] para hacer un benchmark primero.",
|
|
1030
1149
|
reqOllama: "instalar: https://ollama.com/download o brew install ollama",
|
|
1031
1150
|
reqLmStudio: "instalar: https://lmstudio.ai",
|
|
1151
|
+
reqDocker: "instalar: https://docs.docker.com/get-docker/ o brew install --cask docker",
|
|
1152
|
+
dockerHint: "pulsa 4 para correr ollama/ollama en Docker",
|
|
1153
|
+
dockerStarting: "Arrancando contenedor ollama/ollama\u2026",
|
|
1154
|
+
dockerRunOk: "Ollama en Docker est\xE1 en el puerto 11434 (nombre: pudu-ollama).",
|
|
1155
|
+
dockerRunFail: "El daemon de Docker no corre. Abre Docker Desktop, espera a que est\xE9 listo y pulsa 4 otra vez.",
|
|
1156
|
+
dockerBrewInstall: "Instalando Docker con Homebrew (brew install --cask docker)\u2026",
|
|
1157
|
+
dockerDesktopWait: "Arrancando Docker Desktop y esperando al daemon\u2026",
|
|
1032
1158
|
aboutHistory: "Muestra los JSON locales en ~/.pudu-ai/benchmarks. Sirve para ver qu\xE9 hizo realmente esta m\xE1quina.",
|
|
1033
1159
|
aboutDoctor: "Revisa Node, Apple Silicon/Metal, Ollama, llama-bench y la API de CanIRun. Sirve para ver qu\xE9 falta antes de un bench o un launch.",
|
|
1034
1160
|
aboutReport: "Exporta la \xFAltima corrida medida en Markdown. Sirve para pegar resultados en GitHub o notas.",
|
|
@@ -1447,7 +1573,11 @@ async function listBenchmarks() {
|
|
|
1447
1573
|
return records;
|
|
1448
1574
|
}
|
|
1449
1575
|
|
|
1576
|
+
// src/session/load.ts
|
|
1577
|
+
init_which();
|
|
1578
|
+
|
|
1450
1579
|
// src/integrations/agents.ts
|
|
1580
|
+
init_which();
|
|
1451
1581
|
var AGENTS = [
|
|
1452
1582
|
{
|
|
1453
1583
|
id: "opencode",
|
|
@@ -1481,6 +1611,7 @@ async function detectAgents() {
|
|
|
1481
1611
|
}
|
|
1482
1612
|
return out;
|
|
1483
1613
|
}
|
|
1614
|
+
var DOCKER_OLLAMA = "docker run -d --name pudu-ollama -p 11434:11434 -v ollama:/root/.ollama ollama/ollama";
|
|
1484
1615
|
|
|
1485
1616
|
// src/session/load.ts
|
|
1486
1617
|
async function loadSession(options) {
|
|
@@ -1515,7 +1646,12 @@ async function loadSession(options) {
|
|
|
1515
1646
|
};
|
|
1516
1647
|
}
|
|
1517
1648
|
|
|
1649
|
+
// src/benchmark/engine.ts
|
|
1650
|
+
init_process();
|
|
1651
|
+
init_which();
|
|
1652
|
+
|
|
1518
1653
|
// src/telemetry/macos.ts
|
|
1654
|
+
init_process();
|
|
1519
1655
|
import os9 from "node:os";
|
|
1520
1656
|
|
|
1521
1657
|
// src/telemetry/fallback.ts
|
|
@@ -2001,6 +2137,9 @@ function resourceFields(resources) {
|
|
|
2001
2137
|
};
|
|
2002
2138
|
}
|
|
2003
2139
|
|
|
2140
|
+
// src/cli/run.ts
|
|
2141
|
+
init_process();
|
|
2142
|
+
|
|
2004
2143
|
// src/shared/logger.ts
|
|
2005
2144
|
var level = "info";
|
|
2006
2145
|
function setLogLevel(next) {
|
|
@@ -2283,6 +2422,7 @@ function doctorText(session) {
|
|
|
2283
2422
|
),
|
|
2284
2423
|
...session.runtimes.find((r) => r.id === "ollama")?.detected ? [] : [`\u25CB Ollama ${t("reqOllama")}`],
|
|
2285
2424
|
...session.runtimes.find((r) => r.id === "lmstudio")?.detected ? [] : [`\u25CB LM Studio ${t("reqLmStudio")}`],
|
|
2425
|
+
...session.runtimes.find((r) => r.id === "docker")?.detected ? [`\u2713 Docker ${t("dockerHint")}`] : [`\u25CB Docker ${t("reqDocker")}`],
|
|
2286
2426
|
"",
|
|
2287
2427
|
session.llamaBench ? t("doctorReady", { count: session.models.filter((m) => m.artifactPath).length }) : t("doctorNoBench")
|
|
2288
2428
|
];
|
|
@@ -2555,6 +2695,7 @@ function parseIntegration(raw) {
|
|
|
2555
2695
|
}
|
|
2556
2696
|
|
|
2557
2697
|
// src/integrations/execute.ts
|
|
2698
|
+
init_process();
|
|
2558
2699
|
async function executeLaunch(decision) {
|
|
2559
2700
|
if (!decision.eligible || !decision.ollamaTag) {
|
|
2560
2701
|
return { ok: false, log: t("launchBlocked") };
|
|
@@ -2584,8 +2725,34 @@ ${launched.stderr || launched.stdout || t("launchExecFail")}`
|
|
|
2584
2725
|
return { ok: true, log: `${lines.join("\n")}
|
|
2585
2726
|
${launched.stdout}`.trim() };
|
|
2586
2727
|
}
|
|
2728
|
+
async function executeDockerOllama() {
|
|
2729
|
+
const { brewInstallCask: brewInstallCask2, dockerReady: dockerReady2, startDockerDesktop: startDockerDesktop2, waitForDocker: waitForDocker2 } = await Promise.resolve().then(() => (init_brew(), brew_exports));
|
|
2730
|
+
const notes = [];
|
|
2731
|
+
if (!await dockerReady2()) {
|
|
2732
|
+
notes.push(t("dockerBrewInstall"));
|
|
2733
|
+
const installed2 = await brewInstallCask2("docker");
|
|
2734
|
+
if (!installed2.ok) {
|
|
2735
|
+
return { ok: false, log: `${t("reqDocker")}
|
|
2736
|
+
${installed2.log}` };
|
|
2737
|
+
}
|
|
2738
|
+
notes.push(t("dockerDesktopWait"));
|
|
2739
|
+
await startDockerDesktop2();
|
|
2740
|
+
const up = await waitForDocker2();
|
|
2741
|
+
if (!up) return { ok: false, log: `${notes.join("\n")}
|
|
2742
|
+
${t("dockerRunFail")}` };
|
|
2743
|
+
}
|
|
2744
|
+
const start = await runCommand("docker", ["start", "pudu-ollama"], { timeout: 3e4 });
|
|
2745
|
+
if (start.exitCode === 0) return { ok: true, log: t("dockerRunOk") };
|
|
2746
|
+
const args2 = DOCKER_OLLAMA.split(" ").slice(1);
|
|
2747
|
+
const result = await runCommand("docker", args2, { timeout: 10 * 6e4 });
|
|
2748
|
+
if (result.exitCode !== 0) {
|
|
2749
|
+
return { ok: false, log: result.stderr || t("dockerRunFail") };
|
|
2750
|
+
}
|
|
2751
|
+
return { ok: true, log: t("dockerRunOk") };
|
|
2752
|
+
}
|
|
2587
2753
|
|
|
2588
2754
|
// src/integrations/pull.ts
|
|
2755
|
+
init_process();
|
|
2589
2756
|
var INSTALLABLE = ["S", "A", "B"];
|
|
2590
2757
|
function canInstallGrade(grade) {
|
|
2591
2758
|
return Boolean(grade && INSTALLABLE.includes(grade));
|
|
@@ -2633,6 +2800,15 @@ function SetupView({ session }) {
|
|
|
2633
2800
|
setBusy(false);
|
|
2634
2801
|
});
|
|
2635
2802
|
}
|
|
2803
|
+
if (input === "4") {
|
|
2804
|
+
setBusy(true);
|
|
2805
|
+
setLog(t("dockerStarting"));
|
|
2806
|
+
void executeDockerOllama().then((result) => {
|
|
2807
|
+
setLog(result.log);
|
|
2808
|
+
setBusy(false);
|
|
2809
|
+
});
|
|
2810
|
+
return;
|
|
2811
|
+
}
|
|
2636
2812
|
const tool = TOOLS.find((item) => item.key === input)?.id;
|
|
2637
2813
|
if (tool && rec) {
|
|
2638
2814
|
const decision = decideLaunch(session, tool);
|
|
@@ -2671,6 +2847,12 @@ function SetupView({ session }) {
|
|
|
2671
2847
|
agent.label,
|
|
2672
2848
|
agent.detected ? "" : ` \u2192 ${agent.launch}`
|
|
2673
2849
|
] }, agent.id)),
|
|
2850
|
+
/* @__PURE__ */ jsxs6(Text6, { color: session.runtimes.find((r) => r.id === "docker")?.detected ? "green" : "yellow", children: [
|
|
2851
|
+
"[4] ",
|
|
2852
|
+
session.runtimes.find((r) => r.id === "docker")?.detected ? "\u2713" : "\u25CB",
|
|
2853
|
+
" Docker",
|
|
2854
|
+
session.runtimes.find((r) => r.id === "docker")?.detected ? ` \u2192 ${t("dockerHint")}` : ` \u2192 ${t("reqDocker")}`
|
|
2855
|
+
] }),
|
|
2674
2856
|
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: fit(
|
|
2675
2857
|
`Ollama: ${session.runtimes.find((r) => r.id === "ollama")?.detected ? "\u2713" : t("reqOllama")} LM Studio: ${session.runtimes.find((r) => r.id === "lmstudio")?.detected ? "\u2713" : t("reqLmStudio")}`,
|
|
2676
2858
|
cols
|
|
@@ -3164,7 +3346,7 @@ function handleAppKey(screen, input, key) {
|
|
|
3164
3346
|
if (letter === "q") return { type: "quit" };
|
|
3165
3347
|
if (key.escape) return screen === "home" ? { type: "quit" } : { type: "home" };
|
|
3166
3348
|
if (screen === "setup") {
|
|
3167
|
-
if (letter === "i" || letter === "1" || letter === "2" || letter === "3") return { type: "ignore" };
|
|
3349
|
+
if (letter === "i" || letter === "1" || letter === "2" || letter === "3" || letter === "4") return { type: "ignore" };
|
|
3168
3350
|
}
|
|
3169
3351
|
const nav = globalNav(letter);
|
|
3170
3352
|
if (nav) return nav;
|