pudu-ai 0.2.6 → 0.2.8
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 +129 -38
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -828,6 +828,7 @@ async function loadCatalogCache() {
|
|
|
828
828
|
var en = {
|
|
829
829
|
appTitle: "PUDU-AI",
|
|
830
830
|
appSubtitle: "Local AI Hardware & Benchmark Lab",
|
|
831
|
+
byline: "by devjaime",
|
|
831
832
|
aboutDashboard: "Opens the live lab: your machine, installed models, and estimates. Use it to see what can run here before you benchmark or launch a tool.",
|
|
832
833
|
aboutHardware: "Detects CPU, GPU, and Unified Memory/RAM. Use it to know what this computer can host before pulling a model.",
|
|
833
834
|
aboutModels: "Lists installed models vs catalog fits. FIT/EST. SPEED are estimated (CanIRun.ai by midudev); MEASURED is llama-bench history. Use it to separate \u201Calready here\u201D from \u201Cmight run\u201D.",
|
|
@@ -865,6 +866,7 @@ var en = {
|
|
|
865
866
|
linkingTool: "Linking {tool} with {model}\u2026",
|
|
866
867
|
modelPulled: "Pulled {model} with Ollama.",
|
|
867
868
|
installNone: "No recommended model has grade S\u2013B to install.",
|
|
869
|
+
noOllamaTag: "No Ollama library tag for {model}. Catalog names like Agents-A1 are not pullable. Use qwen3:8b, gemma3:4b, qwen3.5:4b, llama3.1:8b.",
|
|
868
870
|
credits: "Measured: llama-bench + OS telemetry. Estimated: CanIRun.ai by midudev (https://canirun.ai, https://github.com/midudev/canirun.ai, https://midu.dev). Labelled separately; never mixed.",
|
|
869
871
|
noModels: "No local models detected",
|
|
870
872
|
notTested: "Not tested",
|
|
@@ -1011,6 +1013,7 @@ Credits:
|
|
|
1011
1013
|
var es = {
|
|
1012
1014
|
appTitle: "PUDU-AI",
|
|
1013
1015
|
appSubtitle: "Laboratorio local de hardware y benchmarks de IA",
|
|
1016
|
+
byline: "by devjaime",
|
|
1014
1017
|
aboutDashboard: "Abre el laboratorio en vivo: equipo, modelos instalados y estimaciones. Sirve para ver qu\xE9 puede correr aqu\xED antes de medir o lanzar una herramienta.",
|
|
1015
1018
|
aboutHardware: "Detecta CPU, GPU y memoria unificada/RAM. Sirve para saber qu\xE9 puede hospedar este equipo antes de descargar un modelo.",
|
|
1016
1019
|
aboutModels: "Lista instalados frente al cat\xE1logo. FIT/EST. SPEED son estimados (CanIRun.ai de midudev); MEASURED es historial de llama-bench. Sirve para separar \u201Cya est\xE1\u201D de \u201Cpodr\xEDa correr\u201D.",
|
|
@@ -1048,6 +1051,7 @@ var es = {
|
|
|
1048
1051
|
linkingTool: "Vinculando {tool} con {model}\u2026",
|
|
1049
1052
|
modelPulled: "Descargado {model} con Ollama.",
|
|
1050
1053
|
installNone: "Ning\xFAn modelo recomendado tiene nota S\u2013B para instalar.",
|
|
1054
|
+
noOllamaTag: "No hay tag de Ollama para {model}. Nombres de cat\xE1logo como Agents-A1 no se pueden descargar. Usa qwen3:8b, gemma3:4b, qwen3.5:4b, llama3.1:8b.",
|
|
1051
1055
|
credits: "Medido: llama-bench + telemetr\xEDa del SO. Estimado: CanIRun.ai de midudev (https://canirun.ai, https://github.com/midudev/canirun.ai, https://midu.dev). Se etiquetan por separado; nunca se mezclan.",
|
|
1052
1056
|
noModels: "No se detectaron modelos locales",
|
|
1053
1057
|
notTested: "Sin probar",
|
|
@@ -1212,6 +1216,35 @@ function t(id, vars) {
|
|
|
1212
1216
|
return text;
|
|
1213
1217
|
}
|
|
1214
1218
|
|
|
1219
|
+
// src/integrations/ollama-tags.ts
|
|
1220
|
+
var RULES = [
|
|
1221
|
+
{ test: /qwen\s*3\.5\s*[-:]?\s*8b/i, tag: "qwen3.5:8b" },
|
|
1222
|
+
{ test: /qwen\s*3\.5\s*[-:]?\s*4b/i, tag: "qwen3.5:4b" },
|
|
1223
|
+
{ test: /qwen\s*3\s*[-:]?\s*14b/i, tag: "qwen3:14b" },
|
|
1224
|
+
{ test: /qwen\s*3\s*[-:]?\s*8b/i, tag: "qwen3:8b" },
|
|
1225
|
+
{ test: /qwen\s*3\s*[-:]?\s*4b/i, tag: "qwen3:4b" },
|
|
1226
|
+
{ test: /qwen\s*2\.5\s*[-:]?\s*coder\s*[-:]?\s*7b/i, tag: "qwen2.5-coder:7b" },
|
|
1227
|
+
{ test: /gemma\s*3\s*[-:]?\s*12b/i, tag: "gemma3:12b" },
|
|
1228
|
+
{ test: /gemma\s*3\s*[-:]?\s*4b/i, tag: "gemma3:4b" },
|
|
1229
|
+
{ test: /gemma\s*3\s*[-:]?\s*1b/i, tag: "gemma3:1b" },
|
|
1230
|
+
{ test: /llama\s*3\.2\s*[-:]?\s*3b/i, tag: "llama3.2:3b" },
|
|
1231
|
+
{ test: /llama\s*3\.2\s*[-:]?\s*1b/i, tag: "llama3.2:1b" },
|
|
1232
|
+
{ test: /llama\s*3\.1\s*[-:]?\s*8b/i, tag: "llama3.1:8b" },
|
|
1233
|
+
{ test: /deepseek[- ]r1\s*[-:]?\s*8b|deepseek-r1-distill.*8b/i, tag: "deepseek-r1:8b" },
|
|
1234
|
+
{ test: /deepseek[- ]r1\s*[-:]?\s*7b/i, tag: "deepseek-r1:7b" },
|
|
1235
|
+
{ test: /mistral\s*[-:]?\s*7b|mistral-nemo/i, tag: "mistral:7b" },
|
|
1236
|
+
{ test: /phi\s*4|phi-4/i, tag: "phi4" }
|
|
1237
|
+
];
|
|
1238
|
+
function resolveOllamaTag(...parts) {
|
|
1239
|
+
const haystack = parts.filter(Boolean).join(" ");
|
|
1240
|
+
if (!haystack.trim()) return void 0;
|
|
1241
|
+
if (/^[a-z0-9._-]+:[a-z0-9._-]+$/i.test(haystack.trim())) return haystack.trim();
|
|
1242
|
+
for (const rule of RULES) {
|
|
1243
|
+
if (rule.test.test(haystack)) return rule.tag;
|
|
1244
|
+
}
|
|
1245
|
+
return void 0;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1215
1248
|
// src/compatibility/local.ts
|
|
1216
1249
|
var GB_PER_BILLION_Q4 = 0.65;
|
|
1217
1250
|
function estimateModelRamGb(model, quant = "Q4_K_M") {
|
|
@@ -1293,8 +1326,9 @@ async function recommendForMachine(hardware, catalog, network) {
|
|
|
1293
1326
|
try {
|
|
1294
1327
|
const rows = [];
|
|
1295
1328
|
for (const useCase of useCases) {
|
|
1296
|
-
const found = await fetchRecommendations(hardware, useCase,
|
|
1297
|
-
|
|
1329
|
+
const found = await fetchRecommendations(hardware, useCase, 8);
|
|
1330
|
+
const mapped = found.filter((item) => resolveOllamaTag(item.model.id, item.model.name)).slice(0, 1).map((item) => ({ ...item, useCase: labelUseCase(useCase) }));
|
|
1331
|
+
rows.push(...mapped);
|
|
1298
1332
|
}
|
|
1299
1333
|
if (rows.length) return rows;
|
|
1300
1334
|
} catch {
|
|
@@ -1306,6 +1340,7 @@ async function recommendForMachine(hardware, catalog, network) {
|
|
|
1306
1340
|
for (const useCase of useCases) {
|
|
1307
1341
|
const hit = ranked.find((row) => {
|
|
1308
1342
|
if (used.has(row.model.id)) return false;
|
|
1343
|
+
if (!resolveOllamaTag(row.model.id, row.model.name)) return false;
|
|
1309
1344
|
if (useCase === "chat") return row.model.useCase?.includes("chat") ?? true;
|
|
1310
1345
|
return row.model.useCase?.some((u) => u.includes(useCase)) ?? false;
|
|
1311
1346
|
});
|
|
@@ -1950,7 +1985,7 @@ function setLogLevel(next) {
|
|
|
1950
1985
|
import { render } from "ink";
|
|
1951
1986
|
|
|
1952
1987
|
// src/tui/App.tsx
|
|
1953
|
-
import { Box as
|
|
1988
|
+
import { Box as Box10, useApp as useApp2, useInput as useInput4 } from "ink";
|
|
1954
1989
|
import { useMemo as useMemo2, useState as useState4 } from "react";
|
|
1955
1990
|
|
|
1956
1991
|
// src/tui/views/Dashboard.tsx
|
|
@@ -2015,11 +2050,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2015
2050
|
function Dashboard({ session }) {
|
|
2016
2051
|
const h = session.hardware;
|
|
2017
2052
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2018
|
-
/* @__PURE__ */
|
|
2019
|
-
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: t("appTitle") }),
|
|
2020
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: t("appSubtitle") }),
|
|
2021
|
-
/* @__PURE__ */ jsx(Text, { dimColor: true, children: t("aboutDashboard") })
|
|
2022
|
-
] }),
|
|
2053
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: t("aboutDashboard") }),
|
|
2023
2054
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: t("machine") }),
|
|
2024
2055
|
/* @__PURE__ */ jsx(Text, { children: h.machineModel ?? t("unknownMachine") }),
|
|
2025
2056
|
/* @__PURE__ */ jsx(Text, { children: h.cpu.name ?? t("cpuNa") }),
|
|
@@ -2287,7 +2318,7 @@ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
|
2287
2318
|
function ModelsView({ session }) {
|
|
2288
2319
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
2289
2320
|
/* @__PURE__ */ jsx2(Text2, { children: modelsText(session) }),
|
|
2290
|
-
/* @__PURE__ */ jsx2(Text2, {
|
|
2321
|
+
/* @__PURE__ */ jsx2(Text2, { color: "yellow", children: t("modelsHint") })
|
|
2291
2322
|
] });
|
|
2292
2323
|
}
|
|
2293
2324
|
|
|
@@ -2298,7 +2329,7 @@ function HardwareView({ session }) {
|
|
|
2298
2329
|
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
2299
2330
|
/* @__PURE__ */ jsx3(Text3, { children: hardwareText(session) }),
|
|
2300
2331
|
/* @__PURE__ */ jsx3(Text3, { children: runtimesText(session) }),
|
|
2301
|
-
/* @__PURE__ */ jsx3(Text3, {
|
|
2332
|
+
/* @__PURE__ */ jsx3(Text3, { color: "yellow", children: t("hardwareHint") })
|
|
2302
2333
|
] });
|
|
2303
2334
|
}
|
|
2304
2335
|
|
|
@@ -2347,13 +2378,6 @@ var INTEGRATION_IDS = ["opencode", "openclaw", "hermes", "claude"];
|
|
|
2347
2378
|
|
|
2348
2379
|
// src/integrations/decide.ts
|
|
2349
2380
|
var GRADE_RANK = { S: 5, A: 4, B: 3, C: 2, D: 1, F: 0 };
|
|
2350
|
-
function toOllamaTag(id) {
|
|
2351
|
-
const compact = id.toLowerCase().replace(/_/g, "-");
|
|
2352
|
-
const match = compact.match(/^([a-z0-9.]+(?:-[a-z0-9.]+)*)-(\d+(?:\.\d+)?b)$/i);
|
|
2353
|
-
if (match) return `${match[1]}:${match[2]}`;
|
|
2354
|
-
if (compact.includes(":")) return compact;
|
|
2355
|
-
return compact;
|
|
2356
|
-
}
|
|
2357
2381
|
function useCaseOk(useCases, needed) {
|
|
2358
2382
|
if (!useCases?.length) return needed.includes("chat");
|
|
2359
2383
|
return useCases.some((u) => needed.some((n) => u.includes(n)));
|
|
@@ -2367,10 +2391,12 @@ function decideLaunch(session, id) {
|
|
|
2367
2391
|
for (const row of session.rows) {
|
|
2368
2392
|
const useCases = row.catalog?.useCase ?? ["chat", "code"];
|
|
2369
2393
|
if (!useCaseOk(useCases, def.useCases)) continue;
|
|
2394
|
+
const tag = resolveOllamaTag(row.local.id, row.local.name, row.catalog?.id, row.catalog?.name);
|
|
2395
|
+
if (!tag) continue;
|
|
2370
2396
|
const tps = row.lastBenchmark?.benchmark.generationTokensPerSecond;
|
|
2371
2397
|
candidates.push({
|
|
2372
2398
|
modelId: row.local.id,
|
|
2373
|
-
ollamaTag:
|
|
2399
|
+
ollamaTag: tag,
|
|
2374
2400
|
installed: true,
|
|
2375
2401
|
origin: row.lastBenchmark ? "measured" : "estimated",
|
|
2376
2402
|
grade: row.compatibility?.grade,
|
|
@@ -2382,9 +2408,11 @@ function decideLaunch(session, id) {
|
|
|
2382
2408
|
if (!useCaseOk(model.useCase, def.useCases)) continue;
|
|
2383
2409
|
const fit = localCompatibility(session.hardware, model);
|
|
2384
2410
|
if (!def.allowedGrades.includes(fit.grade)) continue;
|
|
2411
|
+
const tag = resolveOllamaTag(model.id, model.name);
|
|
2412
|
+
if (!tag) continue;
|
|
2385
2413
|
candidates.push({
|
|
2386
2414
|
modelId: model.id,
|
|
2387
|
-
ollamaTag:
|
|
2415
|
+
ollamaTag: tag,
|
|
2388
2416
|
installed: false,
|
|
2389
2417
|
origin: "estimated",
|
|
2390
2418
|
grade: fit.grade
|
|
@@ -2484,8 +2512,11 @@ var INSTALLABLE = ["S", "A", "B"];
|
|
|
2484
2512
|
function canInstallGrade(grade) {
|
|
2485
2513
|
return Boolean(grade && INSTALLABLE.includes(grade));
|
|
2486
2514
|
}
|
|
2487
|
-
async function pullOllamaModel(modelId) {
|
|
2488
|
-
const tag =
|
|
2515
|
+
async function pullOllamaModel(modelId, extraName) {
|
|
2516
|
+
const tag = resolveOllamaTag(modelId, extraName);
|
|
2517
|
+
if (!tag) {
|
|
2518
|
+
return { ok: false, log: t("noOllamaTag", { model: extraName ?? modelId }), tag: modelId };
|
|
2519
|
+
}
|
|
2489
2520
|
const result = await runCommand("ollama", ["pull", tag], { timeout: 30 * 6e4 });
|
|
2490
2521
|
if (result.exitCode !== 0) {
|
|
2491
2522
|
return { ok: false, log: result.stderr || t("launchPullFail"), tag };
|
|
@@ -2517,8 +2548,8 @@ function RecommendView({ session }) {
|
|
|
2517
2548
|
return;
|
|
2518
2549
|
}
|
|
2519
2550
|
setBusy(true);
|
|
2520
|
-
setLog(t("launchPulling", { model: rec.model.
|
|
2521
|
-
void pullOllamaModel(rec.model.id).then((result) => {
|
|
2551
|
+
setLog(t("launchPulling", { model: rec.model.name }));
|
|
2552
|
+
void pullOllamaModel(rec.model.id, rec.model.name).then((result) => {
|
|
2522
2553
|
setLog(result.log);
|
|
2523
2554
|
setBusy(false);
|
|
2524
2555
|
});
|
|
@@ -2553,7 +2584,9 @@ function RecommendView({ session }) {
|
|
|
2553
2584
|
" ",
|
|
2554
2585
|
/* @__PURE__ */ jsx4(Text4, { color: gradeColor(item.grade), bold: true, children: item.grade }),
|
|
2555
2586
|
" ",
|
|
2556
|
-
GRADE_MEANING[item.grade]
|
|
2587
|
+
GRADE_MEANING[item.grade],
|
|
2588
|
+
" ",
|
|
2589
|
+
/* @__PURE__ */ jsx4(Text4, { dimColor: true, children: resolveOllamaTag(item.model.id, item.model.name) ?? t("noOllamaTag", { model: item.model.name }) })
|
|
2557
2590
|
] }, `${item.useCase}-${item.model.id}`)),
|
|
2558
2591
|
/* @__PURE__ */ jsxs4(Box4, { marginTop: 1, flexDirection: "column", children: [
|
|
2559
2592
|
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "green", children: t("setupStep2") }),
|
|
@@ -3059,8 +3092,65 @@ function handleAppKey(screen, input, key) {
|
|
|
3059
3092
|
return { type: "ignore" };
|
|
3060
3093
|
}
|
|
3061
3094
|
|
|
3062
|
-
// src/tui/
|
|
3095
|
+
// src/tui/Welcome.tsx
|
|
3096
|
+
import { Box as Box9, Text as Text9 } from "ink";
|
|
3063
3097
|
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3098
|
+
function Welcome({ compact = false }) {
|
|
3099
|
+
if (compact) {
|
|
3100
|
+
return /* @__PURE__ */ jsxs8(Box9, { marginBottom: 1, borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
3101
|
+
/* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: t("appTitle") }),
|
|
3102
|
+
/* @__PURE__ */ jsx9(Text9, { color: "gray", children: " \xB7 " }),
|
|
3103
|
+
/* @__PURE__ */ jsx9(Text9, { color: "magenta", children: t("byline") })
|
|
3104
|
+
] });
|
|
3105
|
+
}
|
|
3106
|
+
return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", marginBottom: 1, children: [
|
|
3107
|
+
/* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", marginRight: 2, children: [
|
|
3108
|
+
/* @__PURE__ */ jsx9(Text9, { color: "yellow", children: " \u2572" }),
|
|
3109
|
+
/* @__PURE__ */ jsxs8(Text9, { children: [
|
|
3110
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: " \u256D\u2500" }),
|
|
3111
|
+
/* @__PURE__ */ jsx9(Text9, { color: "white", children: "\u25CF \u25CF" }),
|
|
3112
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: "\u2500\u256E" })
|
|
3113
|
+
] }),
|
|
3114
|
+
/* @__PURE__ */ jsxs8(Text9, { children: [
|
|
3115
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: " \u2502 " }),
|
|
3116
|
+
/* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "\u25BD" }),
|
|
3117
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: " \u2502" })
|
|
3118
|
+
] }),
|
|
3119
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: " \u2570\u252C\u2500\u2500\u2500\u252C\u256F" }),
|
|
3120
|
+
/* @__PURE__ */ jsx9(Text9, { color: "green", children: " uu uu" })
|
|
3121
|
+
] }),
|
|
3122
|
+
/* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", justifyContent: "center", children: [
|
|
3123
|
+
/* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: t("appTitle") }),
|
|
3124
|
+
/* @__PURE__ */ jsx9(Text9, { color: "white", children: t("appSubtitle") }),
|
|
3125
|
+
/* @__PURE__ */ jsx9(Text9, { color: "magenta", children: t("byline") })
|
|
3126
|
+
] })
|
|
3127
|
+
] });
|
|
3128
|
+
}
|
|
3129
|
+
function ColorNav() {
|
|
3130
|
+
return /* @__PURE__ */ jsx9(Box9, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1, children: /* @__PURE__ */ jsxs8(Text9, { children: [
|
|
3131
|
+
/* @__PURE__ */ jsx9(Text9, { color: "yellow", bold: true, children: "[S]" }),
|
|
3132
|
+
/* @__PURE__ */ jsx9(Text9, { color: "yellow", children: " Setup " }),
|
|
3133
|
+
/* @__PURE__ */ jsx9(Text9, { color: "green", bold: true, children: "[B]" }),
|
|
3134
|
+
/* @__PURE__ */ jsx9(Text9, { color: "green", children: " Bench " }),
|
|
3135
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", bold: true, children: "[M]" }),
|
|
3136
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: " Models " }),
|
|
3137
|
+
/* @__PURE__ */ jsx9(Text9, { color: "magenta", bold: true, children: "[R]" }),
|
|
3138
|
+
/* @__PURE__ */ jsx9(Text9, { color: "magenta", children: " Rec " }),
|
|
3139
|
+
/* @__PURE__ */ jsx9(Text9, { color: "blue", bold: true, children: "[T]" }),
|
|
3140
|
+
/* @__PURE__ */ jsx9(Text9, { color: "blue", children: " Tasks " }),
|
|
3141
|
+
/* @__PURE__ */ jsx9(Text9, { color: "white", bold: true, children: "[H]" }),
|
|
3142
|
+
/* @__PURE__ */ jsx9(Text9, { children: " HW " }),
|
|
3143
|
+
/* @__PURE__ */ jsx9(Text9, { color: "green", bold: true, children: "[C]" }),
|
|
3144
|
+
/* @__PURE__ */ jsx9(Text9, { color: "green", children: " Cmp " }),
|
|
3145
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", bold: true, children: "[L]" }),
|
|
3146
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: " Log " }),
|
|
3147
|
+
/* @__PURE__ */ jsx9(Text9, { color: "red", bold: true, children: "[Q]" }),
|
|
3148
|
+
/* @__PURE__ */ jsx9(Text9, { color: "red", children: " Quit" })
|
|
3149
|
+
] }) });
|
|
3150
|
+
}
|
|
3151
|
+
|
|
3152
|
+
// src/tui/App.tsx
|
|
3153
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3064
3154
|
function App(props) {
|
|
3065
3155
|
const { exit } = useApp2();
|
|
3066
3156
|
const [screen, setScreen] = useState4(props.start ?? "home");
|
|
@@ -3075,15 +3165,16 @@ function App(props) {
|
|
|
3075
3165
|
if (result.type === "home") setScreen("home");
|
|
3076
3166
|
if (result.type === "screen") setScreen(result.screen);
|
|
3077
3167
|
});
|
|
3078
|
-
return /* @__PURE__ */
|
|
3079
|
-
screen
|
|
3080
|
-
screen === "
|
|
3081
|
-
screen === "
|
|
3082
|
-
screen === "
|
|
3083
|
-
screen === "
|
|
3084
|
-
screen === "
|
|
3085
|
-
screen === "
|
|
3086
|
-
screen === "
|
|
3168
|
+
return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "column", padding: 1, children: [
|
|
3169
|
+
screen !== "benchmark" && /* @__PURE__ */ jsx10(Welcome, { compact: screen !== "home" }),
|
|
3170
|
+
screen === "home" && /* @__PURE__ */ jsx10(Dashboard, { session: props.session }),
|
|
3171
|
+
screen === "models" && /* @__PURE__ */ jsx10(ModelsView, { session: props.session }),
|
|
3172
|
+
screen === "hardware" && /* @__PURE__ */ jsx10(HardwareView, { session: props.session }),
|
|
3173
|
+
screen === "recommend" && /* @__PURE__ */ jsx10(RecommendView, { session: props.session }),
|
|
3174
|
+
screen === "compare" && /* @__PURE__ */ jsx10(CompareView, { session: props.session }),
|
|
3175
|
+
screen === "history" && /* @__PURE__ */ jsx10(HistoryView, { session: props.session }),
|
|
3176
|
+
screen === "tasks" && /* @__PURE__ */ jsx10(TasksView, { session: props.session }),
|
|
3177
|
+
screen === "benchmark" && /* @__PURE__ */ jsx10(
|
|
3087
3178
|
BenchmarkView,
|
|
3088
3179
|
{
|
|
3089
3180
|
session: props.session,
|
|
@@ -3094,14 +3185,14 @@ function App(props) {
|
|
|
3094
3185
|
onBack: () => setScreen("home")
|
|
3095
3186
|
}
|
|
3096
3187
|
),
|
|
3097
|
-
screen !== "benchmark" && /* @__PURE__ */
|
|
3188
|
+
screen !== "benchmark" && /* @__PURE__ */ jsx10(ColorNav, {})
|
|
3098
3189
|
] });
|
|
3099
3190
|
}
|
|
3100
3191
|
|
|
3101
3192
|
// src/tui/render.tsx
|
|
3102
|
-
import { jsx as
|
|
3193
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
3103
3194
|
async function renderDashboard(session, preset, start) {
|
|
3104
|
-
const instance = render(/* @__PURE__ */
|
|
3195
|
+
const instance = render(/* @__PURE__ */ jsx11(App, { session, preset, start }));
|
|
3105
3196
|
await instance.waitUntilExit();
|
|
3106
3197
|
}
|
|
3107
3198
|
|
|
@@ -3177,7 +3268,7 @@ ${runtimesText(session)}`),
|
|
|
3177
3268
|
print(t("installNone"), args2.json);
|
|
3178
3269
|
return 1;
|
|
3179
3270
|
}
|
|
3180
|
-
const pulled = await pullOllamaModel(rec.model.id);
|
|
3271
|
+
const pulled = await pullOllamaModel(rec.model.id, rec.model.name);
|
|
3181
3272
|
print(args2.json ? pulled : explained("aboutRecommend", pulled.log), args2.json);
|
|
3182
3273
|
return pulled.ok ? 0 : 1;
|
|
3183
3274
|
}
|