pudu-ai 0.2.11 → 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.
Files changed (2) hide show
  1. package/dist/cli/index.js +153 -123
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -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 Box10, useApp as useApp2, useInput as useInput4 } from "ink";
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
@@ -2315,7 +2315,36 @@ function HardwareView({ session }) {
2315
2315
  }
2316
2316
 
2317
2317
  // src/tui/views/Recommend.tsx
2318
- import { Box as Box4, Text as Text4, useApp, useInput } from "ink";
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";
2319
2348
  import { useState } from "react";
2320
2349
 
2321
2350
  // src/integrations/catalog.ts
@@ -2505,14 +2534,14 @@ async function pullOllamaModel(modelId, extraName) {
2505
2534
  return { ok: true, log: t("modelPulled", { model: tag }), tag };
2506
2535
  }
2507
2536
 
2508
- // src/tui/views/Recommend.tsx
2509
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
2537
+ // src/tui/views/Setup.tsx
2538
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
2510
2539
  var TOOLS = [
2511
2540
  { key: "1", id: "opencode", label: "OpenCode" },
2512
2541
  { key: "2", id: "hermes", label: "Hermes" },
2513
2542
  { key: "3", id: "openclaw", label: "OpenClaw" }
2514
2543
  ];
2515
- function RecommendView({ session }) {
2544
+ function SetupView({ session }) {
2516
2545
  const cols = useCols();
2517
2546
  const { exit } = useApp();
2518
2547
  const [cursor, setCursor] = useState(0);
@@ -2553,19 +2582,19 @@ function RecommendView({ session }) {
2553
2582
  }
2554
2583
  });
2555
2584
  const tag = rec ? resolveOllamaTag(rec.model.id, rec.model.name) : void 0;
2556
- return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", width: cols, children: [
2557
- /* @__PURE__ */ jsx4(Text4, { bold: true, color: "yellow", children: fit(t("setupTitle"), cols) }),
2558
- recs.map((item, i) => /* @__PURE__ */ jsxs4(Text4, { color: i === cursor ? "cyan" : void 0, children: [
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: [
2559
2588
  i === cursor ? "\u276F " : " ",
2560
2589
  fit(item.model.name, 20),
2561
2590
  " ",
2562
- /* @__PURE__ */ jsx4(Text4, { color: gradeColor(item.grade), children: item.grade }),
2563
- /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
2591
+ /* @__PURE__ */ jsx5(Text5, { color: gradeColor(item.grade), children: item.grade }),
2592
+ /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
2564
2593
  " ",
2565
2594
  resolveOllamaTag(item.model.id, item.model.name) ?? "\u2014"
2566
2595
  ] })
2567
2596
  ] }, `${item.useCase}-${item.model.id}`)),
2568
- /* @__PURE__ */ jsx4(Text4, { children: session.agents.map((agent, index) => /* @__PURE__ */ jsxs4(Text4, { color: agent.detected ? "green" : "gray", children: [
2597
+ /* @__PURE__ */ jsx5(Text5, { children: session.agents.map((agent, index) => /* @__PURE__ */ jsxs5(Text5, { color: agent.detected ? "green" : "gray", children: [
2569
2598
  index ? " " : "",
2570
2599
  "[",
2571
2600
  index + 1,
@@ -2573,22 +2602,22 @@ function RecommendView({ session }) {
2573
2602
  agent.detected ? "\u2713" : "\u25CB",
2574
2603
  agent.label
2575
2604
  ] }, agent.id)) }),
2576
- /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: fit(`Enter=pull ${tag ?? ""} 1/2/3=agent Esc=back`, cols) }),
2577
- log ? /* @__PURE__ */ jsx4(Text4, { color: "green", children: fit(log, cols) }) : 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
2578
2607
  ] });
2579
2608
  }
2580
2609
 
2581
2610
  // src/tui/views/Compare.tsx
2582
- import { Box as Box5, Text as Text5 } from "ink";
2583
- import { jsx as jsx5 } from "react/jsx-runtime";
2611
+ import { Box as Box6, Text as Text6 } from "ink";
2612
+ import { jsx as jsx6 } from "react/jsx-runtime";
2584
2613
  function CompareView({ session }) {
2585
- return /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", children: /* @__PURE__ */ jsx5(Text5, { children: compareText(session.history) }) });
2614
+ return /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", children: /* @__PURE__ */ jsx6(Text6, { children: compareText(session.history) }) });
2586
2615
  }
2587
2616
 
2588
2617
  // src/tui/views/Benchmark.tsx
2589
- import { Box as Box6, Text as Text6, useInput as useInput2 } from "ink";
2618
+ import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
2590
2619
  import { useEffect, useRef, useState as useState2 } from "react";
2591
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
2620
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2592
2621
  function BenchmarkView(props) {
2593
2622
  const [phase, setPhase] = useState2(props.models.length ? "select" : "error");
2594
2623
  const [sample, setSample] = useState2();
@@ -2648,19 +2677,19 @@ function BenchmarkView(props) {
2648
2677
  const h = props.session.hardware;
2649
2678
  const model = props.models[props.selected];
2650
2679
  if (phase === "select") {
2651
- return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
2652
- /* @__PURE__ */ jsx6(Text6, { bold: true, children: t("selectBenchmark") }),
2653
- props.models.map((m, i) => /* @__PURE__ */ jsxs5(Text6, { color: i === props.selected ? "cyan" : void 0, children: [
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: [
2654
2683
  i === props.selected ? "\u276F " : " ",
2655
2684
  m.name
2656
2685
  ] }, m.id)),
2657
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: t("enterToRun") })
2686
+ /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: t("enterToRun") })
2658
2687
  ] });
2659
2688
  }
2660
2689
  if (phase === "done" && result) {
2661
- return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
2662
- /* @__PURE__ */ jsx6(Text6, { children: resultText(result.record, result.assessment) }),
2663
- /* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
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: [
2664
2693
  t("saved"),
2665
2694
  " ",
2666
2695
  result.path
@@ -2668,17 +2697,17 @@ function BenchmarkView(props) {
2668
2697
  ] });
2669
2698
  }
2670
2699
  if (phase === "error") {
2671
- return /* @__PURE__ */ jsx6(Box6, { flexDirection: "column", children: /* @__PURE__ */ jsx6(Text6, { color: "red", children: error }) });
2700
+ return /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", children: /* @__PURE__ */ jsx7(Text7, { color: "red", children: error }) });
2672
2701
  }
2673
2702
  const cpu = sample?.cpu?.utilizationPercent;
2674
2703
  const gpu = sample?.gpu?.utilizationPercent;
2675
2704
  const memUsed = sample?.memory.usedBytes;
2676
2705
  const memTotal = h.memory.totalBytes;
2677
- return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
2678
- /* @__PURE__ */ jsxs5(Box6, { borderStyle: "round", borderColor: "cyan", flexDirection: "column", paddingX: 1, children: [
2679
- /* @__PURE__ */ jsx6(Text6, { bold: true, children: t("benchmarkTitle") }),
2680
- /* @__PURE__ */ jsx6(Text6, { children: model?.name }),
2681
- /* @__PURE__ */ jsxs5(Text6, { dimColor: true, children: [
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: [
2682
2711
  h.cpu.name,
2683
2712
  " \xB7 ",
2684
2713
  formatBytes(h.memory.totalBytes, 0),
@@ -2686,31 +2715,31 @@ function BenchmarkView(props) {
2686
2715
  memoryLabel(h)
2687
2716
  ] })
2688
2717
  ] }),
2689
- /* @__PURE__ */ jsxs5(Box6, { marginTop: 1, flexDirection: "column", children: [
2690
- /* @__PURE__ */ jsx6(Text6, { bold: true, color: "cyan", children: t("performance") }),
2691
- /* @__PURE__ */ jsxs5(Text6, { children: [
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: [
2692
2721
  t("elapsed"),
2693
2722
  " ",
2694
2723
  elapsed.toFixed(1),
2695
2724
  " s"
2696
2725
  ] }),
2697
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: t("measuredAfter") })
2726
+ /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: t("measuredAfter") })
2698
2727
  ] }),
2699
- /* @__PURE__ */ jsxs5(Box6, { marginTop: 1, flexDirection: "column", children: [
2700
- /* @__PURE__ */ jsx6(Text6, { bold: true, color: "cyan", children: t("system") }),
2701
- /* @__PURE__ */ jsxs5(Text6, { children: [
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: [
2702
2731
  "CPU ",
2703
2732
  bar(cpu),
2704
2733
  " ",
2705
2734
  formatPercent(cpu)
2706
2735
  ] }),
2707
- /* @__PURE__ */ jsxs5(Text6, { children: [
2736
+ /* @__PURE__ */ jsxs6(Text7, { children: [
2708
2737
  "GPU ",
2709
2738
  bar(gpu),
2710
2739
  " ",
2711
2740
  formatPercent(gpu)
2712
2741
  ] }),
2713
- /* @__PURE__ */ jsxs5(Text6, { children: [
2742
+ /* @__PURE__ */ jsxs6(Text7, { children: [
2714
2743
  "Memory ",
2715
2744
  bar(memUsed && memTotal ? memUsed / memTotal * 100 : void 0),
2716
2745
  " ",
@@ -2718,55 +2747,55 @@ function BenchmarkView(props) {
2718
2747
  " / ",
2719
2748
  formatBytes(memTotal, 0)
2720
2749
  ] }),
2721
- /* @__PURE__ */ jsxs5(Text6, { children: [
2750
+ /* @__PURE__ */ jsxs6(Text7, { children: [
2722
2751
  "Swap ",
2723
2752
  bar(0),
2724
2753
  " ",
2725
2754
  sample ? formatBytes(sample.memory.swapUsedBytes) : "N/A"
2726
2755
  ] })
2727
2756
  ] }),
2728
- /* @__PURE__ */ jsxs5(Box6, { marginTop: 1, flexDirection: "column", children: [
2729
- /* @__PURE__ */ jsx6(Text6, { bold: true, color: "cyan", children: t("powerThermals") }),
2730
- /* @__PURE__ */ jsxs5(Text6, { children: [
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: [
2731
2760
  "Package ",
2732
2761
  sample?.packagePowerWatts ?? "N/A",
2733
2762
  " W"
2734
2763
  ] }),
2735
- /* @__PURE__ */ jsxs5(Text6, { children: [
2764
+ /* @__PURE__ */ jsxs6(Text7, { children: [
2736
2765
  "Temperature ",
2737
2766
  sample?.thermal?.temperatureC ?? "N/A",
2738
2767
  " \xB0C"
2739
2768
  ] }),
2740
- /* @__PURE__ */ jsxs5(Text6, { children: [
2769
+ /* @__PURE__ */ jsxs6(Text7, { children: [
2741
2770
  "Thermal Pressure ",
2742
2771
  sample?.thermal?.pressure ?? "N/A"
2743
2772
  ] }),
2744
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: t("permissionsHint") })
2773
+ /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: t("permissionsHint") })
2745
2774
  ] }),
2746
- /* @__PURE__ */ jsxs5(Text6, { children: [
2775
+ /* @__PURE__ */ jsxs6(Text7, { children: [
2747
2776
  sparkline(cpuHist.current),
2748
2777
  " CPU"
2749
2778
  ] }),
2750
- /* @__PURE__ */ jsxs5(Text6, { children: [
2779
+ /* @__PURE__ */ jsxs6(Text7, { children: [
2751
2780
  sparkline(memHist.current.map((v) => v / 1024 ** 3)),
2752
2781
  " Memory"
2753
2782
  ] }),
2754
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: t("cancelHint") })
2783
+ /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: t("cancelHint") })
2755
2784
  ] });
2756
2785
  }
2757
2786
 
2758
2787
  // src/tui/views/History.tsx
2759
- import { Box as Box7, Text as Text7 } from "ink";
2760
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2788
+ import { Box as Box8, Text as Text8 } from "ink";
2789
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2761
2790
  function HistoryView({ session }) {
2762
- return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
2763
- /* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: t("measured") }),
2764
- /* @__PURE__ */ jsx7(Text7, { children: historyText(session.history) })
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) })
2765
2794
  ] });
2766
2795
  }
2767
2796
 
2768
2797
  // src/tui/views/Tasks.tsx
2769
- import { Box as Box8, Text as Text8, useInput as useInput3 } from "ink";
2798
+ import { Box as Box9, Text as Text9, useInput as useInput3 } from "ink";
2770
2799
  import { useMemo, useState as useState3 } from "react";
2771
2800
 
2772
2801
  // src/tasks/catalog.ts
@@ -2962,7 +2991,7 @@ function tasksText(plans, answers) {
2962
2991
  }
2963
2992
 
2964
2993
  // src/tui/views/Tasks.tsx
2965
- import { Fragment, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2994
+ import { Fragment, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2966
2995
  var KIND_LABEL = {
2967
2996
  code: "tasksOptCode",
2968
2997
  video: "tasksOptVideo",
@@ -3003,13 +3032,13 @@ function TasksView({ session }) {
3003
3032
  }
3004
3033
  });
3005
3034
  if (step === 3) {
3006
- return /* @__PURE__ */ jsx8(Box8, { flexDirection: "column", children: /* @__PURE__ */ jsx8(Text8, { children: tasksText(plans, { kinds, scope, priority }) }) });
3035
+ return /* @__PURE__ */ jsx9(Box9, { flexDirection: "column", children: /* @__PURE__ */ jsx9(Text9, { children: tasksText(plans, { kinds, scope, priority }) }) });
3007
3036
  }
3008
- return /* @__PURE__ */ jsxs7(Box8, { flexDirection: "column", children: [
3009
- /* @__PURE__ */ jsx8(Text8, { bold: true, color: "cyan", children: t("tasksTitle") }),
3010
- step === 0 && /* @__PURE__ */ jsxs7(Fragment, { children: [
3011
- /* @__PURE__ */ jsx8(Text8, { children: t("tasksQ1") }),
3012
- WORK_KINDS.map((kind, i) => /* @__PURE__ */ jsxs7(Text8, { color: i === cursor ? "cyan" : void 0, children: [
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: [
3013
3042
  i === cursor ? "\u276F " : " ",
3014
3043
  "[",
3015
3044
  kinds.includes(kind) ? "x" : " ",
@@ -3017,20 +3046,20 @@ function TasksView({ session }) {
3017
3046
  t(KIND_LABEL[kind])
3018
3047
  ] }, kind))
3019
3048
  ] }),
3020
- step === 1 && /* @__PURE__ */ jsxs7(Fragment, { children: [
3021
- /* @__PURE__ */ jsx8(Text8, { children: t("tasksQ2") }),
3022
- /* @__PURE__ */ jsxs7(Text8, { color: scope === "installed" ? "cyan" : void 0, children: [
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: [
3023
3052
  scope === "installed" ? "\u276F " : " ",
3024
3053
  t("tasksOptInstalled")
3025
3054
  ] }),
3026
- /* @__PURE__ */ jsxs7(Text8, { color: scope === "all" ? "cyan" : void 0, children: [
3055
+ /* @__PURE__ */ jsxs8(Text9, { color: scope === "all" ? "cyan" : void 0, children: [
3027
3056
  scope === "all" ? "\u276F " : " ",
3028
3057
  t("tasksOptAll")
3029
3058
  ] })
3030
3059
  ] }),
3031
- step === 2 && /* @__PURE__ */ jsxs7(Fragment, { children: [
3032
- /* @__PURE__ */ jsx8(Text8, { children: t("tasksQ3") }),
3033
- ["speed", "balanced", "quality"].map((item) => /* @__PURE__ */ jsxs7(Text8, { color: priority === item ? "cyan" : void 0, children: [
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: [
3034
3063
  priority === item ? "\u276F " : " ",
3035
3064
  item === "speed" ? t("tasksOptSpeed") : item === "quality" ? t("tasksOptQuality") : t("tasksOptBalanced")
3036
3065
  ] }, item))
@@ -3047,7 +3076,7 @@ function globalNav(letter) {
3047
3076
  if (letter === "c") return { type: "screen", screen: "compare" };
3048
3077
  if (letter === "l") return { type: "screen", screen: "history" };
3049
3078
  if (letter === "t") return { type: "screen", screen: "tasks" };
3050
- if (letter === "s") return { type: "screen", screen: "recommend" };
3079
+ if (letter === "s") return { type: "screen", screen: "setup" };
3051
3080
  return void 0;
3052
3081
  }
3053
3082
  function handleAppKey(screen, input, key) {
@@ -3055,66 +3084,66 @@ function handleAppKey(screen, input, key) {
3055
3084
  if (screen === "benchmark") return { type: "ignore" };
3056
3085
  if (letter === "q") return { type: "quit" };
3057
3086
  if (key.escape) return screen === "home" ? { type: "quit" } : { type: "home" };
3058
- if (screen === "recommend") {
3087
+ if (screen === "setup") {
3059
3088
  if (letter === "i" || letter === "1" || letter === "2" || letter === "3") return { type: "ignore" };
3060
3089
  }
3061
3090
  const nav = globalNav(letter);
3062
3091
  if (nav) return nav;
3063
- if (letter === "i" && screen === "home") return { type: "screen", screen: "recommend" };
3092
+ if (letter === "i" && screen === "home") return { type: "screen", screen: "setup" };
3064
3093
  if (key.return && screen === "home") return { type: "screen", screen: "benchmark" };
3065
3094
  return { type: "ignore" };
3066
3095
  }
3067
3096
 
3068
3097
  // src/tui/Welcome.tsx
3069
- import { Box as Box9, Text as Text9 } from "ink";
3070
- import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
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";
3071
3100
  function Chrome() {
3072
3101
  const cols = useCols();
3073
3102
  const wide = cols >= 72;
3074
- return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", width: cols, marginBottom: 1, children: [
3075
- /* @__PURE__ */ jsxs8(Text9, { children: [
3076
- /* @__PURE__ */ jsx9(Text9, { bold: true, color: "cyan", children: t("appTitle") }),
3077
- /* @__PURE__ */ jsx9(Text9, { color: "gray", children: " \xB7 " }),
3078
- /* @__PURE__ */ jsx9(Text9, { color: "magenta", children: t("byline") }),
3079
- wide ? /* @__PURE__ */ jsxs8(Text9, { color: "gray", children: [
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: [
3080
3109
  " \xB7 ",
3081
3110
  fit(t("appSubtitle"), cols - 28)
3082
3111
  ] }) : null
3083
3112
  ] }),
3084
- /* @__PURE__ */ jsx9(Text9, { children: wide ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
3085
- /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "[S] Setup" }),
3086
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
3087
- /* @__PURE__ */ jsx9(Text9, { color: "green", children: "[B] Bench" }),
3088
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
3089
- /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: "[M] Models" }),
3090
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
3091
- /* @__PURE__ */ jsx9(Text9, { color: "magenta", children: "[R] Rec" }),
3092
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
3093
- /* @__PURE__ */ jsx9(Text9, { color: "blue", children: "[T] Tasks" }),
3094
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
3095
- /* @__PURE__ */ jsx9(Text9, { children: "[H] HW" }),
3096
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
3097
- /* @__PURE__ */ jsx9(Text9, { color: "green", children: "[C] Cmp" }),
3098
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
3099
- /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: "[L] Log" }),
3100
- /* @__PURE__ */ jsx9(Text9, { children: " " }),
3101
- /* @__PURE__ */ jsx9(Text9, { color: "red", children: "[Q] Quit" })
3102
- ] }) : /* @__PURE__ */ jsxs8(Fragment2, { children: [
3103
- /* @__PURE__ */ jsx9(Text9, { color: "yellow", children: "[S]" }),
3104
- /* @__PURE__ */ jsx9(Text9, { color: "green", children: "[B]" }),
3105
- /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: "[M]" }),
3106
- /* @__PURE__ */ jsx9(Text9, { color: "magenta", children: "[R]" }),
3107
- /* @__PURE__ */ jsx9(Text9, { color: "blue", children: "[T]" }),
3108
- /* @__PURE__ */ jsx9(Text9, { children: "[H]" }),
3109
- /* @__PURE__ */ jsx9(Text9, { color: "green", children: "[C]" }),
3110
- /* @__PURE__ */ jsx9(Text9, { color: "cyan", children: "[L]" }),
3111
- /* @__PURE__ */ jsx9(Text9, { color: "red", children: "[Q]" })
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]" })
3112
3141
  ] }) })
3113
3142
  ] });
3114
3143
  }
3115
3144
 
3116
3145
  // src/tui/App.tsx
3117
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
3146
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
3118
3147
  function App(props) {
3119
3148
  const { exit } = useApp2();
3120
3149
  const [screen, setScreen] = useState4(props.start ?? "home");
@@ -3131,16 +3160,17 @@ function App(props) {
3131
3160
  if (result.type === "home") setScreen("home");
3132
3161
  if (result.type === "screen") setScreen(result.screen);
3133
3162
  });
3134
- return /* @__PURE__ */ jsxs9(Box10, { flexDirection: "column", paddingX: 1, children: [
3135
- screen !== "benchmark" && /* @__PURE__ */ jsx10(Chrome, {}),
3136
- screen === "home" && /* @__PURE__ */ jsx10(Dashboard, { session: props.session }),
3137
- screen === "models" && /* @__PURE__ */ jsx10(ModelsView, { session: props.session }),
3138
- screen === "hardware" && /* @__PURE__ */ jsx10(HardwareView, { session: props.session }),
3139
- screen === "recommend" && /* @__PURE__ */ jsx10(RecommendView, { session: props.session }),
3140
- screen === "compare" && /* @__PURE__ */ jsx10(CompareView, { session: props.session }),
3141
- screen === "history" && /* @__PURE__ */ jsx10(HistoryView, { session: props.session }),
3142
- screen === "tasks" && /* @__PURE__ */ jsx10(TasksView, { session: props.session }),
3143
- screen === "benchmark" && /* @__PURE__ */ jsx10(
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(
3144
3174
  BenchmarkView,
3145
3175
  {
3146
3176
  session: props.session,
@@ -3155,9 +3185,9 @@ function App(props) {
3155
3185
  }
3156
3186
 
3157
3187
  // src/tui/render.tsx
3158
- import { jsx as jsx11 } from "react/jsx-runtime";
3188
+ import { jsx as jsx12 } from "react/jsx-runtime";
3159
3189
  async function renderDashboard(session, preset, start) {
3160
- const instance = render(/* @__PURE__ */ jsx11(App, { session, preset, start }));
3190
+ const instance = render(/* @__PURE__ */ jsx12(App, { session, preset, start }));
3161
3191
  await instance.waitUntilExit();
3162
3192
  }
3163
3193
 
@@ -3224,7 +3254,7 @@ ${runtimesText(session)}`),
3224
3254
  print({ recommendations: session.recommendations, agents: session.agents }, true);
3225
3255
  return 0;
3226
3256
  }
3227
- await renderDashboard(session, args2.preset, "recommend");
3257
+ await renderDashboard(session, args2.preset, "setup");
3228
3258
  return 0;
3229
3259
  case "recommend": {
3230
3260
  if (args2.install && args2.yes) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pudu-ai",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "description": "Pudu-AI — local AI hardware & benchmark lab for the terminal",
5
5
  "keywords": [
6
6
  "ai",