pudu-ai 0.2.9 → 0.2.10

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.
Files changed (2) hide show
  1. package/dist/cli/index.js +87 -157
  2. 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: "\u2192 Press [S] or [I] to INSTALL a recommended model and link OpenCode / Hermes / OpenClaw",
854
+ setupCta: "[S] setup",
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: "\u2192 Pulsa [S] o [I] para INSTALAR un modelo recomendado y vincular OpenCode / Hermes / OpenClaw",
1039
+ setupCta: "[S] setup",
1040
1040
  machine: "EQUIPO",
1041
1041
  runtimes: "RUNTIMES DE IA LOCAL",
1042
1042
  installedModels: "MODELOS INSTALADOS",
@@ -2014,16 +2014,6 @@ function memoryLabel(profile) {
2014
2014
  return profile.memory.unified ? "Unified Memory" : "RAM";
2015
2015
  }
2016
2016
 
2017
- // src/compatibility/types.ts
2018
- var GRADE_MEANING = {
2019
- S: "Excellent",
2020
- A: "Recommended",
2021
- B: "Good",
2022
- C: "Tight",
2023
- D: "CPU/offload",
2024
- F: "Not recommended"
2025
- };
2026
-
2027
2017
  // src/tui/theme.ts
2028
2018
  function gradeColor(grade) {
2029
2019
  if (grade === "S" || grade === "A") return "green";
@@ -2050,78 +2040,65 @@ import { jsx, jsxs } from "react/jsx-runtime";
2050
2040
  function Dashboard({ session }) {
2051
2041
  const h = session.hardware;
2052
2042
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
2053
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: t("aboutDashboard") }),
2054
- /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: t("machine") }),
2055
- /* @__PURE__ */ jsx(Text, { children: h.machineModel ?? t("unknownMachine") }),
2056
- /* @__PURE__ */ jsx(Text, { children: h.cpu.name ?? t("cpuNa") }),
2057
- /* @__PURE__ */ jsxs(Text, { children: [
2058
- "CPU ",
2059
- h.cpu.physicalCores ?? "N/A",
2060
- " cores",
2061
- h.cpu.performanceCores ? ` (${h.cpu.performanceCores}P/${h.cpu.efficiencyCores ?? "?"}E)` : ""
2062
- ] }),
2063
- /* @__PURE__ */ jsxs(Text, { children: [
2064
- "GPU ",
2065
- h.gpu.name ?? "N/A"
2066
- ] }),
2067
- /* @__PURE__ */ jsxs(Text, { children: [
2068
- memoryLabel(h).padEnd(13),
2069
- " ",
2070
- formatBytes(h.memory.totalBytes, 0)
2071
- ] }),
2072
- /* @__PURE__ */ jsxs(Text, { children: [
2073
- "Available ",
2074
- h.memory.availableBytes ? formatBytes(h.memory.availableBytes) : "N/A"
2075
- ] }),
2076
2043
  /* @__PURE__ */ jsxs(Text, { children: [
2077
- h.os,
2078
- " ",
2079
- h.osVersion ?? h.arch
2080
- ] }),
2081
- /* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
2082
- /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: t("runtimes") }),
2083
- session.runtimes.map((r) => /* @__PURE__ */ jsxs(Text, { color: r.detected ? "green" : "gray", children: [
2084
- r.detected ? "\u2713" : "\u25CB",
2044
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: h.machineModel ?? t("unknownMachine") }),
2045
+ /* @__PURE__ */ jsxs(Text, { children: [
2046
+ " \xB7 ",
2047
+ h.cpu.name ?? t("cpuNa")
2048
+ ] }),
2049
+ /* @__PURE__ */ jsxs(Text, { children: [
2050
+ " \xB7 ",
2051
+ h.cpu.physicalCores ?? "?",
2052
+ "c"
2053
+ ] }),
2054
+ /* @__PURE__ */ jsxs(Text, { children: [
2085
2055
  " ",
2086
- r.label.padEnd(14),
2056
+ "\xB7 ",
2057
+ formatBytes(h.memory.totalBytes, 0),
2087
2058
  " ",
2088
- r.detected ? r.version ?? t("detected") : t("notDetected")
2089
- ] }, r.id))
2059
+ memoryLabel(h)
2060
+ ] })
2090
2061
  ] }),
2091
- /* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
2092
- /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: t("installedModels") }),
2093
- session.rows.length === 0 && /* @__PURE__ */ jsx(Text, { dimColor: true, children: t("noModels") }),
2094
- session.rows.map((row) => /* @__PURE__ */ jsxs(Text, { children: [
2095
- /* @__PURE__ */ jsx(Text, { color: "green", children: row.local.name.padEnd(20) }),
2096
- " ",
2097
- row.local.sizeBytes ? formatBytes(row.local.sizeBytes) : "N/A",
2098
- " ",
2099
- /* @__PURE__ */ jsx(Text, { color: gradeColor(row.compatibility?.grade), bold: true, children: row.compatibility?.grade ?? "\u2014" }),
2062
+ /* @__PURE__ */ jsx(Text, { children: session.runtimes.map((r, i) => /* @__PURE__ */ jsxs(Text, { color: r.detected ? "green" : "gray", children: [
2063
+ i ? " " : "",
2064
+ r.detected ? "\u2713" : "\u25CB",
2065
+ r.label
2066
+ ] }, r.id)) }),
2067
+ session.rows.slice(0, 5).map((row) => /* @__PURE__ */ jsxs(Text, { children: [
2068
+ /* @__PURE__ */ jsx(Text, { color: "green", children: row.local.name }),
2069
+ /* @__PURE__ */ jsx(Text, { children: " " }),
2070
+ /* @__PURE__ */ jsx(Text, { color: gradeColor(row.compatibility?.grade), children: row.compatibility?.grade ?? "\u2014" }),
2071
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
2100
2072
  " ",
2101
2073
  row.lastBenchmark?.benchmark.generationTokensPerSecond ? formatTokensPerSec(row.lastBenchmark.benchmark.generationTokensPerSecond) : t("notTested")
2102
- ] }, row.local.id))
2103
- ] }),
2104
- /* @__PURE__ */ jsxs(Box, { marginTop: 1, flexDirection: "column", children: [
2105
- /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: t("recommended") }),
2106
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: t("recommendedHint") }),
2107
- session.recommendations.map((rec) => /* @__PURE__ */ jsxs(Text, { children: [
2108
- /* @__PURE__ */ jsx(Text, { color: "magenta", children: rec.useCase.padEnd(12) }),
2109
- " ",
2110
- rec.model.name.padEnd(22),
2111
- " ",
2112
- /* @__PURE__ */ jsx(Text, { color: gradeColor(rec.grade), bold: true, children: rec.grade }),
2074
+ ] })
2075
+ ] }, row.local.id)),
2076
+ session.recommendations.slice(0, 4).map((rec) => /* @__PURE__ */ jsxs(Text, { children: [
2077
+ /* @__PURE__ */ jsx(Text, { color: "magenta", children: rec.useCase }),
2078
+ /* @__PURE__ */ jsxs(Text, { children: [
2113
2079
  " ",
2114
- GRADE_MEANING[rec.grade]
2115
- ] }, `${rec.useCase}-${rec.model.id}`)),
2116
- /* @__PURE__ */ jsx(Text, { dimColor: true, children: t("credits") }),
2117
- /* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: t("setupCta") })
2118
- ] })
2080
+ rec.model.name,
2081
+ " "
2082
+ ] }),
2083
+ /* @__PURE__ */ jsx(Text, { color: gradeColor(rec.grade), children: rec.grade })
2084
+ ] }, `${rec.useCase}-${rec.model.id}`)),
2085
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: t("setupCta") })
2119
2086
  ] });
2120
2087
  }
2121
2088
 
2122
2089
  // src/tui/views/Models.tsx
2123
2090
  import { Box as Box2, Text as Text2 } from "ink";
2124
2091
 
2092
+ // src/compatibility/types.ts
2093
+ var GRADE_MEANING = {
2094
+ S: "Excellent",
2095
+ A: "Recommended",
2096
+ B: "Good",
2097
+ C: "Tight",
2098
+ D: "CPU/offload",
2099
+ F: "Not recommended"
2100
+ };
2101
+
2125
2102
  // src/cli/color.ts
2126
2103
  var enabled = () => !process.env.NO_COLOR && process.stdout.isTTY;
2127
2104
  var wrap = (open, close = 39) => (text) => enabled() ? `\x1B[${open}m${text}\x1B[${close}m` : text;
@@ -2570,42 +2547,32 @@ function RecommendView({ session }) {
2570
2547
  });
2571
2548
  }
2572
2549
  });
2550
+ const tag = rec ? resolveOllamaTag(rec.model.id, rec.model.name) : void 0;
2573
2551
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
2574
- /* @__PURE__ */ jsxs4(Box4, { borderStyle: "round", borderColor: "yellow", flexDirection: "column", paddingX: 1, marginBottom: 1, children: [
2575
- /* @__PURE__ */ jsx4(Text4, { bold: true, color: "yellow", children: t("setupTitle") }),
2576
- /* @__PURE__ */ jsx4(Text4, { children: t("setupIntro") })
2577
- ] }),
2578
- /* @__PURE__ */ jsx4(Text4, { bold: true, color: "cyan", children: t("setupStep1") }),
2579
- recs.length === 0 && /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: t("installNone") }),
2552
+ /* @__PURE__ */ jsx4(Text4, { bold: true, color: "yellow", children: t("setupTitle") }),
2580
2553
  recs.map((item, i) => /* @__PURE__ */ jsxs4(Text4, { color: i === cursor ? "cyan" : void 0, children: [
2581
2554
  i === cursor ? "\u276F " : " ",
2582
- /* @__PURE__ */ jsx4(Text4, { color: "magenta", children: item.useCase.padEnd(12) }),
2583
- item.model.name.padEnd(22),
2584
- " ",
2585
- /* @__PURE__ */ jsx4(Text4, { color: gradeColor(item.grade), bold: true, children: item.grade }),
2586
- " ",
2587
- GRADE_MEANING[item.grade],
2555
+ item.model.name,
2588
2556
  " ",
2589
- /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: resolveOllamaTag(item.model.id, item.model.name) ?? t("noOllamaTag", { model: item.model.name }) })
2590
- ] }, `${item.useCase}-${item.model.id}`)),
2591
- /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, flexDirection: "column", children: [
2592
- /* @__PURE__ */ jsx4(Text4, { bold: true, color: "green", children: t("setupStep2") }),
2593
- /* @__PURE__ */ jsx4(Text4, { color: "green", children: t("setupInstallModel") })
2594
- ] }),
2595
- /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, flexDirection: "column", children: [
2596
- /* @__PURE__ */ jsx4(Text4, { bold: true, color: "yellow", children: t("setupStep3") }),
2597
- session.agents.map((agent, index) => /* @__PURE__ */ jsxs4(Text4, { color: agent.detected ? "green" : "yellow", children: [
2598
- "[",
2599
- index + 1,
2600
- "] ",
2601
- agent.detected ? "\u2713" : "\u25CB",
2557
+ /* @__PURE__ */ jsx4(Text4, { color: gradeColor(item.grade), children: item.grade }),
2558
+ /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
2602
2559
  " ",
2603
- agent.label.padEnd(12),
2604
- " ",
2605
- agent.detected ? t("setupLinkNow") : t("setupInstallAgent")
2606
- ] }, agent.id))
2560
+ resolveOllamaTag(item.model.id, item.model.name) ?? "\u2014"
2561
+ ] })
2562
+ ] }, `${item.useCase}-${item.model.id}`)),
2563
+ /* @__PURE__ */ jsx4(Text4, { children: session.agents.map((agent, index) => /* @__PURE__ */ jsxs4(Text4, { color: agent.detected ? "green" : "gray", children: [
2564
+ index ? " " : "",
2565
+ "[",
2566
+ index + 1,
2567
+ "]",
2568
+ agent.detected ? "\u2713" : "\u25CB",
2569
+ agent.label
2570
+ ] }, agent.id)) }),
2571
+ /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
2572
+ "Enter=pull ",
2573
+ tag ?? "",
2574
+ " \xB7 1/2/3=agent"
2607
2575
  ] }),
2608
- /* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: t("setupKeys") }) }),
2609
2576
  log ? /* @__PURE__ */ jsx4(Text4, { color: "green", children: log }) : null
2610
2577
  ] });
2611
2578
  }
@@ -3100,62 +3067,28 @@ function handleAppKey(screen, input, key) {
3100
3067
  // src/tui/Welcome.tsx
3101
3068
  import { Box as Box9, Text as Text9 } from "ink";
3102
3069
  import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
3103
- function Welcome({ compact = false }) {
3104
- if (compact) {
3105
- return /* @__PURE__ */ jsxs8(Box9, { marginBottom: 1, borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [
3106
- /* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: t("appTitle") }),
3107
- /* @__PURE__ */ jsx9(Text9, { color: "gray", children: " \xB7 " }),
3108
- /* @__PURE__ */ jsx9(Text9, { color: "magenta", children: t("byline") })
3109
- ] });
3110
- }
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" })
3070
+ function Chrome() {
3071
+ return /* @__PURE__ */ jsxs8(Box9, { children: [
3072
+ /* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: t("appTitle") }),
3073
+ /* @__PURE__ */ jsxs8(Text9, { color: "magenta", children: [
3074
+ " ",
3075
+ t("byline"),
3076
+ " "
3126
3077
  ] }),
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
- ] })
3078
+ /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "[S]" }),
3079
+ /* @__PURE__ */ jsx9(Text9, { color: "green", children: "[B]" }),
3080
+ /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: "[M]" }),
3081
+ /* @__PURE__ */ jsx9(Text9, { color: "magenta", children: "[R]" }),
3082
+ /* @__PURE__ */ jsx9(Text9, { color: "blue", children: "[T]" }),
3083
+ /* @__PURE__ */ jsx9(Text9, { children: "[H]" }),
3084
+ /* @__PURE__ */ jsx9(Text9, { color: "green", children: "[C]" }),
3085
+ /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: "[L]" }),
3086
+ /* @__PURE__ */ jsx9(Text9, { color: "red", children: "[Q]" })
3132
3087
  ] });
3133
3088
  }
3134
- function ColorNav() {
3135
- return /* @__PURE__ */ jsx9(Box9, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1, children: /* @__PURE__ */ jsxs8(Text9, { children: [
3136
- /* @__PURE__ */ jsx9(Text9, { color: "yellow", bold: true, children: "[S]" }),
3137
- /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: " Setup " }),
3138
- /* @__PURE__ */ jsx9(Text9, { color: "green", bold: true, children: "[B]" }),
3139
- /* @__PURE__ */ jsx9(Text9, { color: "green", children: " Bench " }),
3140
- /* @__PURE__ */ jsx9(Text9, { color: "cyan", bold: true, children: "[M]" }),
3141
- /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: " Models " }),
3142
- /* @__PURE__ */ jsx9(Text9, { color: "magenta", bold: true, children: "[R]" }),
3143
- /* @__PURE__ */ jsx9(Text9, { color: "magenta", children: " Rec " }),
3144
- /* @__PURE__ */ jsx9(Text9, { color: "blue", bold: true, children: "[T]" }),
3145
- /* @__PURE__ */ jsx9(Text9, { color: "blue", children: " Tasks " }),
3146
- /* @__PURE__ */ jsx9(Text9, { color: "white", bold: true, children: "[H]" }),
3147
- /* @__PURE__ */ jsx9(Text9, { children: " HW " }),
3148
- /* @__PURE__ */ jsx9(Text9, { color: "green", bold: true, children: "[C]" }),
3149
- /* @__PURE__ */ jsx9(Text9, { color: "green", children: " Cmp " }),
3150
- /* @__PURE__ */ jsx9(Text9, { color: "cyan", bold: true, children: "[L]" }),
3151
- /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: " Log " }),
3152
- /* @__PURE__ */ jsx9(Text9, { color: "red", bold: true, children: "[Q]" }),
3153
- /* @__PURE__ */ jsx9(Text9, { color: "red", children: " Quit" })
3154
- ] }) });
3155
- }
3156
3089
 
3157
3090
  // src/tui/App.tsx
3158
- import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
3091
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
3159
3092
  function App(props) {
3160
3093
  const { exit } = useApp2();
3161
3094
  const [screen, setScreen] = useState4(props.start ?? "home");
@@ -3172,11 +3105,8 @@ function App(props) {
3172
3105
  if (result.type === "home") setScreen("home");
3173
3106
  if (result.type === "screen") setScreen(result.screen);
3174
3107
  });
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
- ] }),
3108
+ return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "column", paddingX: 1, children: [
3109
+ screen !== "benchmark" && /* @__PURE__ */ jsx10(Chrome, {}),
3180
3110
  screen === "home" && /* @__PURE__ */ jsx10(Dashboard, { session: props.session }),
3181
3111
  screen === "models" && /* @__PURE__ */ jsx10(ModelsView, { session: props.session }),
3182
3112
  screen === "hardware" && /* @__PURE__ */ jsx10(HardwareView, { session: props.session }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pudu-ai",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "description": "Pudu-AI — local AI hardware & benchmark lab for the terminal",
5
5
  "keywords": [
6
6
  "ai",