pudu-ai 0.2.7 → 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/dist/cli/index.js +102 -66
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -866,6 +866,7 @@ var en = {
|
|
|
866
866
|
linkingTool: "Linking {tool} with {model}\u2026",
|
|
867
867
|
modelPulled: "Pulled {model} with Ollama.",
|
|
868
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.",
|
|
869
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.",
|
|
870
871
|
noModels: "No local models detected",
|
|
871
872
|
notTested: "Not tested",
|
|
@@ -1050,6 +1051,7 @@ var es = {
|
|
|
1050
1051
|
linkingTool: "Vinculando {tool} con {model}\u2026",
|
|
1051
1052
|
modelPulled: "Descargado {model} con Ollama.",
|
|
1052
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.",
|
|
1053
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.",
|
|
1054
1056
|
noModels: "No se detectaron modelos locales",
|
|
1055
1057
|
notTested: "Sin probar",
|
|
@@ -1214,6 +1216,35 @@ function t(id, vars) {
|
|
|
1214
1216
|
return text;
|
|
1215
1217
|
}
|
|
1216
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
|
+
|
|
1217
1248
|
// src/compatibility/local.ts
|
|
1218
1249
|
var GB_PER_BILLION_Q4 = 0.65;
|
|
1219
1250
|
function estimateModelRamGb(model, quant = "Q4_K_M") {
|
|
@@ -1295,8 +1326,9 @@ async function recommendForMachine(hardware, catalog, network) {
|
|
|
1295
1326
|
try {
|
|
1296
1327
|
const rows = [];
|
|
1297
1328
|
for (const useCase of useCases) {
|
|
1298
|
-
const found = await fetchRecommendations(hardware, useCase,
|
|
1299
|
-
|
|
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);
|
|
1300
1332
|
}
|
|
1301
1333
|
if (rows.length) return rows;
|
|
1302
1334
|
} catch {
|
|
@@ -1308,6 +1340,7 @@ async function recommendForMachine(hardware, catalog, network) {
|
|
|
1308
1340
|
for (const useCase of useCases) {
|
|
1309
1341
|
const hit = ranked.find((row) => {
|
|
1310
1342
|
if (used.has(row.model.id)) return false;
|
|
1343
|
+
if (!resolveOllamaTag(row.model.id, row.model.name)) return false;
|
|
1311
1344
|
if (useCase === "chat") return row.model.useCase?.includes("chat") ?? true;
|
|
1312
1345
|
return row.model.useCase?.some((u) => u.includes(useCase)) ?? false;
|
|
1313
1346
|
});
|
|
@@ -1953,7 +1986,7 @@ import { render } from "ink";
|
|
|
1953
1986
|
|
|
1954
1987
|
// src/tui/App.tsx
|
|
1955
1988
|
import { Box as Box10, useApp as useApp2, useInput as useInput4 } from "ink";
|
|
1956
|
-
import { useMemo as useMemo2, useState as useState4 } from "react";
|
|
1989
|
+
import { useMemo as useMemo2, useRef as useRef2, useState as useState4 } from "react";
|
|
1957
1990
|
|
|
1958
1991
|
// src/tui/views/Dashboard.tsx
|
|
1959
1992
|
import { Box, Text } from "ink";
|
|
@@ -2345,13 +2378,6 @@ var INTEGRATION_IDS = ["opencode", "openclaw", "hermes", "claude"];
|
|
|
2345
2378
|
|
|
2346
2379
|
// src/integrations/decide.ts
|
|
2347
2380
|
var GRADE_RANK = { S: 5, A: 4, B: 3, C: 2, D: 1, F: 0 };
|
|
2348
|
-
function toOllamaTag(id) {
|
|
2349
|
-
const compact = id.toLowerCase().replace(/_/g, "-");
|
|
2350
|
-
const match = compact.match(/^([a-z0-9.]+(?:-[a-z0-9.]+)*)-(\d+(?:\.\d+)?b)$/i);
|
|
2351
|
-
if (match) return `${match[1]}:${match[2]}`;
|
|
2352
|
-
if (compact.includes(":")) return compact;
|
|
2353
|
-
return compact;
|
|
2354
|
-
}
|
|
2355
2381
|
function useCaseOk(useCases, needed) {
|
|
2356
2382
|
if (!useCases?.length) return needed.includes("chat");
|
|
2357
2383
|
return useCases.some((u) => needed.some((n) => u.includes(n)));
|
|
@@ -2365,10 +2391,12 @@ function decideLaunch(session, id) {
|
|
|
2365
2391
|
for (const row of session.rows) {
|
|
2366
2392
|
const useCases = row.catalog?.useCase ?? ["chat", "code"];
|
|
2367
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;
|
|
2368
2396
|
const tps = row.lastBenchmark?.benchmark.generationTokensPerSecond;
|
|
2369
2397
|
candidates.push({
|
|
2370
2398
|
modelId: row.local.id,
|
|
2371
|
-
ollamaTag:
|
|
2399
|
+
ollamaTag: tag,
|
|
2372
2400
|
installed: true,
|
|
2373
2401
|
origin: row.lastBenchmark ? "measured" : "estimated",
|
|
2374
2402
|
grade: row.compatibility?.grade,
|
|
@@ -2380,9 +2408,11 @@ function decideLaunch(session, id) {
|
|
|
2380
2408
|
if (!useCaseOk(model.useCase, def.useCases)) continue;
|
|
2381
2409
|
const fit = localCompatibility(session.hardware, model);
|
|
2382
2410
|
if (!def.allowedGrades.includes(fit.grade)) continue;
|
|
2411
|
+
const tag = resolveOllamaTag(model.id, model.name);
|
|
2412
|
+
if (!tag) continue;
|
|
2383
2413
|
candidates.push({
|
|
2384
2414
|
modelId: model.id,
|
|
2385
|
-
ollamaTag:
|
|
2415
|
+
ollamaTag: tag,
|
|
2386
2416
|
installed: false,
|
|
2387
2417
|
origin: "estimated",
|
|
2388
2418
|
grade: fit.grade
|
|
@@ -2482,8 +2512,11 @@ var INSTALLABLE = ["S", "A", "B"];
|
|
|
2482
2512
|
function canInstallGrade(grade) {
|
|
2483
2513
|
return Boolean(grade && INSTALLABLE.includes(grade));
|
|
2484
2514
|
}
|
|
2485
|
-
async function pullOllamaModel(modelId) {
|
|
2486
|
-
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
|
+
}
|
|
2487
2520
|
const result = await runCommand("ollama", ["pull", tag], { timeout: 30 * 6e4 });
|
|
2488
2521
|
if (result.exitCode !== 0) {
|
|
2489
2522
|
return { ok: false, log: result.stderr || t("launchPullFail"), tag };
|
|
@@ -2515,8 +2548,8 @@ function RecommendView({ session }) {
|
|
|
2515
2548
|
return;
|
|
2516
2549
|
}
|
|
2517
2550
|
setBusy(true);
|
|
2518
|
-
setLog(t("launchPulling", { model: rec.model.
|
|
2519
|
-
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) => {
|
|
2520
2553
|
setLog(result.log);
|
|
2521
2554
|
setBusy(false);
|
|
2522
2555
|
});
|
|
@@ -2551,7 +2584,9 @@ function RecommendView({ session }) {
|
|
|
2551
2584
|
" ",
|
|
2552
2585
|
/* @__PURE__ */ jsx4(Text4, { color: gradeColor(item.grade), bold: true, children: item.grade }),
|
|
2553
2586
|
" ",
|
|
2554
|
-
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 }) })
|
|
2555
2590
|
] }, `${item.useCase}-${item.model.id}`)),
|
|
2556
2591
|
/* @__PURE__ */ jsxs4(Box4, { marginTop: 1, flexDirection: "column", children: [
|
|
2557
2592
|
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "green", children: t("setupStep2") }),
|
|
@@ -3036,15 +3071,7 @@ function TasksView({ session }) {
|
|
|
3036
3071
|
}
|
|
3037
3072
|
|
|
3038
3073
|
// src/tui/keys.ts
|
|
3039
|
-
function
|
|
3040
|
-
const letter = input.toLowerCase();
|
|
3041
|
-
if (screen === "benchmark") return { type: "ignore" };
|
|
3042
|
-
if (screen === "recommend" || screen === "tasks") {
|
|
3043
|
-
if (letter === "q") return { type: "quit" };
|
|
3044
|
-
if (key.escape) return { type: "home" };
|
|
3045
|
-
return { type: "ignore" };
|
|
3046
|
-
}
|
|
3047
|
-
if (letter === "q" || key.escape) return { type: "quit" };
|
|
3074
|
+
function globalNav(letter) {
|
|
3048
3075
|
if (letter === "b") return { type: "screen", screen: "benchmark" };
|
|
3049
3076
|
if (letter === "m") return { type: "screen", screen: "models" };
|
|
3050
3077
|
if (letter === "r") return { type: "screen", screen: "recommend" };
|
|
@@ -3052,7 +3079,20 @@ function handleAppKey(screen, input, key) {
|
|
|
3052
3079
|
if (letter === "c") return { type: "screen", screen: "compare" };
|
|
3053
3080
|
if (letter === "l") return { type: "screen", screen: "history" };
|
|
3054
3081
|
if (letter === "t") return { type: "screen", screen: "tasks" };
|
|
3055
|
-
if (letter === "s"
|
|
3082
|
+
if (letter === "s") return { type: "screen", screen: "recommend" };
|
|
3083
|
+
return void 0;
|
|
3084
|
+
}
|
|
3085
|
+
function handleAppKey(screen, input, key) {
|
|
3086
|
+
const letter = input.toLowerCase();
|
|
3087
|
+
if (screen === "benchmark") return { type: "ignore" };
|
|
3088
|
+
if (letter === "q") return { type: "quit" };
|
|
3089
|
+
if (key.escape) return screen === "home" ? { type: "quit" } : { type: "home" };
|
|
3090
|
+
if (screen === "recommend") {
|
|
3091
|
+
if (letter === "i" || letter === "1" || letter === "2" || letter === "3") return { type: "ignore" };
|
|
3092
|
+
}
|
|
3093
|
+
const nav = globalNav(letter);
|
|
3094
|
+
if (nav) return nav;
|
|
3095
|
+
if (letter === "i" && screen === "home") return { type: "screen", screen: "recommend" };
|
|
3056
3096
|
if (key.return && screen === "home") return { type: "screen", screen: "benchmark" };
|
|
3057
3097
|
return { type: "ignore" };
|
|
3058
3098
|
}
|
|
@@ -3062,45 +3102,37 @@ import { Box as Box9, Text as Text9 } from "ink";
|
|
|
3062
3102
|
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3063
3103
|
function Welcome({ compact = false }) {
|
|
3064
3104
|
if (compact) {
|
|
3065
|
-
return /* @__PURE__ */ jsxs8(Box9, { marginBottom: 1, children: [
|
|
3066
|
-
/* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "\u{1F98C} " }),
|
|
3105
|
+
return /* @__PURE__ */ jsxs8(Box9, { marginBottom: 1, borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
|
|
3067
3106
|
/* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: t("appTitle") }),
|
|
3068
|
-
/* @__PURE__ */
|
|
3069
|
-
|
|
3070
|
-
t("byline")
|
|
3071
|
-
] })
|
|
3107
|
+
/* @__PURE__ */ jsx9(Text9, { color: "gray", children: " \xB7 " }),
|
|
3108
|
+
/* @__PURE__ */ jsx9(Text9, { color: "magenta", children: t("byline") })
|
|
3072
3109
|
] });
|
|
3073
3110
|
}
|
|
3074
|
-
return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "
|
|
3075
|
-
/* @__PURE__ */
|
|
3076
|
-
|
|
3077
|
-
/* @__PURE__ */
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
/* @__PURE__ */
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
/* @__PURE__ */ jsx9(Text9, { color: "
|
|
3089
|
-
/* @__PURE__ */ jsx9(Text9, { color: "red", children: "^" }),
|
|
3090
|
-
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: " /" }),
|
|
3091
|
-
/* @__PURE__ */ jsx9(Text9, { children: " " }),
|
|
3092
|
-
/* @__PURE__ */ jsx9(Text9, { color: "white", children: t("appSubtitle") })
|
|
3093
|
-
] }),
|
|
3094
|
-
/* @__PURE__ */ jsxs8(Text9, { children: [
|
|
3095
|
-
/* @__PURE__ */ jsx9(Text9, { color: "green", children: " /| |\\" }),
|
|
3096
|
-
/* @__PURE__ */ jsx9(Text9, { children: " " }),
|
|
3097
|
-
/* @__PURE__ */ jsx9(Text9, { bold: true, color: "magenta", children: t("byline") })
|
|
3111
|
+
return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "row", marginBottom: 1, children: [
|
|
3112
|
+
/* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", marginRight: 2, children: [
|
|
3113
|
+
/* @__PURE__ */ jsx9(Text9, { color: "yellow", children: " \u2572" }),
|
|
3114
|
+
/* @__PURE__ */ jsxs8(Text9, { children: [
|
|
3115
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: " \u256D\u2500" }),
|
|
3116
|
+
/* @__PURE__ */ jsx9(Text9, { color: "white", children: "\u25CF \u25CF" }),
|
|
3117
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: "\u2500\u256E" })
|
|
3118
|
+
] }),
|
|
3119
|
+
/* @__PURE__ */ jsxs8(Text9, { children: [
|
|
3120
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: " \u2502 " }),
|
|
3121
|
+
/* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "\u25BD" }),
|
|
3122
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: " \u2502" })
|
|
3123
|
+
] }),
|
|
3124
|
+
/* @__PURE__ */ jsx9(Text9, { color: "cyan", children: " \u2570\u252C\u2500\u2500\u2500\u252C\u256F" }),
|
|
3125
|
+
/* @__PURE__ */ jsx9(Text9, { color: "green", children: " uu uu" })
|
|
3098
3126
|
] }),
|
|
3099
|
-
/* @__PURE__ */
|
|
3127
|
+
/* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", justifyContent: "center", children: [
|
|
3128
|
+
/* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: t("appTitle") }),
|
|
3129
|
+
/* @__PURE__ */ jsx9(Text9, { color: "white", children: t("appSubtitle") }),
|
|
3130
|
+
/* @__PURE__ */ jsx9(Text9, { color: "magenta", children: t("byline") })
|
|
3131
|
+
] })
|
|
3100
3132
|
] });
|
|
3101
3133
|
}
|
|
3102
3134
|
function ColorNav() {
|
|
3103
|
-
return /* @__PURE__ */ jsx9(Box9, { marginTop: 1, children: /* @__PURE__ */ jsxs8(Text9, { children: [
|
|
3135
|
+
return /* @__PURE__ */ jsx9(Box9, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1, children: /* @__PURE__ */ jsxs8(Text9, { children: [
|
|
3104
3136
|
/* @__PURE__ */ jsx9(Text9, { color: "yellow", bold: true, children: "[S]" }),
|
|
3105
3137
|
/* @__PURE__ */ jsx9(Text9, { color: "yellow", children: " Setup " }),
|
|
3106
3138
|
/* @__PURE__ */ jsx9(Text9, { color: "green", bold: true, children: "[B]" }),
|
|
@@ -3123,23 +3155,28 @@ function ColorNav() {
|
|
|
3123
3155
|
}
|
|
3124
3156
|
|
|
3125
3157
|
// src/tui/App.tsx
|
|
3126
|
-
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3158
|
+
import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3127
3159
|
function App(props) {
|
|
3128
3160
|
const { exit } = useApp2();
|
|
3129
3161
|
const [screen, setScreen] = useState4(props.start ?? "home");
|
|
3162
|
+
const screenRef = useRef2(screen);
|
|
3163
|
+
screenRef.current = screen;
|
|
3130
3164
|
const [selected, setSelected] = useState4(0);
|
|
3131
3165
|
const benchable = useMemo2(
|
|
3132
3166
|
() => props.session.models.filter((m) => Boolean(m.artifactPath)),
|
|
3133
3167
|
[props.session.models]
|
|
3134
3168
|
);
|
|
3135
3169
|
useInput4((input, key) => {
|
|
3136
|
-
const result = handleAppKey(
|
|
3170
|
+
const result = handleAppKey(screenRef.current, input, key);
|
|
3137
3171
|
if (result.type === "quit") exit();
|
|
3138
3172
|
if (result.type === "home") setScreen("home");
|
|
3139
3173
|
if (result.type === "screen") setScreen(result.screen);
|
|
3140
3174
|
});
|
|
3141
|
-
return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "column",
|
|
3142
|
-
screen !== "benchmark" && /* @__PURE__ */
|
|
3175
|
+
return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "column", paddingX: 1, paddingTop: 0, paddingBottom: 1, children: [
|
|
3176
|
+
screen !== "benchmark" && /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
3177
|
+
/* @__PURE__ */ jsx10(ColorNav, {}),
|
|
3178
|
+
/* @__PURE__ */ jsx10(Welcome, { compact: true })
|
|
3179
|
+
] }),
|
|
3143
3180
|
screen === "home" && /* @__PURE__ */ jsx10(Dashboard, { session: props.session }),
|
|
3144
3181
|
screen === "models" && /* @__PURE__ */ jsx10(ModelsView, { session: props.session }),
|
|
3145
3182
|
screen === "hardware" && /* @__PURE__ */ jsx10(HardwareView, { session: props.session }),
|
|
@@ -3157,8 +3194,7 @@ function App(props) {
|
|
|
3157
3194
|
preset: props.preset,
|
|
3158
3195
|
onBack: () => setScreen("home")
|
|
3159
3196
|
}
|
|
3160
|
-
)
|
|
3161
|
-
screen !== "benchmark" && /* @__PURE__ */ jsx10(ColorNav, {})
|
|
3197
|
+
)
|
|
3162
3198
|
] });
|
|
3163
3199
|
}
|
|
3164
3200
|
|
|
@@ -3241,7 +3277,7 @@ ${runtimesText(session)}`),
|
|
|
3241
3277
|
print(t("installNone"), args2.json);
|
|
3242
3278
|
return 1;
|
|
3243
3279
|
}
|
|
3244
|
-
const pulled = await pullOllamaModel(rec.model.id);
|
|
3280
|
+
const pulled = await pullOllamaModel(rec.model.id, rec.model.name);
|
|
3245
3281
|
print(args2.json ? pulled : explained("aboutRecommend", pulled.log), args2.json);
|
|
3246
3282
|
return pulled.ok ? 0 : 1;
|
|
3247
3283
|
}
|