pudu-ai 0.2.10 → 0.2.12
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 +200 -144
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -851,7 +851,7 @@ var en = {
|
|
|
851
851
|
setupLinkNow: "installed \u2192 press 1/2/3 to link this model",
|
|
852
852
|
setupInstallAgent: "not installed \u2192 press 1/2/3 to install via ollama launch (if eligible)",
|
|
853
853
|
setupKeys: "Enter/I = pull model 1 OpenCode 2 Hermes 3 OpenClaw Esc = back",
|
|
854
|
-
setupCta: "[S]
|
|
854
|
+
setupCta: "[S] Setup: install model + OpenCode / Hermes / OpenClaw",
|
|
855
855
|
machine: "MACHINE",
|
|
856
856
|
runtimes: "LOCAL AI RUNTIMES",
|
|
857
857
|
installedModels: "INSTALLED MODELS",
|
|
@@ -1036,7 +1036,7 @@ var es = {
|
|
|
1036
1036
|
setupLinkNow: "instalado \u2192 pulsa 1/2/3 para vincular este modelo",
|
|
1037
1037
|
setupInstallAgent: "no instalado \u2192 pulsa 1/2/3 para instalar con ollama launch (si es elegible)",
|
|
1038
1038
|
setupKeys: "Enter/I = descargar modelo 1 OpenCode 2 Hermes 3 OpenClaw Esc = atr\xE1s",
|
|
1039
|
-
setupCta: "[S]
|
|
1039
|
+
setupCta: "[S] Setup: instalar modelo + OpenCode / Hermes / OpenClaw",
|
|
1040
1040
|
machine: "EQUIPO",
|
|
1041
1041
|
runtimes: "RUNTIMES DE IA LOCAL",
|
|
1042
1042
|
installedModels: "MODELOS INSTALADOS",
|
|
@@ -1985,7 +1985,7 @@ function setLogLevel(next) {
|
|
|
1985
1985
|
import { render } from "ink";
|
|
1986
1986
|
|
|
1987
1987
|
// src/tui/App.tsx
|
|
1988
|
-
import { Box as
|
|
1988
|
+
import { Box as Box11, useApp as useApp2, useInput as useInput4 } from "ink";
|
|
1989
1989
|
import { useMemo as useMemo2, useRef as useRef2, useState as useState4 } from "react";
|
|
1990
1990
|
|
|
1991
1991
|
// src/tui/views/Dashboard.tsx
|
|
@@ -2035,37 +2035,40 @@ function sparkline(values, width = 24) {
|
|
|
2035
2035
|
return slice.map((v) => glyphs[Math.min(glyphs.length - 1, Math.floor(v / max * (glyphs.length - 1)))]).join("").padStart(width, glyphs[0]);
|
|
2036
2036
|
}
|
|
2037
2037
|
|
|
2038
|
+
// src/tui/width.ts
|
|
2039
|
+
import { useStdout } from "ink";
|
|
2040
|
+
function useCols() {
|
|
2041
|
+
const { stdout } = useStdout();
|
|
2042
|
+
const cols = stdout?.columns ?? 80;
|
|
2043
|
+
return Math.max(40, Math.min(cols - 2, 100));
|
|
2044
|
+
}
|
|
2045
|
+
function fit(text, width) {
|
|
2046
|
+
if (text.length <= width) return text;
|
|
2047
|
+
if (width <= 1) return "\u2026";
|
|
2048
|
+
return `${text.slice(0, width - 1)}\u2026`;
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2038
2051
|
// src/tui/views/Dashboard.tsx
|
|
2039
2052
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2040
2053
|
function Dashboard({ session }) {
|
|
2054
|
+
const cols = useCols();
|
|
2041
2055
|
const h = session.hardware;
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2050
|
-
" \xB7 ",
|
|
2051
|
-
h.cpu.physicalCores ?? "?",
|
|
2052
|
-
"c"
|
|
2053
|
-
] }),
|
|
2054
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2055
|
-
" ",
|
|
2056
|
-
"\xB7 ",
|
|
2057
|
-
formatBytes(h.memory.totalBytes, 0),
|
|
2058
|
-
" ",
|
|
2059
|
-
memoryLabel(h)
|
|
2060
|
-
] })
|
|
2061
|
-
] }),
|
|
2056
|
+
const line = fit(
|
|
2057
|
+
`${h.machineModel ?? t("unknownMachine")} \xB7 ${h.cpu.name ?? t("cpuNa")} \xB7 ${formatBytes(h.memory.totalBytes, 0)} ${memoryLabel(h)}`,
|
|
2058
|
+
cols
|
|
2059
|
+
);
|
|
2060
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: cols, children: [
|
|
2061
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: t("machine") }),
|
|
2062
|
+
/* @__PURE__ */ jsx(Text, { children: line }),
|
|
2062
2063
|
/* @__PURE__ */ jsx(Text, { children: session.runtimes.map((r, i) => /* @__PURE__ */ jsxs(Text, { color: r.detected ? "green" : "gray", children: [
|
|
2063
|
-
i ? "
|
|
2064
|
+
i ? " " : "",
|
|
2064
2065
|
r.detected ? "\u2713" : "\u25CB",
|
|
2065
2066
|
r.label
|
|
2066
2067
|
] }, r.id)) }),
|
|
2067
|
-
|
|
2068
|
-
|
|
2068
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: t("installedModels") }),
|
|
2069
|
+
session.rows.length === 0 && /* @__PURE__ */ jsx(Text, { dimColor: true, children: t("noModels") }),
|
|
2070
|
+
session.rows.slice(0, 6).map((row) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
2071
|
+
/* @__PURE__ */ jsx(Text, { color: "green", children: fit(row.local.name, 18) }),
|
|
2069
2072
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
2070
2073
|
/* @__PURE__ */ jsx(Text, { color: gradeColor(row.compatibility?.grade), children: row.compatibility?.grade ?? "\u2014" }),
|
|
2071
2074
|
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
@@ -2073,16 +2076,17 @@ function Dashboard({ session }) {
|
|
|
2073
2076
|
row.lastBenchmark?.benchmark.generationTokensPerSecond ? formatTokensPerSec(row.lastBenchmark.benchmark.generationTokensPerSecond) : t("notTested")
|
|
2074
2077
|
] })
|
|
2075
2078
|
] }, row.local.id)),
|
|
2079
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: t("recommended") }),
|
|
2076
2080
|
session.recommendations.slice(0, 4).map((rec) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
2077
|
-
/* @__PURE__ */ jsx(Text, { color: "magenta", children: rec.useCase }),
|
|
2081
|
+
/* @__PURE__ */ jsx(Text, { color: "magenta", children: fit(rec.useCase, 10) }),
|
|
2078
2082
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
2079
2083
|
" ",
|
|
2080
|
-
rec.model.name,
|
|
2084
|
+
fit(rec.model.name, 22),
|
|
2081
2085
|
" "
|
|
2082
2086
|
] }),
|
|
2083
2087
|
/* @__PURE__ */ jsx(Text, { color: gradeColor(rec.grade), children: rec.grade })
|
|
2084
2088
|
] }, `${rec.useCase}-${rec.model.id}`)),
|
|
2085
|
-
/* @__PURE__ */ jsx(Text, { color: "yellow", children: t("setupCta") })
|
|
2089
|
+
/* @__PURE__ */ jsx(Text, { color: "yellow", children: fit(t("setupCta"), cols) })
|
|
2086
2090
|
] });
|
|
2087
2091
|
}
|
|
2088
2092
|
|
|
@@ -2146,11 +2150,11 @@ function runtimesText(session) {
|
|
|
2146
2150
|
function modelsText(session) {
|
|
2147
2151
|
const lines = [bold(cyan(t("installedModels"))), dim("MODEL INSTALLED FIT EST. SPEED MEASURED")];
|
|
2148
2152
|
for (const row of session.rows) {
|
|
2149
|
-
const
|
|
2153
|
+
const fit2 = row.compatibility?.grade ?? "\u2014";
|
|
2150
2154
|
const est = row.compatibility?.estimatedTokensPerSecond ? `~${formatNumber(row.compatibility.estimatedTokensPerSecond)} t/s` : "\u2014";
|
|
2151
2155
|
const measured = row.lastBenchmark?.benchmark.generationTokensPerSecond ? formatTokensPerSec(row.lastBenchmark.benchmark.generationTokensPerSecond) : t("notTested");
|
|
2152
2156
|
lines.push(
|
|
2153
|
-
`${green(row.local.name.padEnd(22))} \u2713 ${gradeAnsi(
|
|
2157
|
+
`${green(row.local.name.padEnd(22))} \u2713 ${gradeAnsi(fit2).padEnd(9)} ${est.padEnd(14)} ${measured}`
|
|
2154
2158
|
);
|
|
2155
2159
|
}
|
|
2156
2160
|
lines.push("", t("compatible"));
|
|
@@ -2311,7 +2315,36 @@ function HardwareView({ session }) {
|
|
|
2311
2315
|
}
|
|
2312
2316
|
|
|
2313
2317
|
// src/tui/views/Recommend.tsx
|
|
2314
|
-
import { Box as Box4, Text as Text4
|
|
2318
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
2319
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2320
|
+
function RecommendView({ session }) {
|
|
2321
|
+
const cols = useCols();
|
|
2322
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", width: cols, children: [
|
|
2323
|
+
/* @__PURE__ */ jsx4(Text4, { bold: true, color: "magenta", children: t("recommended") }),
|
|
2324
|
+
/* @__PURE__ */ jsx4(Text4, { dimColor: true, children: fit(t("aboutRecommend"), cols) }),
|
|
2325
|
+
session.recommendations.map((rec) => /* @__PURE__ */ jsxs4(Text4, { children: [
|
|
2326
|
+
/* @__PURE__ */ jsx4(Text4, { color: "magenta", children: fit(rec.useCase, 10) }),
|
|
2327
|
+
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
2328
|
+
" ",
|
|
2329
|
+
fit(rec.model.name, 22),
|
|
2330
|
+
" "
|
|
2331
|
+
] }),
|
|
2332
|
+
/* @__PURE__ */ jsx4(Text4, { color: gradeColor(rec.grade), children: rec.grade }),
|
|
2333
|
+
/* @__PURE__ */ jsxs4(Text4, { children: [
|
|
2334
|
+
" ",
|
|
2335
|
+
GRADE_MEANING[rec.grade]
|
|
2336
|
+
] }),
|
|
2337
|
+
/* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
|
|
2338
|
+
" ",
|
|
2339
|
+
resolveOllamaTag(rec.model.id, rec.model.name) ?? "\u2014"
|
|
2340
|
+
] })
|
|
2341
|
+
] }, `${rec.useCase}-${rec.model.id}`)),
|
|
2342
|
+
/* @__PURE__ */ jsx4(Text4, { color: "yellow", children: fit(t("setupCta"), cols) })
|
|
2343
|
+
] });
|
|
2344
|
+
}
|
|
2345
|
+
|
|
2346
|
+
// src/tui/views/Setup.tsx
|
|
2347
|
+
import { Box as Box5, Text as Text5, useApp, useInput } from "ink";
|
|
2315
2348
|
import { useState } from "react";
|
|
2316
2349
|
|
|
2317
2350
|
// src/integrations/catalog.ts
|
|
@@ -2383,8 +2416,8 @@ function decideLaunch(session, id) {
|
|
|
2383
2416
|
if (!candidates.length) {
|
|
2384
2417
|
for (const model of session.catalog) {
|
|
2385
2418
|
if (!useCaseOk(model.useCase, def.useCases)) continue;
|
|
2386
|
-
const
|
|
2387
|
-
if (!def.allowedGrades.includes(
|
|
2419
|
+
const fit2 = localCompatibility(session.hardware, model);
|
|
2420
|
+
if (!def.allowedGrades.includes(fit2.grade)) continue;
|
|
2388
2421
|
const tag = resolveOllamaTag(model.id, model.name);
|
|
2389
2422
|
if (!tag) continue;
|
|
2390
2423
|
candidates.push({
|
|
@@ -2392,7 +2425,7 @@ function decideLaunch(session, id) {
|
|
|
2392
2425
|
ollamaTag: tag,
|
|
2393
2426
|
installed: false,
|
|
2394
2427
|
origin: "estimated",
|
|
2395
|
-
grade:
|
|
2428
|
+
grade: fit2.grade
|
|
2396
2429
|
});
|
|
2397
2430
|
}
|
|
2398
2431
|
}
|
|
@@ -2501,14 +2534,15 @@ async function pullOllamaModel(modelId, extraName) {
|
|
|
2501
2534
|
return { ok: true, log: t("modelPulled", { model: tag }), tag };
|
|
2502
2535
|
}
|
|
2503
2536
|
|
|
2504
|
-
// src/tui/views/
|
|
2505
|
-
import { jsx as
|
|
2537
|
+
// src/tui/views/Setup.tsx
|
|
2538
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2506
2539
|
var TOOLS = [
|
|
2507
2540
|
{ key: "1", id: "opencode", label: "OpenCode" },
|
|
2508
2541
|
{ key: "2", id: "hermes", label: "Hermes" },
|
|
2509
2542
|
{ key: "3", id: "openclaw", label: "OpenClaw" }
|
|
2510
2543
|
];
|
|
2511
|
-
function
|
|
2544
|
+
function SetupView({ session }) {
|
|
2545
|
+
const cols = useCols();
|
|
2512
2546
|
const { exit } = useApp();
|
|
2513
2547
|
const [cursor, setCursor] = useState(0);
|
|
2514
2548
|
const [log, setLog] = useState("");
|
|
@@ -2548,19 +2582,19 @@ function RecommendView({ session }) {
|
|
|
2548
2582
|
}
|
|
2549
2583
|
});
|
|
2550
2584
|
const tag = rec ? resolveOllamaTag(rec.model.id, rec.model.name) : void 0;
|
|
2551
|
-
return /* @__PURE__ */
|
|
2552
|
-
/* @__PURE__ */
|
|
2553
|
-
recs.map((item, i) => /* @__PURE__ */
|
|
2585
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", width: cols, children: [
|
|
2586
|
+
/* @__PURE__ */ jsx5(Text5, { bold: true, color: "yellow", children: fit(t("setupTitle"), cols) }),
|
|
2587
|
+
recs.map((item, i) => /* @__PURE__ */ jsxs5(Text5, { color: i === cursor ? "cyan" : void 0, children: [
|
|
2554
2588
|
i === cursor ? "\u276F " : " ",
|
|
2555
|
-
item.model.name,
|
|
2589
|
+
fit(item.model.name, 20),
|
|
2556
2590
|
" ",
|
|
2557
|
-
/* @__PURE__ */
|
|
2558
|
-
/* @__PURE__ */
|
|
2591
|
+
/* @__PURE__ */ jsx5(Text5, { color: gradeColor(item.grade), children: item.grade }),
|
|
2592
|
+
/* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
|
|
2559
2593
|
" ",
|
|
2560
2594
|
resolveOllamaTag(item.model.id, item.model.name) ?? "\u2014"
|
|
2561
2595
|
] })
|
|
2562
2596
|
] }, `${item.useCase}-${item.model.id}`)),
|
|
2563
|
-
/* @__PURE__ */
|
|
2597
|
+
/* @__PURE__ */ jsx5(Text5, { children: session.agents.map((agent, index) => /* @__PURE__ */ jsxs5(Text5, { color: agent.detected ? "green" : "gray", children: [
|
|
2564
2598
|
index ? " " : "",
|
|
2565
2599
|
"[",
|
|
2566
2600
|
index + 1,
|
|
@@ -2568,26 +2602,22 @@ function RecommendView({ session }) {
|
|
|
2568
2602
|
agent.detected ? "\u2713" : "\u25CB",
|
|
2569
2603
|
agent.label
|
|
2570
2604
|
] }, agent.id)) }),
|
|
2571
|
-
/* @__PURE__ */
|
|
2572
|
-
|
|
2573
|
-
tag ?? "",
|
|
2574
|
-
" \xB7 1/2/3=agent"
|
|
2575
|
-
] }),
|
|
2576
|
-
log ? /* @__PURE__ */ jsx4(Text4, { color: "green", children: log }) : null
|
|
2605
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: fit(`Enter=pull ${tag ?? ""} 1/2/3=agent Esc=back`, cols) }),
|
|
2606
|
+
log ? /* @__PURE__ */ jsx5(Text5, { color: "green", children: fit(log, cols) }) : null
|
|
2577
2607
|
] });
|
|
2578
2608
|
}
|
|
2579
2609
|
|
|
2580
2610
|
// src/tui/views/Compare.tsx
|
|
2581
|
-
import { Box as
|
|
2582
|
-
import { jsx as
|
|
2611
|
+
import { Box as Box6, Text as Text6 } from "ink";
|
|
2612
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
2583
2613
|
function CompareView({ session }) {
|
|
2584
|
-
return /* @__PURE__ */
|
|
2614
|
+
return /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", children: /* @__PURE__ */ jsx6(Text6, { children: compareText(session.history) }) });
|
|
2585
2615
|
}
|
|
2586
2616
|
|
|
2587
2617
|
// src/tui/views/Benchmark.tsx
|
|
2588
|
-
import { Box as
|
|
2618
|
+
import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
|
|
2589
2619
|
import { useEffect, useRef, useState as useState2 } from "react";
|
|
2590
|
-
import { jsx as
|
|
2620
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2591
2621
|
function BenchmarkView(props) {
|
|
2592
2622
|
const [phase, setPhase] = useState2(props.models.length ? "select" : "error");
|
|
2593
2623
|
const [sample, setSample] = useState2();
|
|
@@ -2647,19 +2677,19 @@ function BenchmarkView(props) {
|
|
|
2647
2677
|
const h = props.session.hardware;
|
|
2648
2678
|
const model = props.models[props.selected];
|
|
2649
2679
|
if (phase === "select") {
|
|
2650
|
-
return /* @__PURE__ */
|
|
2651
|
-
/* @__PURE__ */
|
|
2652
|
-
props.models.map((m, i) => /* @__PURE__ */
|
|
2680
|
+
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
|
|
2681
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, children: t("selectBenchmark") }),
|
|
2682
|
+
props.models.map((m, i) => /* @__PURE__ */ jsxs6(Text7, { color: i === props.selected ? "cyan" : void 0, children: [
|
|
2653
2683
|
i === props.selected ? "\u276F " : " ",
|
|
2654
2684
|
m.name
|
|
2655
2685
|
] }, m.id)),
|
|
2656
|
-
/* @__PURE__ */
|
|
2686
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: t("enterToRun") })
|
|
2657
2687
|
] });
|
|
2658
2688
|
}
|
|
2659
2689
|
if (phase === "done" && result) {
|
|
2660
|
-
return /* @__PURE__ */
|
|
2661
|
-
/* @__PURE__ */
|
|
2662
|
-
/* @__PURE__ */
|
|
2690
|
+
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
|
|
2691
|
+
/* @__PURE__ */ jsx7(Text7, { children: resultText(result.record, result.assessment) }),
|
|
2692
|
+
/* @__PURE__ */ jsxs6(Text7, { dimColor: true, children: [
|
|
2663
2693
|
t("saved"),
|
|
2664
2694
|
" ",
|
|
2665
2695
|
result.path
|
|
@@ -2667,17 +2697,17 @@ function BenchmarkView(props) {
|
|
|
2667
2697
|
] });
|
|
2668
2698
|
}
|
|
2669
2699
|
if (phase === "error") {
|
|
2670
|
-
return /* @__PURE__ */
|
|
2700
|
+
return /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", children: /* @__PURE__ */ jsx7(Text7, { color: "red", children: error }) });
|
|
2671
2701
|
}
|
|
2672
2702
|
const cpu = sample?.cpu?.utilizationPercent;
|
|
2673
2703
|
const gpu = sample?.gpu?.utilizationPercent;
|
|
2674
2704
|
const memUsed = sample?.memory.usedBytes;
|
|
2675
2705
|
const memTotal = h.memory.totalBytes;
|
|
2676
|
-
return /* @__PURE__ */
|
|
2677
|
-
/* @__PURE__ */
|
|
2678
|
-
/* @__PURE__ */
|
|
2679
|
-
/* @__PURE__ */
|
|
2680
|
-
/* @__PURE__ */
|
|
2706
|
+
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
|
|
2707
|
+
/* @__PURE__ */ jsxs6(Box7, { borderStyle: "round", borderColor: "cyan", flexDirection: "column", paddingX: 1, children: [
|
|
2708
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, children: t("benchmarkTitle") }),
|
|
2709
|
+
/* @__PURE__ */ jsx7(Text7, { children: model?.name }),
|
|
2710
|
+
/* @__PURE__ */ jsxs6(Text7, { dimColor: true, children: [
|
|
2681
2711
|
h.cpu.name,
|
|
2682
2712
|
" \xB7 ",
|
|
2683
2713
|
formatBytes(h.memory.totalBytes, 0),
|
|
@@ -2685,31 +2715,31 @@ function BenchmarkView(props) {
|
|
|
2685
2715
|
memoryLabel(h)
|
|
2686
2716
|
] })
|
|
2687
2717
|
] }),
|
|
2688
|
-
/* @__PURE__ */
|
|
2689
|
-
/* @__PURE__ */
|
|
2690
|
-
/* @__PURE__ */
|
|
2718
|
+
/* @__PURE__ */ jsxs6(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
2719
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: t("performance") }),
|
|
2720
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
2691
2721
|
t("elapsed"),
|
|
2692
2722
|
" ",
|
|
2693
2723
|
elapsed.toFixed(1),
|
|
2694
2724
|
" s"
|
|
2695
2725
|
] }),
|
|
2696
|
-
/* @__PURE__ */
|
|
2726
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: t("measuredAfter") })
|
|
2697
2727
|
] }),
|
|
2698
|
-
/* @__PURE__ */
|
|
2699
|
-
/* @__PURE__ */
|
|
2700
|
-
/* @__PURE__ */
|
|
2728
|
+
/* @__PURE__ */ jsxs6(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
2729
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: t("system") }),
|
|
2730
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
2701
2731
|
"CPU ",
|
|
2702
2732
|
bar(cpu),
|
|
2703
2733
|
" ",
|
|
2704
2734
|
formatPercent(cpu)
|
|
2705
2735
|
] }),
|
|
2706
|
-
/* @__PURE__ */
|
|
2736
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
2707
2737
|
"GPU ",
|
|
2708
2738
|
bar(gpu),
|
|
2709
2739
|
" ",
|
|
2710
2740
|
formatPercent(gpu)
|
|
2711
2741
|
] }),
|
|
2712
|
-
/* @__PURE__ */
|
|
2742
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
2713
2743
|
"Memory ",
|
|
2714
2744
|
bar(memUsed && memTotal ? memUsed / memTotal * 100 : void 0),
|
|
2715
2745
|
" ",
|
|
@@ -2717,55 +2747,55 @@ function BenchmarkView(props) {
|
|
|
2717
2747
|
" / ",
|
|
2718
2748
|
formatBytes(memTotal, 0)
|
|
2719
2749
|
] }),
|
|
2720
|
-
/* @__PURE__ */
|
|
2750
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
2721
2751
|
"Swap ",
|
|
2722
2752
|
bar(0),
|
|
2723
2753
|
" ",
|
|
2724
2754
|
sample ? formatBytes(sample.memory.swapUsedBytes) : "N/A"
|
|
2725
2755
|
] })
|
|
2726
2756
|
] }),
|
|
2727
|
-
/* @__PURE__ */
|
|
2728
|
-
/* @__PURE__ */
|
|
2729
|
-
/* @__PURE__ */
|
|
2757
|
+
/* @__PURE__ */ jsxs6(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
2758
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: t("powerThermals") }),
|
|
2759
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
2730
2760
|
"Package ",
|
|
2731
2761
|
sample?.packagePowerWatts ?? "N/A",
|
|
2732
2762
|
" W"
|
|
2733
2763
|
] }),
|
|
2734
|
-
/* @__PURE__ */
|
|
2764
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
2735
2765
|
"Temperature ",
|
|
2736
2766
|
sample?.thermal?.temperatureC ?? "N/A",
|
|
2737
2767
|
" \xB0C"
|
|
2738
2768
|
] }),
|
|
2739
|
-
/* @__PURE__ */
|
|
2769
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
2740
2770
|
"Thermal Pressure ",
|
|
2741
2771
|
sample?.thermal?.pressure ?? "N/A"
|
|
2742
2772
|
] }),
|
|
2743
|
-
/* @__PURE__ */
|
|
2773
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: t("permissionsHint") })
|
|
2744
2774
|
] }),
|
|
2745
|
-
/* @__PURE__ */
|
|
2775
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
2746
2776
|
sparkline(cpuHist.current),
|
|
2747
2777
|
" CPU"
|
|
2748
2778
|
] }),
|
|
2749
|
-
/* @__PURE__ */
|
|
2779
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
2750
2780
|
sparkline(memHist.current.map((v) => v / 1024 ** 3)),
|
|
2751
2781
|
" Memory"
|
|
2752
2782
|
] }),
|
|
2753
|
-
/* @__PURE__ */
|
|
2783
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: t("cancelHint") })
|
|
2754
2784
|
] });
|
|
2755
2785
|
}
|
|
2756
2786
|
|
|
2757
2787
|
// src/tui/views/History.tsx
|
|
2758
|
-
import { Box as
|
|
2759
|
-
import { jsx as
|
|
2788
|
+
import { Box as Box8, Text as Text8 } from "ink";
|
|
2789
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2760
2790
|
function HistoryView({ session }) {
|
|
2761
|
-
return /* @__PURE__ */
|
|
2762
|
-
/* @__PURE__ */
|
|
2763
|
-
/* @__PURE__ */
|
|
2791
|
+
return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", children: [
|
|
2792
|
+
/* @__PURE__ */ jsx8(Text8, { bold: true, color: "cyan", children: t("measured") }),
|
|
2793
|
+
/* @__PURE__ */ jsx8(Text8, { children: historyText(session.history) })
|
|
2764
2794
|
] });
|
|
2765
2795
|
}
|
|
2766
2796
|
|
|
2767
2797
|
// src/tui/views/Tasks.tsx
|
|
2768
|
-
import { Box as
|
|
2798
|
+
import { Box as Box9, Text as Text9, useInput as useInput3 } from "ink";
|
|
2769
2799
|
import { useMemo, useState as useState3 } from "react";
|
|
2770
2800
|
|
|
2771
2801
|
// src/tasks/catalog.ts
|
|
@@ -2896,13 +2926,13 @@ function planTasks(session, answers) {
|
|
|
2896
2926
|
const catalogExtras = answers.scope === "all" ? session.catalog.filter((model) => !session.rows.some((row) => idsLikelyMatch(row.local.id, model.id))).map((model) => {
|
|
2897
2927
|
const useCases = model.useCase ?? [];
|
|
2898
2928
|
const kinds = answers.kinds.filter((kind) => kindMatches(kind, useCases));
|
|
2899
|
-
const
|
|
2929
|
+
const fit2 = localCompatibility(session.hardware, model);
|
|
2900
2930
|
return {
|
|
2901
2931
|
modelId: model.id,
|
|
2902
2932
|
modelName: model.name,
|
|
2903
2933
|
installed: false,
|
|
2904
2934
|
origin: "estimated",
|
|
2905
|
-
grade:
|
|
2935
|
+
grade: fit2.grade,
|
|
2906
2936
|
useCases,
|
|
2907
2937
|
kinds
|
|
2908
2938
|
};
|
|
@@ -2961,7 +2991,7 @@ function tasksText(plans, answers) {
|
|
|
2961
2991
|
}
|
|
2962
2992
|
|
|
2963
2993
|
// src/tui/views/Tasks.tsx
|
|
2964
|
-
import { Fragment, jsx as
|
|
2994
|
+
import { Fragment, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2965
2995
|
var KIND_LABEL = {
|
|
2966
2996
|
code: "tasksOptCode",
|
|
2967
2997
|
video: "tasksOptVideo",
|
|
@@ -3002,13 +3032,13 @@ function TasksView({ session }) {
|
|
|
3002
3032
|
}
|
|
3003
3033
|
});
|
|
3004
3034
|
if (step === 3) {
|
|
3005
|
-
return /* @__PURE__ */
|
|
3035
|
+
return /* @__PURE__ */ jsx9(Box9, { flexDirection: "column", children: /* @__PURE__ */ jsx9(Text9, { children: tasksText(plans, { kinds, scope, priority }) }) });
|
|
3006
3036
|
}
|
|
3007
|
-
return /* @__PURE__ */
|
|
3008
|
-
/* @__PURE__ */
|
|
3009
|
-
step === 0 && /* @__PURE__ */
|
|
3010
|
-
/* @__PURE__ */
|
|
3011
|
-
WORK_KINDS.map((kind, i) => /* @__PURE__ */
|
|
3037
|
+
return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", children: [
|
|
3038
|
+
/* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: t("tasksTitle") }),
|
|
3039
|
+
step === 0 && /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
3040
|
+
/* @__PURE__ */ jsx9(Text9, { children: t("tasksQ1") }),
|
|
3041
|
+
WORK_KINDS.map((kind, i) => /* @__PURE__ */ jsxs8(Text9, { color: i === cursor ? "cyan" : void 0, children: [
|
|
3012
3042
|
i === cursor ? "\u276F " : " ",
|
|
3013
3043
|
"[",
|
|
3014
3044
|
kinds.includes(kind) ? "x" : " ",
|
|
@@ -3016,20 +3046,20 @@ function TasksView({ session }) {
|
|
|
3016
3046
|
t(KIND_LABEL[kind])
|
|
3017
3047
|
] }, kind))
|
|
3018
3048
|
] }),
|
|
3019
|
-
step === 1 && /* @__PURE__ */
|
|
3020
|
-
/* @__PURE__ */
|
|
3021
|
-
/* @__PURE__ */
|
|
3049
|
+
step === 1 && /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
3050
|
+
/* @__PURE__ */ jsx9(Text9, { children: t("tasksQ2") }),
|
|
3051
|
+
/* @__PURE__ */ jsxs8(Text9, { color: scope === "installed" ? "cyan" : void 0, children: [
|
|
3022
3052
|
scope === "installed" ? "\u276F " : " ",
|
|
3023
3053
|
t("tasksOptInstalled")
|
|
3024
3054
|
] }),
|
|
3025
|
-
/* @__PURE__ */
|
|
3055
|
+
/* @__PURE__ */ jsxs8(Text9, { color: scope === "all" ? "cyan" : void 0, children: [
|
|
3026
3056
|
scope === "all" ? "\u276F " : " ",
|
|
3027
3057
|
t("tasksOptAll")
|
|
3028
3058
|
] })
|
|
3029
3059
|
] }),
|
|
3030
|
-
step === 2 && /* @__PURE__ */
|
|
3031
|
-
/* @__PURE__ */
|
|
3032
|
-
["speed", "balanced", "quality"].map((item) => /* @__PURE__ */
|
|
3060
|
+
step === 2 && /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
3061
|
+
/* @__PURE__ */ jsx9(Text9, { children: t("tasksQ3") }),
|
|
3062
|
+
["speed", "balanced", "quality"].map((item) => /* @__PURE__ */ jsxs8(Text9, { color: priority === item ? "cyan" : void 0, children: [
|
|
3033
3063
|
priority === item ? "\u276F " : " ",
|
|
3034
3064
|
item === "speed" ? t("tasksOptSpeed") : item === "quality" ? t("tasksOptQuality") : t("tasksOptBalanced")
|
|
3035
3065
|
] }, item))
|
|
@@ -3046,7 +3076,7 @@ function globalNav(letter) {
|
|
|
3046
3076
|
if (letter === "c") return { type: "screen", screen: "compare" };
|
|
3047
3077
|
if (letter === "l") return { type: "screen", screen: "history" };
|
|
3048
3078
|
if (letter === "t") return { type: "screen", screen: "tasks" };
|
|
3049
|
-
if (letter === "s") return { type: "screen", screen: "
|
|
3079
|
+
if (letter === "s") return { type: "screen", screen: "setup" };
|
|
3050
3080
|
return void 0;
|
|
3051
3081
|
}
|
|
3052
3082
|
function handleAppKey(screen, input, key) {
|
|
@@ -3054,41 +3084,66 @@ function handleAppKey(screen, input, key) {
|
|
|
3054
3084
|
if (screen === "benchmark") return { type: "ignore" };
|
|
3055
3085
|
if (letter === "q") return { type: "quit" };
|
|
3056
3086
|
if (key.escape) return screen === "home" ? { type: "quit" } : { type: "home" };
|
|
3057
|
-
if (screen === "
|
|
3087
|
+
if (screen === "setup") {
|
|
3058
3088
|
if (letter === "i" || letter === "1" || letter === "2" || letter === "3") return { type: "ignore" };
|
|
3059
3089
|
}
|
|
3060
3090
|
const nav = globalNav(letter);
|
|
3061
3091
|
if (nav) return nav;
|
|
3062
|
-
if (letter === "i" && screen === "home") return { type: "screen", screen: "
|
|
3092
|
+
if (letter === "i" && screen === "home") return { type: "screen", screen: "setup" };
|
|
3063
3093
|
if (key.return && screen === "home") return { type: "screen", screen: "benchmark" };
|
|
3064
3094
|
return { type: "ignore" };
|
|
3065
3095
|
}
|
|
3066
3096
|
|
|
3067
3097
|
// src/tui/Welcome.tsx
|
|
3068
|
-
import { Box as
|
|
3069
|
-
import { jsx as
|
|
3098
|
+
import { Box as Box10, Text as Text10 } from "ink";
|
|
3099
|
+
import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3070
3100
|
function Chrome() {
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
t("
|
|
3076
|
-
" "
|
|
3101
|
+
const cols = useCols();
|
|
3102
|
+
const wide = cols >= 72;
|
|
3103
|
+
return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "column", width: cols, marginBottom: 1, children: [
|
|
3104
|
+
/* @__PURE__ */ jsxs9(Text10, { children: [
|
|
3105
|
+
/* @__PURE__ */ jsx10(Text10, { bold: true, color: "cyan", children: t("appTitle") }),
|
|
3106
|
+
/* @__PURE__ */ jsx10(Text10, { color: "gray", children: " \xB7 " }),
|
|
3107
|
+
/* @__PURE__ */ jsx10(Text10, { color: "magenta", children: t("byline") }),
|
|
3108
|
+
wide ? /* @__PURE__ */ jsxs9(Text10, { color: "gray", children: [
|
|
3109
|
+
" \xB7 ",
|
|
3110
|
+
fit(t("appSubtitle"), cols - 28)
|
|
3111
|
+
] }) : null
|
|
3077
3112
|
] }),
|
|
3078
|
-
/* @__PURE__ */
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3113
|
+
/* @__PURE__ */ jsx10(Text10, { children: wide ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
3114
|
+
/* @__PURE__ */ jsx10(Text10, { color: "yellow", children: "[S] Setup" }),
|
|
3115
|
+
/* @__PURE__ */ jsx10(Text10, { children: " " }),
|
|
3116
|
+
/* @__PURE__ */ jsx10(Text10, { color: "green", children: "[B] Bench" }),
|
|
3117
|
+
/* @__PURE__ */ jsx10(Text10, { children: " " }),
|
|
3118
|
+
/* @__PURE__ */ jsx10(Text10, { color: "cyan", children: "[M] Models" }),
|
|
3119
|
+
/* @__PURE__ */ jsx10(Text10, { children: " " }),
|
|
3120
|
+
/* @__PURE__ */ jsx10(Text10, { color: "magenta", children: "[R] Rec" }),
|
|
3121
|
+
/* @__PURE__ */ jsx10(Text10, { children: " " }),
|
|
3122
|
+
/* @__PURE__ */ jsx10(Text10, { color: "blue", children: "[T] Tasks" }),
|
|
3123
|
+
/* @__PURE__ */ jsx10(Text10, { children: " " }),
|
|
3124
|
+
/* @__PURE__ */ jsx10(Text10, { children: "[H] HW" }),
|
|
3125
|
+
/* @__PURE__ */ jsx10(Text10, { children: " " }),
|
|
3126
|
+
/* @__PURE__ */ jsx10(Text10, { color: "green", children: "[C] Cmp" }),
|
|
3127
|
+
/* @__PURE__ */ jsx10(Text10, { children: " " }),
|
|
3128
|
+
/* @__PURE__ */ jsx10(Text10, { color: "cyan", children: "[L] Log" }),
|
|
3129
|
+
/* @__PURE__ */ jsx10(Text10, { children: " " }),
|
|
3130
|
+
/* @__PURE__ */ jsx10(Text10, { color: "red", children: "[Q] Quit" })
|
|
3131
|
+
] }) : /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
3132
|
+
/* @__PURE__ */ jsx10(Text10, { color: "yellow", children: "[S]" }),
|
|
3133
|
+
/* @__PURE__ */ jsx10(Text10, { color: "green", children: "[B]" }),
|
|
3134
|
+
/* @__PURE__ */ jsx10(Text10, { color: "cyan", children: "[M]" }),
|
|
3135
|
+
/* @__PURE__ */ jsx10(Text10, { color: "magenta", children: "[R]" }),
|
|
3136
|
+
/* @__PURE__ */ jsx10(Text10, { color: "blue", children: "[T]" }),
|
|
3137
|
+
/* @__PURE__ */ jsx10(Text10, { children: "[H]" }),
|
|
3138
|
+
/* @__PURE__ */ jsx10(Text10, { color: "green", children: "[C]" }),
|
|
3139
|
+
/* @__PURE__ */ jsx10(Text10, { color: "cyan", children: "[L]" }),
|
|
3140
|
+
/* @__PURE__ */ jsx10(Text10, { color: "red", children: "[Q]" })
|
|
3141
|
+
] }) })
|
|
3087
3142
|
] });
|
|
3088
3143
|
}
|
|
3089
3144
|
|
|
3090
3145
|
// src/tui/App.tsx
|
|
3091
|
-
import { jsx as
|
|
3146
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3092
3147
|
function App(props) {
|
|
3093
3148
|
const { exit } = useApp2();
|
|
3094
3149
|
const [screen, setScreen] = useState4(props.start ?? "home");
|
|
@@ -3105,16 +3160,17 @@ function App(props) {
|
|
|
3105
3160
|
if (result.type === "home") setScreen("home");
|
|
3106
3161
|
if (result.type === "screen") setScreen(result.screen);
|
|
3107
3162
|
});
|
|
3108
|
-
return /* @__PURE__ */
|
|
3109
|
-
screen !== "benchmark" && /* @__PURE__ */
|
|
3110
|
-
screen === "home" && /* @__PURE__ */
|
|
3111
|
-
screen === "models" && /* @__PURE__ */
|
|
3112
|
-
screen === "hardware" && /* @__PURE__ */
|
|
3113
|
-
screen === "recommend" && /* @__PURE__ */
|
|
3114
|
-
screen === "
|
|
3115
|
-
screen === "
|
|
3116
|
-
screen === "
|
|
3117
|
-
screen === "
|
|
3163
|
+
return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", paddingX: 1, children: [
|
|
3164
|
+
screen !== "benchmark" && /* @__PURE__ */ jsx11(Chrome, {}),
|
|
3165
|
+
screen === "home" && /* @__PURE__ */ jsx11(Dashboard, { session: props.session }),
|
|
3166
|
+
screen === "models" && /* @__PURE__ */ jsx11(ModelsView, { session: props.session }),
|
|
3167
|
+
screen === "hardware" && /* @__PURE__ */ jsx11(HardwareView, { session: props.session }),
|
|
3168
|
+
screen === "recommend" && /* @__PURE__ */ jsx11(RecommendView, { session: props.session }),
|
|
3169
|
+
screen === "setup" && /* @__PURE__ */ jsx11(SetupView, { session: props.session }),
|
|
3170
|
+
screen === "compare" && /* @__PURE__ */ jsx11(CompareView, { session: props.session }),
|
|
3171
|
+
screen === "history" && /* @__PURE__ */ jsx11(HistoryView, { session: props.session }),
|
|
3172
|
+
screen === "tasks" && /* @__PURE__ */ jsx11(TasksView, { session: props.session }),
|
|
3173
|
+
screen === "benchmark" && /* @__PURE__ */ jsx11(
|
|
3118
3174
|
BenchmarkView,
|
|
3119
3175
|
{
|
|
3120
3176
|
session: props.session,
|
|
@@ -3129,9 +3185,9 @@ function App(props) {
|
|
|
3129
3185
|
}
|
|
3130
3186
|
|
|
3131
3187
|
// src/tui/render.tsx
|
|
3132
|
-
import { jsx as
|
|
3188
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
3133
3189
|
async function renderDashboard(session, preset, start) {
|
|
3134
|
-
const instance = render(/* @__PURE__ */
|
|
3190
|
+
const instance = render(/* @__PURE__ */ jsx12(App, { session, preset, start }));
|
|
3135
3191
|
await instance.waitUntilExit();
|
|
3136
3192
|
}
|
|
3137
3193
|
|
|
@@ -3198,7 +3254,7 @@ ${runtimesText(session)}`),
|
|
|
3198
3254
|
print({ recommendations: session.recommendations, agents: session.agents }, true);
|
|
3199
3255
|
return 0;
|
|
3200
3256
|
}
|
|
3201
|
-
await renderDashboard(session, args2.preset, "
|
|
3257
|
+
await renderDashboard(session, args2.preset, "setup");
|
|
3202
3258
|
return 0;
|
|
3203
3259
|
case "recommend": {
|
|
3204
3260
|
if (args2.install && args2.yes) {
|