ai-speedometer 2.3.3 → 2.4.0

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.
@@ -1,9 +1,4 @@
1
- #!/bin/sh -
2
- ':'; /*-
3
- test1=$(bun --version 2>&1) && exec bun "$0" "$@"
4
- test2=$(node --version 2>&1) && exec node "$0" "$@"
5
- exec printf '%s\n' "$test1" "$test2" 1>&2
6
- */
1
+ #!/usr/bin/env bun
7
2
  // @bun
8
3
  var __defProp = Object.defineProperty;
9
4
  var __returnValue = (v) => v;
@@ -22,6 +17,28 @@ var __export = (target, all) => {
22
17
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
23
18
  var __require = import.meta.require;
24
19
 
20
+ // ../../node_modules/.bun/xdg-basedir@5.1.0/node_modules/xdg-basedir/index.js
21
+ import os from "os";
22
+ import path from "path";
23
+ var homeDirectory, env, xdgData, xdgConfig, xdgState, xdgCache, xdgRuntime, xdgDataDirectories, xdgConfigDirectories;
24
+ var init_xdg_basedir = __esm(() => {
25
+ homeDirectory = os.homedir();
26
+ ({ env } = process);
27
+ xdgData = env.XDG_DATA_HOME || (homeDirectory ? path.join(homeDirectory, ".local", "share") : undefined);
28
+ xdgConfig = env.XDG_CONFIG_HOME || (homeDirectory ? path.join(homeDirectory, ".config") : undefined);
29
+ xdgState = env.XDG_STATE_HOME || (homeDirectory ? path.join(homeDirectory, ".local", "state") : undefined);
30
+ xdgCache = env.XDG_CACHE_HOME || (homeDirectory ? path.join(homeDirectory, ".cache") : undefined);
31
+ xdgRuntime = env.XDG_RUNTIME_DIR || undefined;
32
+ xdgDataDirectories = (env.XDG_DATA_DIRS || "/usr/local/share/:/usr/share/").split(":");
33
+ if (xdgData) {
34
+ xdgDataDirectories.unshift(xdgData);
35
+ }
36
+ xdgConfigDirectories = (env.XDG_CONFIG_DIRS || "/etc/xdg").split(":");
37
+ if (xdgConfig) {
38
+ xdgConfigDirectories.unshift(xdgConfig);
39
+ }
40
+ });
41
+
25
42
  // ../core/custom-verified-providers.json
26
43
  var custom_verified_providers_default;
27
44
  var init_custom_verified_providers = __esm(() => {
@@ -160,7 +177,7 @@ __export(exports_models_dev, {
160
177
  clearCache: () => clearCache
161
178
  });
162
179
  import fs from "fs";
163
- import path from "path";
180
+ import path2 from "path";
164
181
  import { homedir } from "os";
165
182
  function ensureCacheDir() {
166
183
  try {
@@ -212,7 +229,7 @@ async function fetchFromAPI() {
212
229
  }
213
230
  function getCustomProvidersJson() {
214
231
  let data = custom_verified_providers_default;
215
- const customProvidersPath = path.join(process.cwd(), "custom-verified-providers.json");
232
+ const customProvidersPath = path2.join(process.cwd(), "custom-verified-providers.json");
216
233
  if (fs.existsSync(customProvidersPath)) {
217
234
  try {
218
235
  data = JSON.parse(fs.readFileSync(customProvidersPath, "utf8"));
@@ -349,11 +366,13 @@ function clearCache() {
349
366
  console.warn("Warning: Could not clear cache:", error.message);
350
367
  }
351
368
  }
352
- var CACHE_DIR, CACHE_FILE, FALLBACK_PROVIDERS;
369
+ var cacheBase, CACHE_DIR, CACHE_FILE, FALLBACK_PROVIDERS;
353
370
  var init_models_dev = __esm(() => {
371
+ init_xdg_basedir();
354
372
  init_custom_verified_providers();
355
- CACHE_DIR = path.join(homedir(), ".cache", "ai-speedometer");
356
- CACHE_FILE = path.join(CACHE_DIR, "models.json");
373
+ cacheBase = process.env.XDG_CACHE_HOME || xdgCache || path2.join(homedir(), ".cache");
374
+ CACHE_DIR = path2.join(cacheBase, "ai-speedometer");
375
+ CACHE_FILE = path2.join(CACHE_DIR, "models.json");
357
376
  FALLBACK_PROVIDERS = [
358
377
  {
359
378
  id: "openai",
@@ -413,15 +432,15 @@ __export(exports_ai_config, {
413
432
  addCustomProvider: () => addCustomProvider
414
433
  });
415
434
  import fs2 from "fs";
416
- import path2 from "path";
435
+ import path3 from "path";
417
436
  import { homedir as homedir2 } from "os";
418
437
  var getAIConfigPaths = () => {
419
- const aiConfigDir = process.env.XDG_CONFIG_HOME || path2.join(homedir2(), ".config");
420
- const aiSpeedometerConfigDir = path2.join(aiConfigDir, "ai-speedometer");
438
+ const aiConfigDir = process.env.XDG_CONFIG_HOME || xdgConfig || path3.join(homedir2(), ".config");
439
+ const aiSpeedometerConfigDir = path3.join(aiConfigDir, "ai-speedometer");
421
440
  return {
422
441
  configDir: aiSpeedometerConfigDir,
423
- configJson: path2.join(aiSpeedometerConfigDir, "ai-benchmark-config.json"),
424
- recentModelsCache: path2.join(aiSpeedometerConfigDir, "recent-models.json")
442
+ configJson: path3.join(aiSpeedometerConfigDir, "ai-benchmark-config.json"),
443
+ recentModelsCache: path3.join(aiSpeedometerConfigDir, "recent-models.json")
425
444
  };
426
445
  }, ensureAIConfigDirectory = () => {
427
446
  const { configDir } = getAIConfigPaths();
@@ -442,7 +461,7 @@ var getAIConfigPaths = () => {
442
461
  }
443
462
  }, readThemeFromConfig = async () => {
444
463
  const config = await readAIConfig();
445
- return config.theme ?? "tokyonight";
464
+ return config.theme ?? "minimal-b";
446
465
  }, writeThemeToConfig = async (theme) => {
447
466
  const config = await readAIConfig();
448
467
  await writeAIConfig({ ...config, theme });
@@ -569,7 +588,9 @@ var getAIConfigPaths = () => {
569
588
  const paths = getAIConfigPaths();
570
589
  return { ...paths, configExists: fs2.existsSync(paths.configJson) };
571
590
  };
572
- var init_ai_config = () => {};
591
+ var init_ai_config = __esm(() => {
592
+ init_xdg_basedir();
593
+ });
573
594
 
574
595
  // ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
575
596
  function createScanner(text, ignoreTrivia = false) {
@@ -1418,16 +1439,16 @@ __export(exports_opencode_integration, {
1418
1439
  addApiKey: () => addApiKey
1419
1440
  });
1420
1441
  import fs3 from "fs";
1421
- import path3 from "path";
1442
+ import path4 from "path";
1422
1443
  import { homedir as homedir3 } from "os";
1423
1444
  var getXDGPaths = () => ({
1424
- data: path3.join(process.env.XDG_DATA_HOME || path3.join(homedir3(), ".local", "share"), "opencode"),
1425
- config: path3.join(process.env.XDG_CONFIG_HOME || path3.join(homedir3(), ".config"), "opencode")
1445
+ data: path4.join(process.env.XDG_DATA_HOME || xdgData || path4.join(path4.join(process.env.HOME || process.env.USERPROFILE || "."), ".local", "share"), "opencode"),
1446
+ config: path4.join(process.env.XDG_CONFIG_HOME || xdgConfig || path4.join(path4.join(process.env.HOME || process.env.USERPROFILE || "."), ".config"), "opencode")
1426
1447
  }), getFilePaths = () => {
1427
1448
  const paths = getXDGPaths();
1428
1449
  return {
1429
- authJson: path3.join(paths.data, "auth.json"),
1430
- opencodeJson: path3.join(paths.config, "opencode.json")
1450
+ authJson: path4.join(paths.data, "auth.json"),
1451
+ opencodeJson: path4.join(paths.config, "opencode.json")
1431
1452
  };
1432
1453
  }, ensureDirectories = () => {
1433
1454
  const paths = getXDGPaths();
@@ -1457,7 +1478,9 @@ var getXDGPaths = () => ({
1457
1478
  try {
1458
1479
  ensureDirectories();
1459
1480
  fs3.writeFileSync(authJson, JSON.stringify(authData, null, 2));
1460
- fs3.chmodSync(authJson, 384);
1481
+ try {
1482
+ fs3.chmodSync(authJson, 384);
1483
+ } catch {}
1461
1484
  return true;
1462
1485
  } catch (error) {
1463
1486
  console.error("Error writing auth.json:", error.message);
@@ -1470,11 +1493,11 @@ var getXDGPaths = () => ({
1470
1493
  console.warn("Warning: opencode.json is no longer used. Use ai-benchmark-config.json instead.");
1471
1494
  return { provider: {} };
1472
1495
  }, readOpencodeGlobalConfig = () => {
1473
- const configDir = path3.join(process.env.XDG_CONFIG_HOME || path3.join(homedir3(), ".config"), "opencode");
1496
+ const configDir = path4.join(process.env.XDG_CONFIG_HOME || path4.join(homedir3(), ".config"), "opencode");
1474
1497
  const candidates = ["config.json", "opencode.json", "opencode.jsonc"];
1475
1498
  let merged = {};
1476
1499
  for (const filename of candidates) {
1477
- const filePath = path3.join(configDir, filename);
1500
+ const filePath = path4.join(configDir, filename);
1478
1501
  try {
1479
1502
  if (!fs3.existsSync(filePath))
1480
1503
  continue;
@@ -1712,6 +1735,7 @@ var getXDGPaths = () => ({
1712
1735
  };
1713
1736
  };
1714
1737
  var init_opencode_integration = __esm(() => {
1738
+ init_xdg_basedir();
1715
1739
  init_models_dev();
1716
1740
  init_ai_config();
1717
1741
  init_main();
@@ -1719,6 +1743,7 @@ var init_opencode_integration = __esm(() => {
1719
1743
 
1720
1744
  // ../core/src/constants.ts
1721
1745
  import { execSync } from "child_process";
1746
+ import { readFileSync } from "fs";
1722
1747
  function getOpencodeSystemPrompt(modelId) {
1723
1748
  const mid = modelId.toLowerCase();
1724
1749
  if (mid.includes("gpt-4") || mid.includes("o1") || mid.includes("o3"))
@@ -1759,10 +1784,10 @@ function getOpencodeVersion() {
1759
1784
  return v;
1760
1785
  } catch {
1761
1786
  try {
1762
- return execSync(`grep -E '^\\s*"version"' /home/idc/proj/opencode/packages/opencode/package.json | sed 's/.*: "\\([^"]*\\)".*/\\1/'`, {
1763
- encoding: "utf8",
1764
- stdio: ["ignore", "pipe", "ignore"]
1765
- }).trim();
1787
+ const pkgJson = readFileSync("/home/idc/proj/opencode/packages/opencode/package.json", "utf8");
1788
+ const parsed = JSON.parse(pkgJson);
1789
+ if (parsed.version)
1790
+ return parsed.version;
1766
1791
  } catch {}
1767
1792
  }
1768
1793
  return "1.14.37";
@@ -2897,11 +2922,24 @@ async function benchmarkSingleModelRest(model, logger) {
2897
2922
  };
2898
2923
  });
2899
2924
  }
2900
- const response = await fetch(url, {
2925
+ let response = await fetch(url, {
2901
2926
  method: "POST",
2902
2927
  headers,
2903
2928
  body: JSON.stringify(body)
2904
2929
  });
2930
+ if (!response.ok && (response.status === 400 || response.status === 422)) {
2931
+ const errText = await response.text();
2932
+ if (errText.includes("2013") || errText.includes("invalid params") || errText.includes("invalid chat setting")) {
2933
+ delete body["tools"];
2934
+ delete body["tool_choice"];
2935
+ delete body["stream_options"];
2936
+ response = await fetch(url, {
2937
+ method: "POST",
2938
+ headers,
2939
+ body: JSON.stringify(body)
2940
+ });
2941
+ }
2942
+ }
2905
2943
  if (!response.ok) {
2906
2944
  const errBody = await response.text();
2907
2945
  let errDetail = "";
@@ -3274,11 +3312,13 @@ function createRunId() {
3274
3312
  return generateRunId();
3275
3313
  }
3276
3314
  function getLogPath(runId) {
3277
- return join(homedir4(), ".local", "share", "ai-speedometer", "logs", `${runId}.log`);
3315
+ const baseDir = process.env.XDG_DATA_HOME || xdgData || join(homedir4(), ".local", "share");
3316
+ return join(baseDir, "ai-speedometer", "logs", `${runId}.log`);
3278
3317
  }
3279
3318
  async function createBenchLogger(runId) {
3280
3319
  const logPath = getLogPath(runId);
3281
- const logDir = join(homedir4(), ".local", "share", "ai-speedometer", "logs");
3320
+ const baseDir = process.env.XDG_DATA_HOME || xdgData || join(homedir4(), ".local", "share");
3321
+ const logDir = join(baseDir, "ai-speedometer", "logs");
3282
3322
  await mkdir(logDir, { recursive: true });
3283
3323
  let currentApiKey = "";
3284
3324
  let buffer = "";
@@ -3306,7 +3346,9 @@ async function createBenchLogger(runId) {
3306
3346
  }
3307
3347
  };
3308
3348
  }
3309
- var init_logger = () => {};
3349
+ var init_logger = __esm(() => {
3350
+ init_xdg_basedir();
3351
+ });
3310
3352
 
3311
3353
  // src/tui/context/AppContext.tsx
3312
3354
  import { createContext, useContext, useReducer, useEffect } from "react";
@@ -3415,7 +3457,7 @@ var init_AppContext = __esm(() => {
3415
3457
  function getTheme(name) {
3416
3458
  return THEMES[name] ?? THEMES[DEFAULT_THEME];
3417
3459
  }
3418
- var THEMES, DEFAULT_THEME = "tokyonight", THEME_NAMES;
3460
+ var THEMES, DEFAULT_THEME = "minimal-b", THEME_NAMES;
3419
3461
  var init_themes = __esm(() => {
3420
3462
  THEMES = {
3421
3463
  tokyonight: {
@@ -3846,6 +3888,32 @@ var init_themes = __esm(() => {
3846
3888
  success: "#388E3C",
3847
3889
  error: "#DC3545",
3848
3890
  warning: "#FF9500"
3891
+ },
3892
+ "minimal-b": {
3893
+ background: "#000000",
3894
+ surface: "#000000",
3895
+ border: "#333333",
3896
+ dim: "#888888",
3897
+ text: "#FFFFFF",
3898
+ primary: "#FFFFFF",
3899
+ accent: "#FFFFFF",
3900
+ secondary: "#FFFFFF",
3901
+ success: "#FFFFFF",
3902
+ error: "#FFFFFF",
3903
+ warning: "#FFFFFF"
3904
+ },
3905
+ "minimal-w": {
3906
+ background: "#FFFFFF",
3907
+ surface: "#FFFFFF",
3908
+ border: "#CCCCCC",
3909
+ dim: "#777777",
3910
+ text: "#000000",
3911
+ primary: "#000000",
3912
+ accent: "#000000",
3913
+ secondary: "#000000",
3914
+ success: "#000000",
3915
+ error: "#000000",
3916
+ warning: "#000000"
3849
3917
  }
3850
3918
  };
3851
3919
  THEME_NAMES = Object.keys(THEMES);
@@ -3974,7 +4042,7 @@ function ThemePicker({ onClose }) {
3974
4042
  width: W,
3975
4043
  flexDirection: "column",
3976
4044
  border: true,
3977
- borderStyle: "rounded",
4045
+ borderStyle: "single",
3978
4046
  borderColor: theme.primary,
3979
4047
  backgroundColor: theme.surface,
3980
4048
  zIndex: 100,
@@ -4005,7 +4073,10 @@ function ThemePicker({ onClose }) {
4005
4073
  }, undefined, true, undefined, this),
4006
4074
  /* @__PURE__ */ jsxDEV4("box", {
4007
4075
  height: 1,
4008
- backgroundColor: theme.border
4076
+ children: /* @__PURE__ */ jsxDEV4("text", {
4077
+ fg: theme.border,
4078
+ children: "\u2500".repeat(150)
4079
+ }, undefined, false, undefined, this)
4009
4080
  }, undefined, false, undefined, this),
4010
4081
  /* @__PURE__ */ jsxDEV4("box", {
4011
4082
  height: 1,
@@ -4031,7 +4102,10 @@ function ThemePicker({ onClose }) {
4031
4102
  }, undefined, true, undefined, this),
4032
4103
  /* @__PURE__ */ jsxDEV4("box", {
4033
4104
  height: 1,
4034
- backgroundColor: theme.border
4105
+ children: /* @__PURE__ */ jsxDEV4("text", {
4106
+ fg: theme.border,
4107
+ children: "\u2500".repeat(150)
4108
+ }, undefined, false, undefined, this)
4035
4109
  }, undefined, false, undefined, this),
4036
4110
  /* @__PURE__ */ jsxDEV4("scrollbox", {
4037
4111
  ref: scrollRef,
@@ -4084,7 +4158,10 @@ function ThemePicker({ onClose }) {
4084
4158
  }, undefined, false, undefined, this),
4085
4159
  /* @__PURE__ */ jsxDEV4("box", {
4086
4160
  height: 1,
4087
- backgroundColor: theme.border
4161
+ children: /* @__PURE__ */ jsxDEV4("text", {
4162
+ fg: theme.border,
4163
+ children: "\u2500".repeat(150)
4164
+ }, undefined, false, undefined, this)
4088
4165
  }, undefined, false, undefined, this),
4089
4166
  /* @__PURE__ */ jsxDEV4("box", {
4090
4167
  height: 1,
@@ -4131,7 +4208,7 @@ var package_default;
4131
4208
  var init_package = __esm(() => {
4132
4209
  package_default = {
4133
4210
  name: "ai-speedometer",
4134
- version: "2.3.3",
4211
+ version: "2.4.0",
4135
4212
  description: "A comprehensive CLI tool for benchmarking AI models across multiple providers with parallel execution and professional metrics",
4136
4213
  bin: {
4137
4214
  "ai-speedometer": "dist/ai-speedometer",
@@ -4143,7 +4220,7 @@ var init_package = __esm(() => {
4143
4220
  scripts: {
4144
4221
  start: "bun src/index.ts",
4145
4222
  dev: "bun --watch src/index.ts",
4146
- build: "bun build src/index.ts --outdir dist --target bun --external '@opentui/core' --external '@opentui/react' --external 'react' --external 'react-reconciler' && cat ../../scripts/shebang dist/index.js > dist/ai-speedometer && chmod +x dist/ai-speedometer && rm dist/index.js",
4223
+ build: "node ../../scripts/build-tui.mjs",
4147
4224
  typecheck: "bun tsc --noEmit",
4148
4225
  prepublishOnly: "bun run build"
4149
4226
  },
@@ -4233,7 +4310,6 @@ function Footer({ hints }) {
4233
4310
  const theme = useTheme();
4234
4311
  const joined = hints.join(" \xB7 ");
4235
4312
  return /* @__PURE__ */ jsxDEV6("box", {
4236
- height: 1,
4237
4313
  flexDirection: "row",
4238
4314
  alignItems: "center",
4239
4315
  paddingLeft: 1,
@@ -4278,20 +4354,23 @@ function MainMenuScreen() {
4278
4354
  { label: "? FAQ / Learn", desc: "how metrics work & resources", color: theme.primary },
4279
4355
  { label: "\u2715 Exit", desc: "quit the application", color: theme.error }
4280
4356
  ];
4357
+ function handleSelect(index) {
4358
+ if (index === 0)
4359
+ navigate("model-select");
4360
+ else if (index === 1)
4361
+ navigate("model-menu");
4362
+ else if (index === 2)
4363
+ navigate("faq");
4364
+ else if (index === 3)
4365
+ renderer.destroy();
4366
+ }
4281
4367
  useAppKeyboard((key) => {
4282
4368
  if (key.name === "up") {
4283
4369
  setCursor((i) => (i - 1 + ITEMS.length) % ITEMS.length);
4284
4370
  } else if (key.name === "down") {
4285
4371
  setCursor((i) => (i + 1) % ITEMS.length);
4286
4372
  } else if (key.name === "enter" || key.name === "return") {
4287
- if (cursor === 0)
4288
- navigate("model-select");
4289
- else if (cursor === 1)
4290
- navigate("model-menu");
4291
- else if (cursor === 2)
4292
- navigate("faq");
4293
- else if (cursor === 3)
4294
- renderer.destroy();
4373
+ handleSelect(cursor);
4295
4374
  }
4296
4375
  });
4297
4376
  return /* @__PURE__ */ jsxDEV7("box", {
@@ -4322,7 +4401,7 @@ function MainMenuScreen() {
4322
4401
  /* @__PURE__ */ jsxDEV7("box", {
4323
4402
  flexDirection: "column",
4324
4403
  border: true,
4325
- borderStyle: "rounded",
4404
+ borderStyle: "single",
4326
4405
  borderColor: theme.border,
4327
4406
  backgroundColor: theme.background,
4328
4407
  width: 48,
@@ -4336,6 +4415,8 @@ function MainMenuScreen() {
4336
4415
  paddingRight: 2,
4337
4416
  paddingTop: 1,
4338
4417
  paddingBottom: 1,
4418
+ onMouseOver: () => setCursor(i),
4419
+ onMouseDown: () => handleSelect(i),
4339
4420
  children: [
4340
4421
  /* @__PURE__ */ jsxDEV7("box", {
4341
4422
  flexDirection: "column",
@@ -4369,74 +4450,13 @@ var init_MainMenuScreen = __esm(() => {
4369
4450
  init_package();
4370
4451
  });
4371
4452
 
4372
- // src/tui/components/MenuList.tsx
4453
+ // src/tui/screens/ModelMenuScreen.tsx
4373
4454
  import { useState as useState5 } from "react";
4374
4455
  import { jsxDEV as jsxDEV8 } from "@opentui/react/jsx-dev-runtime";
4375
- function MenuList({ items, selectedIndex: initialIndex = 0, onSelect, onNavigate }) {
4376
- const theme = useTheme();
4377
- const [cursor, setCursor] = useState5(initialIndex);
4378
- useAppKeyboard((key) => {
4379
- if (key.name === "up") {
4380
- const next = (cursor - 1 + items.length) % items.length;
4381
- setCursor(next);
4382
- onNavigate?.(next);
4383
- } else if (key.name === "down") {
4384
- const next = (cursor + 1) % items.length;
4385
- setCursor(next);
4386
- onNavigate?.(next);
4387
- } else if (key.name === "enter" || key.name === "return") {
4388
- onSelect(cursor);
4389
- }
4390
- });
4391
- return /* @__PURE__ */ jsxDEV8("box", {
4392
- flexDirection: "column",
4393
- children: items.map((item, i) => {
4394
- const isSelected = i === cursor;
4395
- return /* @__PURE__ */ jsxDEV8("box", {
4396
- flexDirection: "row",
4397
- alignItems: "center",
4398
- backgroundColor: isSelected ? theme.border : "transparent",
4399
- paddingLeft: 1,
4400
- paddingRight: 1,
4401
- children: [
4402
- /* @__PURE__ */ jsxDEV8("box", {
4403
- flexDirection: "column",
4404
- flexGrow: 1,
4405
- children: [
4406
- /* @__PURE__ */ jsxDEV8("text", {
4407
- fg: isSelected ? theme.text : theme.dim,
4408
- children: item.label
4409
- }, undefined, false, undefined, this),
4410
- item.description ? /* @__PURE__ */ jsxDEV8("text", {
4411
- fg: isSelected ? theme.dim : theme.border,
4412
- children: item.description
4413
- }, undefined, false, undefined, this) : null
4414
- ]
4415
- }, undefined, true, undefined, this),
4416
- isSelected && /* @__PURE__ */ jsxDEV8("text", {
4417
- fg: theme.primary,
4418
- children: "\u203A"
4419
- }, undefined, false, undefined, this)
4420
- ]
4421
- }, i, true, undefined, this);
4422
- })
4423
- }, undefined, false, undefined, this);
4424
- }
4425
- var init_MenuList = __esm(() => {
4426
- init_useAppKeyboard();
4427
- init_ThemeContext();
4428
- });
4429
-
4430
- // src/tui/screens/ModelMenuScreen.tsx
4431
- import { jsxDEV as jsxDEV9 } from "@opentui/react/jsx-dev-runtime";
4432
4456
  function ModelMenuScreen() {
4433
4457
  const navigate = useNavigate();
4434
4458
  const theme = useTheme();
4435
- useAppKeyboard((key) => {
4436
- if (key.name === "escape" || key.name === "q") {
4437
- navigate("main-menu");
4438
- }
4439
- });
4459
+ const [cursor, setCursor] = useState5(0);
4440
4460
  function handleSelect(index) {
4441
4461
  if (index === 0)
4442
4462
  navigate("add-verified");
@@ -4449,21 +4469,81 @@ function ModelMenuScreen() {
4449
4469
  else if (index === 4)
4450
4470
  navigate("main-menu");
4451
4471
  }
4452
- return /* @__PURE__ */ jsxDEV9("box", {
4472
+ useAppKeyboard((key) => {
4473
+ if (key.name === "up") {
4474
+ setCursor((i) => (i - 1 + ITEMS.length) % ITEMS.length);
4475
+ } else if (key.name === "down") {
4476
+ setCursor((i) => (i + 1) % ITEMS.length);
4477
+ } else if (key.name === "enter" || key.name === "return") {
4478
+ handleSelect(cursor);
4479
+ } else if (key.name === "escape" || key.name === "q") {
4480
+ navigate("main-menu");
4481
+ }
4482
+ });
4483
+ return /* @__PURE__ */ jsxDEV8("box", {
4453
4484
  flexDirection: "column",
4454
4485
  flexGrow: 1,
4455
- padding: 1,
4486
+ alignItems: "center",
4487
+ justifyContent: "center",
4456
4488
  children: [
4457
- /* @__PURE__ */ jsxDEV9("text", {
4458
- fg: theme.primary,
4459
- children: "Model Management"
4460
- }, undefined, false, undefined, this),
4461
- /* @__PURE__ */ jsxDEV9("box", {
4462
- marginTop: 1,
4463
- children: /* @__PURE__ */ jsxDEV9(MenuList, {
4464
- items: ITEMS,
4465
- onSelect: handleSelect
4466
- }, undefined, false, undefined, this)
4489
+ /* @__PURE__ */ jsxDEV8("box", {
4490
+ flexDirection: "column",
4491
+ alignItems: "center",
4492
+ marginBottom: 2,
4493
+ children: [
4494
+ /* @__PURE__ */ jsxDEV8("text", {
4495
+ fg: theme.primary,
4496
+ bold: true,
4497
+ children: "MODEL MANAGEMENT"
4498
+ }, undefined, false, undefined, this),
4499
+ /* @__PURE__ */ jsxDEV8("text", {
4500
+ fg: theme.dim,
4501
+ children: "configure providers & models"
4502
+ }, undefined, false, undefined, this)
4503
+ ]
4504
+ }, undefined, true, undefined, this),
4505
+ /* @__PURE__ */ jsxDEV8("box", {
4506
+ flexDirection: "column",
4507
+ border: true,
4508
+ borderStyle: "single",
4509
+ borderColor: theme.border,
4510
+ backgroundColor: theme.background,
4511
+ width: 48,
4512
+ children: ITEMS.map((item, i) => {
4513
+ const active = i === cursor;
4514
+ const color = theme[item.color];
4515
+ return /* @__PURE__ */ jsxDEV8("box", {
4516
+ flexDirection: "row",
4517
+ alignItems: "center",
4518
+ backgroundColor: active ? theme.border : "transparent",
4519
+ paddingLeft: 2,
4520
+ paddingRight: 2,
4521
+ paddingTop: 1,
4522
+ paddingBottom: 1,
4523
+ onMouseOver: () => setCursor(i),
4524
+ onMouseDown: () => handleSelect(i),
4525
+ children: [
4526
+ /* @__PURE__ */ jsxDEV8("box", {
4527
+ flexDirection: "column",
4528
+ flexGrow: 1,
4529
+ children: [
4530
+ /* @__PURE__ */ jsxDEV8("text", {
4531
+ fg: active ? color : theme.dim,
4532
+ children: item.label
4533
+ }, undefined, false, undefined, this),
4534
+ /* @__PURE__ */ jsxDEV8("text", {
4535
+ fg: active ? theme.dim : theme.border,
4536
+ children: item.desc
4537
+ }, undefined, false, undefined, this)
4538
+ ]
4539
+ }, undefined, true, undefined, this),
4540
+ active && /* @__PURE__ */ jsxDEV8("text", {
4541
+ fg: color,
4542
+ children: "\u203A"
4543
+ }, undefined, false, undefined, this)
4544
+ ]
4545
+ }, i, true, undefined, this);
4546
+ })
4467
4547
  }, undefined, false, undefined, this)
4468
4548
  ]
4469
4549
  }, undefined, true, undefined, this);
@@ -4473,13 +4553,12 @@ var init_ModelMenuScreen = __esm(() => {
4473
4553
  init_useAppKeyboard();
4474
4554
  init_AppContext();
4475
4555
  init_ThemeContext();
4476
- init_MenuList();
4477
4556
  ITEMS = [
4478
- { label: "Add Verified Provider" },
4479
- { label: "Add Custom Provider" },
4480
- { label: "Add Models to Provider" },
4481
- { label: "List Providers" },
4482
- { label: "Back" }
4557
+ { label: "Add Verified Provider", desc: "from models.dev verified list", color: "accent" },
4558
+ { label: "Add Custom Provider", desc: "configure your own API endpoint", color: "secondary" },
4559
+ { label: "Add Models to Provider", desc: "register models for a provider", color: "primary" },
4560
+ { label: "List Providers", desc: "view all configured providers", color: "text" },
4561
+ { label: "Back", desc: "return to main menu", color: "error" }
4483
4562
  ];
4484
4563
  });
4485
4564
 
@@ -4503,7 +4582,7 @@ var init_usePaste = () => {};
4503
4582
  // src/tui/screens/ModelSelectScreen.tsx
4504
4583
  import { useState as useState6, useEffect as useEffect4, useCallback as useCallback2, useRef as useRef3 } from "react";
4505
4584
  import { useTerminalDimensions } from "@opentui/react";
4506
- import { jsxDEV as jsxDEV10 } from "@opentui/react/jsx-dev-runtime";
4585
+ import { jsxDEV as jsxDEV9 } from "@opentui/react/jsx-dev-runtime";
4507
4586
  function ModelSelectScreen() {
4508
4587
  const { state, dispatch } = useAppContext();
4509
4588
  const navigate = useNavigate();
@@ -4665,12 +4744,12 @@ function ModelSelectScreen() {
4665
4744
  setSearchQuery((q) => q + key.sequence);
4666
4745
  });
4667
4746
  if (state.isLoadingConfig) {
4668
- return /* @__PURE__ */ jsxDEV10("box", {
4747
+ return /* @__PURE__ */ jsxDEV9("box", {
4669
4748
  flexDirection: "column",
4670
4749
  flexGrow: 1,
4671
4750
  alignItems: "center",
4672
4751
  justifyContent: "center",
4673
- children: /* @__PURE__ */ jsxDEV10("text", {
4752
+ children: /* @__PURE__ */ jsxDEV9("text", {
4674
4753
  fg: theme.dim,
4675
4754
  children: "Loading config..."
4676
4755
  }, undefined, false, undefined, this)
@@ -4678,31 +4757,31 @@ function ModelSelectScreen() {
4678
4757
  }
4679
4758
  const nameW = Math.floor((CARD_W - 10) / 2);
4680
4759
  const provW = CARD_W - nameW - 10;
4681
- return /* @__PURE__ */ jsxDEV10("box", {
4760
+ return /* @__PURE__ */ jsxDEV9("box", {
4682
4761
  flexDirection: "column",
4683
4762
  flexGrow: 1,
4684
4763
  alignItems: "center",
4685
4764
  justifyContent: "center",
4686
- children: /* @__PURE__ */ jsxDEV10("box", {
4765
+ children: /* @__PURE__ */ jsxDEV9("box", {
4687
4766
  flexDirection: "column",
4688
4767
  border: true,
4689
- borderStyle: "rounded",
4768
+ borderStyle: "single",
4690
4769
  borderColor: theme.border,
4691
4770
  backgroundColor: theme.background,
4692
4771
  width: CARD_W,
4693
4772
  children: [
4694
- /* @__PURE__ */ jsxDEV10("box", {
4773
+ /* @__PURE__ */ jsxDEV9("box", {
4695
4774
  flexDirection: "row",
4696
4775
  paddingLeft: 2,
4697
4776
  paddingRight: 2,
4698
4777
  paddingTop: 1,
4699
4778
  paddingBottom: 1,
4700
4779
  children: [
4701
- /* @__PURE__ */ jsxDEV10("text", {
4780
+ /* @__PURE__ */ jsxDEV9("text", {
4702
4781
  fg: theme.accent,
4703
4782
  children: "Search: "
4704
4783
  }, undefined, false, undefined, this),
4705
- /* @__PURE__ */ jsxDEV10("text", {
4784
+ /* @__PURE__ */ jsxDEV9("text", {
4706
4785
  fg: theme.text,
4707
4786
  children: [
4708
4787
  searchQuery,
@@ -4711,19 +4790,22 @@ function ModelSelectScreen() {
4711
4790
  }, undefined, true, undefined, this)
4712
4791
  ]
4713
4792
  }, undefined, true, undefined, this),
4714
- /* @__PURE__ */ jsxDEV10("box", {
4793
+ /* @__PURE__ */ jsxDEV9("box", {
4715
4794
  height: 1,
4716
- backgroundColor: theme.border
4795
+ children: /* @__PURE__ */ jsxDEV9("text", {
4796
+ fg: theme.border,
4797
+ children: "\u2500".repeat(150)
4798
+ }, undefined, false, undefined, this)
4717
4799
  }, undefined, false, undefined, this),
4718
- /* @__PURE__ */ jsxDEV10("scrollbox", {
4800
+ /* @__PURE__ */ jsxDEV9("scrollbox", {
4719
4801
  ref: scrollboxRef,
4720
4802
  height: PAGE_SIZE,
4721
4803
  style: { scrollbarOptions: { showArrows: true, trackOptions: { foregroundColor: theme.primary, backgroundColor: theme.border } } },
4722
4804
  children: [
4723
- allRows.length === 0 && /* @__PURE__ */ jsxDEV10("box", {
4805
+ allRows.length === 0 && /* @__PURE__ */ jsxDEV9("box", {
4724
4806
  height: 1,
4725
4807
  paddingLeft: 2,
4726
- children: /* @__PURE__ */ jsxDEV10("text", {
4808
+ children: /* @__PURE__ */ jsxDEV9("text", {
4727
4809
  fg: theme.dim,
4728
4810
  children: "No models found"
4729
4811
  }, undefined, false, undefined, this)
@@ -4732,10 +4814,10 @@ function ModelSelectScreen() {
4732
4814
  let modelCursor = 0;
4733
4815
  return allRows.map((row, i) => {
4734
4816
  if (row.kind === "separator")
4735
- return /* @__PURE__ */ jsxDEV10("box", {
4817
+ return /* @__PURE__ */ jsxDEV9("box", {
4736
4818
  height: 1,
4737
4819
  paddingLeft: 2,
4738
- children: /* @__PURE__ */ jsxDEV10("text", {
4820
+ children: /* @__PURE__ */ jsxDEV9("text", {
4739
4821
  fg: theme.dim,
4740
4822
  children: row.label
4741
4823
  }, undefined, false, undefined, this)
@@ -4750,33 +4832,45 @@ function ModelSelectScreen() {
4750
4832
  nameFg = theme.text;
4751
4833
  else if (isSel)
4752
4834
  nameFg = theme.success;
4753
- return /* @__PURE__ */ jsxDEV10("box", {
4835
+ return /* @__PURE__ */ jsxDEV9("box", {
4754
4836
  height: 1,
4755
4837
  width: "100%",
4756
4838
  flexDirection: "row",
4757
4839
  backgroundColor: isActive ? theme.border : "transparent",
4840
+ onMouseOver: () => setCursor(localCursor),
4841
+ onMouseDown: () => {
4842
+ setCursor(localCursor);
4843
+ setSelected((prev) => {
4844
+ const next = new Set(prev);
4845
+ if (next.has(row.model.key))
4846
+ next.delete(row.model.key);
4847
+ else
4848
+ next.add(row.model.key);
4849
+ return next;
4850
+ });
4851
+ },
4758
4852
  children: [
4759
- /* @__PURE__ */ jsxDEV10("text", {
4853
+ /* @__PURE__ */ jsxDEV9("text", {
4760
4854
  fg: theme.dim,
4761
4855
  width: 2,
4762
4856
  children: " "
4763
4857
  }, undefined, false, undefined, this),
4764
- /* @__PURE__ */ jsxDEV10("text", {
4858
+ /* @__PURE__ */ jsxDEV9("text", {
4765
4859
  fg: nameFg,
4766
4860
  width: nameW,
4767
4861
  children: row.model.name
4768
4862
  }, undefined, false, undefined, this),
4769
- /* @__PURE__ */ jsxDEV10("text", {
4863
+ /* @__PURE__ */ jsxDEV9("text", {
4770
4864
  fg: isActive ? theme.primary : theme.dim,
4771
4865
  width: provW,
4772
4866
  children: row.model.providerName
4773
4867
  }, undefined, false, undefined, this),
4774
- /* @__PURE__ */ jsxDEV10("text", {
4868
+ /* @__PURE__ */ jsxDEV9("text", {
4775
4869
  fg: theme.success,
4776
4870
  width: 2,
4777
4871
  children: isSel ? "\u2713" : " "
4778
4872
  }, undefined, false, undefined, this),
4779
- /* @__PURE__ */ jsxDEV10("text", {
4873
+ /* @__PURE__ */ jsxDEV9("text", {
4780
4874
  fg: theme.accent,
4781
4875
  width: 2,
4782
4876
  children: isActive ? "\u203A" : " "
@@ -4787,38 +4881,35 @@ function ModelSelectScreen() {
4787
4881
  })()
4788
4882
  ]
4789
4883
  }, undefined, true, undefined, this),
4790
- /* @__PURE__ */ jsxDEV10("box", {
4884
+ /* @__PURE__ */ jsxDEV9("box", {
4791
4885
  height: 1,
4792
- backgroundColor: theme.border
4886
+ children: /* @__PURE__ */ jsxDEV9("text", {
4887
+ fg: theme.border,
4888
+ children: "\u2500".repeat(150)
4889
+ }, undefined, false, undefined, this)
4793
4890
  }, undefined, false, undefined, this),
4794
- /* @__PURE__ */ jsxDEV10("box", {
4891
+ /* @__PURE__ */ jsxDEV9("box", {
4795
4892
  flexDirection: "row",
4796
4893
  paddingLeft: 2,
4797
4894
  paddingRight: 2,
4798
4895
  paddingTop: 1,
4799
4896
  paddingBottom: 1,
4800
4897
  children: [
4801
- /* @__PURE__ */ jsxDEV10("text", {
4898
+ /* @__PURE__ */ jsxDEV9("text", {
4802
4899
  fg: theme.secondary,
4803
4900
  children: [
4804
4901
  "Selected: ",
4805
- selected.size,
4806
- " model",
4807
- selected.size !== 1 ? "s" : ""
4902
+ selected.size
4808
4903
  ]
4809
4904
  }, undefined, true, undefined, this),
4810
- recentCount > 0 && /* @__PURE__ */ jsxDEV10("text", {
4905
+ recentCount > 0 && /* @__PURE__ */ jsxDEV9("text", {
4811
4906
  fg: theme.dim,
4812
4907
  children: [
4813
4908
  " [R] recent (",
4814
4909
  recentCount,
4815
4910
  ")"
4816
4911
  ]
4817
- }, undefined, true, undefined, this),
4818
- /* @__PURE__ */ jsxDEV10("text", {
4819
- fg: theme.dim,
4820
- children: " [\u2191\u2193/PgUp/PgDn/wheel] scroll"
4821
- }, undefined, false, undefined, this)
4912
+ }, undefined, true, undefined, this)
4822
4913
  ]
4823
4914
  }, undefined, true, undefined, this)
4824
4915
  ]
@@ -4833,24 +4924,10 @@ var init_ModelSelectScreen = __esm(() => {
4833
4924
  init_usePaste();
4834
4925
  });
4835
4926
 
4836
- // src/tui/components/BarChart.tsx
4837
- import { jsxDEV as jsxDEV11 } from "@opentui/react/jsx-dev-runtime";
4838
- function BarChart({ value, max, width, color, inverted = false }) {
4839
- const normalizedValue = inverted && max > 0 ? Math.max(0, max - value) : value;
4840
- const filled = max === 0 ? 0 : Math.round(normalizedValue / max * width);
4841
- const empty = width - filled;
4842
- const bar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
4843
- return /* @__PURE__ */ jsxDEV11("text", {
4844
- fg: color,
4845
- children: bar
4846
- }, undefined, false, undefined, this);
4847
- }
4848
- var init_BarChart = () => {};
4849
-
4850
4927
  // src/tui/components/GlowBar.tsx
4851
4928
  import { useState as useState7, useEffect as useEffect5 } from "react";
4852
4929
  import { engine, Timeline } from "@opentui/core";
4853
- import { jsxDEV as jsxDEV12 } from "@opentui/react/jsx-dev-runtime";
4930
+ import { jsxDEV as jsxDEV10 } from "@opentui/react/jsx-dev-runtime";
4854
4931
  function blendHex(hex, toward, t) {
4855
4932
  const parse3 = (h) => [
4856
4933
  parseInt(h.slice(1, 3), 16),
@@ -4889,16 +4966,16 @@ function GlowBar({ done, total, running }) {
4889
4966
  const fg = intensity >= 0 ? blendHex(theme.accent, "#ffffff", intensity * 0.55) : blendHex(theme.accent, theme.background, Math.abs(intensity) * 0.5);
4890
4967
  return { ch: "\u2588", fg };
4891
4968
  });
4892
- return /* @__PURE__ */ jsxDEV12("box", {
4969
+ return /* @__PURE__ */ jsxDEV10("box", {
4893
4970
  height: 1,
4894
4971
  flexDirection: "row",
4895
4972
  paddingLeft: 2,
4896
4973
  children: [
4897
- /* @__PURE__ */ jsxDEV12("text", {
4974
+ /* @__PURE__ */ jsxDEV10("text", {
4898
4975
  fg: theme.dim,
4899
4976
  children: "Benchmarking "
4900
4977
  }, undefined, false, undefined, this),
4901
- /* @__PURE__ */ jsxDEV12("text", {
4978
+ /* @__PURE__ */ jsxDEV10("text", {
4902
4979
  fg: theme.accent,
4903
4980
  children: [
4904
4981
  done,
@@ -4907,11 +4984,11 @@ function GlowBar({ done, total, running }) {
4907
4984
  " "
4908
4985
  ]
4909
4986
  }, undefined, true, undefined, this),
4910
- barChars.map((b, i) => /* @__PURE__ */ jsxDEV12("text", {
4987
+ barChars.map((b, i) => /* @__PURE__ */ jsxDEV10("text", {
4911
4988
  fg: b.fg,
4912
4989
  children: b.ch
4913
4990
  }, i, false, undefined, this)),
4914
- /* @__PURE__ */ jsxDEV12("text", {
4991
+ /* @__PURE__ */ jsxDEV10("text", {
4915
4992
  fg: theme.warning,
4916
4993
  children: [
4917
4994
  " ",
@@ -4928,7 +5005,7 @@ var init_GlowBar = __esm(() => {
4928
5005
  });
4929
5006
 
4930
5007
  // src/tui/components/ResultsTable.tsx
4931
- import { jsxDEV as jsxDEV13 } from "@opentui/react/jsx-dev-runtime";
5008
+ import { jsxDEV as jsxDEV11 } from "@opentui/react/jsx-dev-runtime";
4932
5009
  function lpad(s, w) {
4933
5010
  return s.length >= w ? s.slice(0, w) : " ".repeat(w - s.length) + s;
4934
5011
  }
@@ -4942,33 +5019,37 @@ function ResultsTable({ results, pendingCount }) {
4942
5019
  const theme = useTheme();
4943
5020
  const sorted = [...results].sort((a, b) => b.tokensPerSecond - a.tokensPerSecond);
4944
5021
  const C = { rank: 4, model: 16, prov: 10, time: 8, ttft: 7, tps: 9, f1000: 8, out: 6, inp: 6, tot: 6 };
4945
- const totalW = C.rank + C.model + C.prov + C.time + C.ttft + C.tps + C.f1000 + C.out + C.inp + C.tot + 10;
4946
- const sep = "\u2500".repeat(totalW);
4947
5022
  const maxTps = Math.max(...results.map((r) => r.tokensPerSecond), 0);
4948
5023
  const minTtft = Math.min(...results.map((r) => r.timeToFirstToken), Infinity);
4949
5024
  const validF1000s = results.map((r) => r.f1000).filter((f) => f !== Infinity);
4950
5025
  const minF1000 = validF1000s.length > 0 ? Math.min(...validF1000s) : Infinity;
4951
- function row(rank, model, prov, time, ttft, tps, f1000, out, inp, tot) {
4952
- return lpad(rank, C.rank) + " \u2502 " + rpad(model, C.model) + " \u2502 " + rpad(prov, C.prov) + " \u2502 " + lpad(time, C.time) + " \u2502 " + lpad(ttft, C.ttft) + " \u2502 " + lpad(tps, C.tps) + " \u2502 " + lpad(f1000, C.f1000) + " \u2502 " + lpad(out, C.out) + " \u2502 " + lpad(inp, C.inp) + " \u2502 " + lpad(tot, C.tot);
5026
+ function headerRow() {
5027
+ return "\u2502 " + lpad("#", C.rank) + " \u2502 " + rpad("Model", C.model) + " \u2502 " + rpad("Provider", C.prov) + " \u2502 " + lpad("Time(s)", C.time) + " \u2502 " + lpad("TTFT(s)", C.ttft) + " \u2502 " + lpad("Tok/s", C.tps) + " \u2502 " + lpad("F1000(h)", C.f1000) + " \u2502 " + lpad("Out", C.out) + " \u2502 " + lpad("In", C.inp) + " \u2502 " + lpad("Total", C.tot) + " \u2502";
4953
5028
  }
4954
- const header = row("#", "Model", "Provider", "Time(s)", "TTFT(s)", "Tok/s", "F1000(h)", "Out", "In", "Total");
4955
- return /* @__PURE__ */ jsxDEV13("box", {
5029
+ return /* @__PURE__ */ jsxDEV11("box", {
4956
5030
  flexDirection: "column",
4957
- paddingLeft: 1,
4958
- paddingRight: 1,
5031
+ paddingLeft: 2,
5032
+ paddingRight: 2,
4959
5033
  children: [
4960
- /* @__PURE__ */ jsxDEV13("box", {
5034
+ /* @__PURE__ */ jsxDEV11("box", {
5035
+ height: 1,
5036
+ children: /* @__PURE__ */ jsxDEV11("text", {
5037
+ fg: theme.border,
5038
+ children: RULE
5039
+ }, undefined, false, undefined, this)
5040
+ }, undefined, false, undefined, this),
5041
+ /* @__PURE__ */ jsxDEV11("box", {
4961
5042
  height: 1,
4962
- children: /* @__PURE__ */ jsxDEV13("text", {
5043
+ children: /* @__PURE__ */ jsxDEV11("text", {
4963
5044
  fg: theme.accent,
4964
- children: header
5045
+ children: headerRow()
4965
5046
  }, undefined, false, undefined, this)
4966
5047
  }, undefined, false, undefined, this),
4967
- /* @__PURE__ */ jsxDEV13("box", {
5048
+ /* @__PURE__ */ jsxDEV11("box", {
4968
5049
  height: 1,
4969
- children: /* @__PURE__ */ jsxDEV13("text", {
5050
+ children: /* @__PURE__ */ jsxDEV11("text", {
4970
5051
  fg: theme.border,
4971
- children: sep
5052
+ children: RULE
4972
5053
  }, undefined, false, undefined, this)
4973
5054
  }, undefined, false, undefined, this),
4974
5055
  sorted.map((r, i) => {
@@ -4984,97 +5065,105 @@ function ResultsTable({ results, pendingCount }) {
4984
5065
  const isBestTps = r.tokensPerSecond === maxTps && maxTps > 0;
4985
5066
  const isBestTtft = r.timeToFirstToken === minTtft;
4986
5067
  const isBestF1000 = r.f1000 === minF1000 && r.f1000 !== Infinity;
4987
- return /* @__PURE__ */ jsxDEV13("box", {
5068
+ return /* @__PURE__ */ jsxDEV11("box", {
4988
5069
  height: 1,
4989
5070
  flexDirection: "row",
4990
5071
  children: [
4991
- /* @__PURE__ */ jsxDEV13("text", {
5072
+ /* @__PURE__ */ jsxDEV11("text", {
5073
+ fg: theme.dim,
5074
+ children: "\u2502 "
5075
+ }, undefined, false, undefined, this),
5076
+ /* @__PURE__ */ jsxDEV11("text", {
4992
5077
  fg: theme.dim,
4993
5078
  children: [
4994
5079
  lpad(rank, C.rank),
4995
5080
  " \u2502 "
4996
5081
  ]
4997
5082
  }, undefined, true, undefined, this),
4998
- /* @__PURE__ */ jsxDEV13("text", {
5083
+ /* @__PURE__ */ jsxDEV11("text", {
4999
5084
  fg: theme.text,
5000
5085
  children: [
5001
5086
  rpad(trunc(r.model, C.model), C.model),
5002
5087
  " \u2502 "
5003
5088
  ]
5004
5089
  }, undefined, true, undefined, this),
5005
- /* @__PURE__ */ jsxDEV13("text", {
5090
+ /* @__PURE__ */ jsxDEV11("text", {
5006
5091
  fg: theme.dim,
5007
5092
  children: [
5008
5093
  rpad(trunc(r.provider, C.prov), C.prov),
5009
5094
  " \u2502 "
5010
5095
  ]
5011
5096
  }, undefined, true, undefined, this),
5012
- /* @__PURE__ */ jsxDEV13("text", {
5097
+ /* @__PURE__ */ jsxDEV11("text", {
5013
5098
  fg: theme.dim,
5014
5099
  children: [
5015
5100
  lpad(timeSec, C.time),
5016
5101
  " \u2502 "
5017
5102
  ]
5018
5103
  }, undefined, true, undefined, this),
5019
- /* @__PURE__ */ jsxDEV13("text", {
5104
+ /* @__PURE__ */ jsxDEV11("text", {
5020
5105
  fg: isBestTtft ? theme.success : theme.dim,
5021
5106
  children: [
5022
5107
  lpad(ttftSec, C.ttft),
5023
5108
  " \u2502 "
5024
5109
  ]
5025
5110
  }, undefined, true, undefined, this),
5026
- /* @__PURE__ */ jsxDEV13("text", {
5111
+ /* @__PURE__ */ jsxDEV11("text", {
5027
5112
  fg: isBestTps ? theme.success : theme.dim,
5028
5113
  children: [
5029
5114
  lpad(tps, C.tps),
5030
5115
  " \u2502 "
5031
5116
  ]
5032
5117
  }, undefined, true, undefined, this),
5033
- /* @__PURE__ */ jsxDEV13("text", {
5118
+ /* @__PURE__ */ jsxDEV11("text", {
5034
5119
  fg: isBestF1000 ? theme.success : theme.dim,
5035
5120
  children: [
5036
5121
  lpad(f1000Val, C.f1000),
5037
5122
  " \u2502 "
5038
5123
  ]
5039
5124
  }, undefined, true, undefined, this),
5040
- /* @__PURE__ */ jsxDEV13("text", {
5125
+ /* @__PURE__ */ jsxDEV11("text", {
5041
5126
  fg: theme.dim,
5042
5127
  children: [
5043
5128
  lpad(outTok, C.out),
5044
5129
  " \u2502 "
5045
5130
  ]
5046
5131
  }, undefined, true, undefined, this),
5047
- /* @__PURE__ */ jsxDEV13("text", {
5132
+ /* @__PURE__ */ jsxDEV11("text", {
5048
5133
  fg: theme.dim,
5049
5134
  children: [
5050
5135
  lpad(inTok, C.inp),
5051
5136
  " \u2502 "
5052
5137
  ]
5053
5138
  }, undefined, true, undefined, this),
5054
- /* @__PURE__ */ jsxDEV13("text", {
5139
+ /* @__PURE__ */ jsxDEV11("text", {
5055
5140
  fg: theme.dim,
5056
5141
  children: lpad(totTok, C.tot)
5057
5142
  }, undefined, false, undefined, this),
5058
- hasEst && /* @__PURE__ */ jsxDEV13("text", {
5143
+ /* @__PURE__ */ jsxDEV11("text", {
5144
+ fg: theme.dim,
5145
+ children: " \u2502"
5146
+ }, undefined, false, undefined, this),
5147
+ hasEst && /* @__PURE__ */ jsxDEV11("text", {
5059
5148
  fg: theme.warning,
5060
5149
  children: " [est]"
5061
5150
  }, undefined, false, undefined, this)
5062
5151
  ]
5063
5152
  }, `${r.model}-${r.provider}-${i}`, true, undefined, this);
5064
5153
  }),
5065
- /* @__PURE__ */ jsxDEV13("box", {
5154
+ /* @__PURE__ */ jsxDEV11("box", {
5066
5155
  height: 1,
5067
- children: /* @__PURE__ */ jsxDEV13("text", {
5156
+ children: /* @__PURE__ */ jsxDEV11("text", {
5068
5157
  fg: theme.border,
5069
- children: sep
5158
+ children: RULE
5070
5159
  }, undefined, false, undefined, this)
5071
5160
  }, undefined, false, undefined, this),
5072
- pendingCount > 0 && /* @__PURE__ */ jsxDEV13("box", {
5161
+ pendingCount > 0 && /* @__PURE__ */ jsxDEV11("box", {
5073
5162
  height: 1,
5074
- children: /* @__PURE__ */ jsxDEV13("text", {
5163
+ children: /* @__PURE__ */ jsxDEV11("text", {
5075
5164
  fg: theme.dim,
5076
5165
  children: [
5077
- " Waiting for ",
5166
+ "Waiting for ",
5078
5167
  pendingCount,
5079
5168
  " more result",
5080
5169
  pendingCount !== 1 ? "s" : "",
@@ -5085,14 +5174,35 @@ function ResultsTable({ results, pendingCount }) {
5085
5174
  ]
5086
5175
  }, undefined, true, undefined, this);
5087
5176
  }
5177
+ var RULE;
5088
5178
  var init_ResultsTable = __esm(() => {
5089
5179
  init_ThemeContext();
5180
+ RULE = "\u2500".repeat(200);
5090
5181
  });
5091
5182
 
5092
- // src/tui/screens/BenchmarkScreen.tsx
5093
- import { useState as useState8, useEffect as useEffect6, useRef as useRef4, useMemo } from "react";
5094
- import { jsxDEV as jsxDEV14 } from "@opentui/react/jsx-dev-runtime";
5095
- function rankBadge(rank) {
5183
+ // src/tui/components/BarChart.tsx
5184
+ import { jsxDEV as jsxDEV12 } from "@opentui/react/jsx-dev-runtime";
5185
+ function BarChart({ value, max, width, color, inverted = false }) {
5186
+ const normalizedValue = inverted && max > 0 ? Math.max(0, max - value) : value;
5187
+ const filled = max === 0 ? 0 : Math.round(normalizedValue / max * width);
5188
+ const empty = width - filled;
5189
+ const bar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
5190
+ return /* @__PURE__ */ jsxDEV12("text", {
5191
+ fg: color,
5192
+ children: bar
5193
+ }, undefined, false, undefined, this);
5194
+ }
5195
+ var init_BarChart = () => {};
5196
+
5197
+ // src/tui/components/RankingRow.tsx
5198
+ import { jsxDEV as jsxDEV13 } from "@opentui/react/jsx-dev-runtime";
5199
+ function pad(s, w, align) {
5200
+ if (s.length >= w)
5201
+ return s.slice(0, w);
5202
+ const pad2 = " ".repeat(w - s.length);
5203
+ return align === "right" ? pad2 + s : s + pad2;
5204
+ }
5205
+ function rankLabel(rank) {
5096
5206
  if (rank === 1)
5097
5207
  return "1st";
5098
5208
  if (rank === 2)
@@ -5101,6 +5211,73 @@ function rankBadge(rank) {
5101
5211
  return "3rd";
5102
5212
  return `${rank}th`;
5103
5213
  }
5214
+ function RankingRow({ rank, rankFg, metrics, model, modelFg, provider, providerFg, bar, theme }) {
5215
+ const badge = pad(rankLabel(rank), 3, "left");
5216
+ const modelCol = pad(model, 18, "left");
5217
+ const provCol = pad(provider, 12, "left");
5218
+ return /* @__PURE__ */ jsxDEV13("box", {
5219
+ height: 1,
5220
+ flexDirection: "row",
5221
+ paddingLeft: 2,
5222
+ children: [
5223
+ /* @__PURE__ */ jsxDEV13("text", {
5224
+ fg: rankFg,
5225
+ children: [
5226
+ badge,
5227
+ " "
5228
+ ]
5229
+ }, undefined, true, undefined, this),
5230
+ metrics.map((m, i) => /* @__PURE__ */ jsxDEV13("box", {
5231
+ flexDirection: "row",
5232
+ children: [
5233
+ /* @__PURE__ */ jsxDEV13("text", {
5234
+ fg: theme.dim,
5235
+ children: " \u2502 "
5236
+ }, undefined, false, undefined, this),
5237
+ /* @__PURE__ */ jsxDEV13("text", {
5238
+ fg: m.fg,
5239
+ children: [
5240
+ pad(m.text, m.width, m.align ?? "right"),
5241
+ " "
5242
+ ]
5243
+ }, undefined, true, undefined, this)
5244
+ ]
5245
+ }, `m-${i}`, true, undefined, this)),
5246
+ /* @__PURE__ */ jsxDEV13("text", {
5247
+ fg: theme.dim,
5248
+ children: " \u2502 "
5249
+ }, undefined, false, undefined, this),
5250
+ /* @__PURE__ */ jsxDEV13("text", {
5251
+ fg: modelFg,
5252
+ children: [
5253
+ modelCol,
5254
+ " "
5255
+ ]
5256
+ }, undefined, true, undefined, this),
5257
+ /* @__PURE__ */ jsxDEV13("text", {
5258
+ fg: providerFg,
5259
+ children: provCol
5260
+ }, undefined, false, undefined, this),
5261
+ /* @__PURE__ */ jsxDEV13("text", {
5262
+ fg: theme.dim,
5263
+ children: " \u2502 "
5264
+ }, undefined, false, undefined, this),
5265
+ /* @__PURE__ */ jsxDEV13(BarChart, {
5266
+ value: bar.value,
5267
+ max: bar.max,
5268
+ width: bar.width,
5269
+ color: bar.color
5270
+ }, undefined, false, undefined, this)
5271
+ ]
5272
+ }, undefined, true, undefined, this);
5273
+ }
5274
+ var init_RankingRow = __esm(() => {
5275
+ init_BarChart();
5276
+ });
5277
+
5278
+ // src/tui/screens/BenchmarkScreen.tsx
5279
+ import { useState as useState8, useEffect as useEffect6, useRef as useRef4, useMemo } from "react";
5280
+ import { jsxDEV as jsxDEV14 } from "@opentui/react/jsx-dev-runtime";
5104
5281
  function BenchmarkScreen() {
5105
5282
  const { state, dispatch } = useAppContext();
5106
5283
  const navigate = useNavigate();
@@ -5253,7 +5430,10 @@ function BenchmarkScreen() {
5253
5430
  if (tpsRanked.length > 0) {
5254
5431
  rows.push(/* @__PURE__ */ jsxDEV14("box", {
5255
5432
  height: 1,
5256
- backgroundColor: theme.border
5433
+ children: /* @__PURE__ */ jsxDEV14("text", {
5434
+ fg: theme.border,
5435
+ children: "\u2500".repeat(150)
5436
+ }, undefined, false, undefined, this)
5257
5437
  }, "div-tps", false, undefined, this));
5258
5438
  rows.push(/* @__PURE__ */ jsxDEV14("box", {
5259
5439
  height: 1,
@@ -5269,75 +5449,29 @@ function BenchmarkScreen() {
5269
5449
  const rankFg = rank === 1 ? theme.accent : rank === 2 ? theme.secondary : theme.dim;
5270
5450
  const tps = s.result?.tokensPerSecond ?? 0;
5271
5451
  const timeSec = (s.result?.totalTime ?? 0) / 1000;
5272
- const badge = rankBadge(rank).padStart(3);
5273
- const modelCol = s.model.name.padEnd(18).slice(0, 18);
5274
- const provCol = s.model.providerName.padEnd(12).slice(0, 12);
5275
- rows.push(/* @__PURE__ */ jsxDEV14("box", {
5276
- height: 1,
5277
- flexDirection: "row",
5278
- paddingLeft: 2,
5279
- children: [
5280
- /* @__PURE__ */ jsxDEV14("text", {
5281
- fg: rankFg,
5282
- children: [
5283
- badge,
5284
- " "
5285
- ]
5286
- }, undefined, true, undefined, this),
5287
- /* @__PURE__ */ jsxDEV14("text", {
5288
- fg: theme.dim,
5289
- children: " \u2502 "
5290
- }, undefined, false, undefined, this),
5291
- /* @__PURE__ */ jsxDEV14("text", {
5292
- fg: theme.accent,
5293
- children: [
5294
- tps.toFixed(1).padStart(8),
5295
- " tok/s "
5296
- ]
5297
- }, undefined, true, undefined, this),
5298
- /* @__PURE__ */ jsxDEV14("text", {
5299
- fg: theme.dim,
5300
- children: " \u2502 "
5301
- }, undefined, false, undefined, this),
5302
- /* @__PURE__ */ jsxDEV14("text", {
5303
- fg: theme.secondary,
5304
- children: [
5305
- timeSec.toFixed(2).padStart(6),
5306
- "s "
5307
- ]
5308
- }, undefined, true, undefined, this),
5309
- /* @__PURE__ */ jsxDEV14("text", {
5310
- fg: theme.dim,
5311
- children: " \u2502 "
5312
- }, undefined, false, undefined, this),
5313
- /* @__PURE__ */ jsxDEV14("text", {
5314
- fg: theme.text,
5315
- children: [
5316
- modelCol,
5317
- " "
5318
- ]
5319
- }, undefined, true, undefined, this),
5320
- /* @__PURE__ */ jsxDEV14("text", {
5321
- fg: theme.dim,
5322
- children: [
5323
- provCol,
5324
- " \u2502 "
5325
- ]
5326
- }, undefined, true, undefined, this),
5327
- /* @__PURE__ */ jsxDEV14(BarChart, {
5328
- value: tps,
5329
- max: maxTps,
5330
- width: BAR_W2,
5331
- color: theme.accent
5332
- }, undefined, false, undefined, this)
5333
- ]
5334
- }, `tps-${s.model.id}-${s.model.providerId}`, true, undefined, this));
5452
+ rows.push(/* @__PURE__ */ jsxDEV14(RankingRow, {
5453
+ rank,
5454
+ rankFg,
5455
+ metrics: [
5456
+ { text: `${tps.toFixed(1)} tok/s`, fg: theme.accent, width: 12 },
5457
+ { text: `${timeSec.toFixed(2)}s`, fg: theme.secondary, width: 7 }
5458
+ ],
5459
+ model: s.model.name,
5460
+ modelFg: theme.text,
5461
+ provider: s.model.providerName,
5462
+ providerFg: theme.dim,
5463
+ bar: { value: tps, max: maxTps, width: BAR_W2, color: theme.accent },
5464
+ theme
5465
+ }, `tps-${s.model.id}-${s.model.providerId}`, false, undefined, this));
5335
5466
  }
5336
5467
  }
5337
5468
  if (ttftRanked.length > 0) {
5338
5469
  rows.push(/* @__PURE__ */ jsxDEV14("box", {
5339
5470
  height: 1,
5340
- backgroundColor: theme.border
5471
+ children: /* @__PURE__ */ jsxDEV14("text", {
5472
+ fg: theme.border,
5473
+ children: "\u2500".repeat(150)
5474
+ }, undefined, false, undefined, this)
5341
5475
  }, "div-ttft", false, undefined, this));
5342
5476
  rows.push(/* @__PURE__ */ jsxDEV14("box", {
5343
5477
  height: 1,
@@ -5353,75 +5487,29 @@ function BenchmarkScreen() {
5353
5487
  const rankFg = rank === 1 ? theme.accent : rank === 2 ? theme.secondary : theme.dim;
5354
5488
  const ttft = (s.result?.timeToFirstToken ?? 0) / 1000;
5355
5489
  const tps = s.result?.tokensPerSecond ?? 0;
5356
- const badge = rankBadge(rank).padStart(3);
5357
- const modelCol = s.model.name.padEnd(18).slice(0, 18);
5358
- const provCol = s.model.providerName.padEnd(12).slice(0, 12);
5359
- rows.push(/* @__PURE__ */ jsxDEV14("box", {
5360
- height: 1,
5361
- flexDirection: "row",
5362
- paddingLeft: 2,
5363
- children: [
5364
- /* @__PURE__ */ jsxDEV14("text", {
5365
- fg: rankFg,
5366
- children: [
5367
- badge,
5368
- " "
5369
- ]
5370
- }, undefined, true, undefined, this),
5371
- /* @__PURE__ */ jsxDEV14("text", {
5372
- fg: theme.dim,
5373
- children: " \u2502 "
5374
- }, undefined, false, undefined, this),
5375
- /* @__PURE__ */ jsxDEV14("text", {
5376
- fg: theme.secondary,
5377
- children: [
5378
- ttft.toFixed(2).padStart(7),
5379
- "s "
5380
- ]
5381
- }, undefined, true, undefined, this),
5382
- /* @__PURE__ */ jsxDEV14("text", {
5383
- fg: theme.dim,
5384
- children: " \u2502 "
5385
- }, undefined, false, undefined, this),
5386
- /* @__PURE__ */ jsxDEV14("text", {
5387
- fg: theme.accent,
5388
- children: [
5389
- tps.toFixed(1).padStart(8),
5390
- " tok/s "
5391
- ]
5392
- }, undefined, true, undefined, this),
5393
- /* @__PURE__ */ jsxDEV14("text", {
5394
- fg: theme.dim,
5395
- children: " \u2502 "
5396
- }, undefined, false, undefined, this),
5397
- /* @__PURE__ */ jsxDEV14("text", {
5398
- fg: theme.text,
5399
- children: [
5400
- modelCol,
5401
- " "
5402
- ]
5403
- }, undefined, true, undefined, this),
5404
- /* @__PURE__ */ jsxDEV14("text", {
5405
- fg: theme.dim,
5406
- children: [
5407
- provCol,
5408
- " \u2502 "
5409
- ]
5410
- }, undefined, true, undefined, this),
5411
- /* @__PURE__ */ jsxDEV14(BarChart, {
5412
- value: ttft,
5413
- max: maxTtftForBar,
5414
- width: BAR_W2,
5415
- color: theme.secondary
5416
- }, undefined, false, undefined, this)
5417
- ]
5418
- }, `ttft-${s.model.id}-${s.model.providerId}`, true, undefined, this));
5490
+ rows.push(/* @__PURE__ */ jsxDEV14(RankingRow, {
5491
+ rank,
5492
+ rankFg,
5493
+ metrics: [
5494
+ { text: `${ttft.toFixed(2)}s`, fg: theme.secondary, width: 7 },
5495
+ { text: `${tps.toFixed(1)} tok/s`, fg: theme.accent, width: 12 }
5496
+ ],
5497
+ model: s.model.name,
5498
+ modelFg: theme.text,
5499
+ provider: s.model.providerName,
5500
+ providerFg: theme.dim,
5501
+ bar: { value: ttft, max: maxTtftForBar, width: BAR_W2, color: theme.secondary },
5502
+ theme
5503
+ }, `ttft-${s.model.id}-${s.model.providerId}`, false, undefined, this));
5419
5504
  }
5420
5505
  }
5421
5506
  if (f1000Ranked.length > 0) {
5422
5507
  rows.push(/* @__PURE__ */ jsxDEV14("box", {
5423
5508
  height: 1,
5424
- backgroundColor: theme.border
5509
+ children: /* @__PURE__ */ jsxDEV14("text", {
5510
+ fg: theme.border,
5511
+ children: "\u2500".repeat(150)
5512
+ }, undefined, false, undefined, this)
5425
5513
  }, "div-f1000", false, undefined, this));
5426
5514
  rows.push(/* @__PURE__ */ jsxDEV14("box", {
5427
5515
  height: 1,
@@ -5436,89 +5524,31 @@ function BenchmarkScreen() {
5436
5524
  const rank = i + 1;
5437
5525
  const rankFg = rank === 1 ? theme.accent : rank === 2 ? theme.secondary : theme.dim;
5438
5526
  const f1000 = s.result?.f1000 ?? Infinity;
5439
- const f1000Str = f1000 === Infinity ? "\u221E" : f1000.toFixed(2);
5440
- const ttft = (s.result?.timeToFirstToken ?? 0) / 1000;
5527
+ const f1000Str = f1000 === Infinity ? "\u221E" : `${f1000.toFixed(2)}h`;
5441
5528
  const tps = s.result?.tokensPerSecond ?? 0;
5442
- const badge = rankBadge(rank).padStart(3);
5443
- const modelCol = s.model.name.padEnd(18).slice(0, 18);
5444
- const provCol = s.model.providerName.padEnd(12).slice(0, 12);
5445
- rows.push(/* @__PURE__ */ jsxDEV14("box", {
5446
- height: 1,
5447
- flexDirection: "row",
5448
- paddingLeft: 2,
5449
- children: [
5450
- /* @__PURE__ */ jsxDEV14("text", {
5451
- fg: rankFg,
5452
- children: [
5453
- badge,
5454
- " "
5455
- ]
5456
- }, undefined, true, undefined, this),
5457
- /* @__PURE__ */ jsxDEV14("text", {
5458
- fg: theme.dim,
5459
- children: " \u2502 "
5460
- }, undefined, false, undefined, this),
5461
- /* @__PURE__ */ jsxDEV14("text", {
5462
- fg: theme.primary,
5463
- children: [
5464
- f1000Str.padStart(7),
5465
- "h "
5466
- ]
5467
- }, undefined, true, undefined, this),
5468
- /* @__PURE__ */ jsxDEV14("text", {
5469
- fg: theme.dim,
5470
- children: " \u2502 "
5471
- }, undefined, false, undefined, this),
5472
- /* @__PURE__ */ jsxDEV14("text", {
5473
- fg: theme.secondary,
5474
- children: [
5475
- ttft.toFixed(2).padStart(5),
5476
- "s "
5477
- ]
5478
- }, undefined, true, undefined, this),
5479
- /* @__PURE__ */ jsxDEV14("text", {
5480
- fg: theme.dim,
5481
- children: " \u2502 "
5482
- }, undefined, false, undefined, this),
5483
- /* @__PURE__ */ jsxDEV14("text", {
5484
- fg: theme.accent,
5485
- children: [
5486
- tps.toFixed(0).padStart(5),
5487
- " tok/s "
5488
- ]
5489
- }, undefined, true, undefined, this),
5490
- /* @__PURE__ */ jsxDEV14("text", {
5491
- fg: theme.dim,
5492
- children: " \u2502 "
5493
- }, undefined, false, undefined, this),
5494
- /* @__PURE__ */ jsxDEV14("text", {
5495
- fg: theme.text,
5496
- children: [
5497
- modelCol,
5498
- " "
5499
- ]
5500
- }, undefined, true, undefined, this),
5501
- /* @__PURE__ */ jsxDEV14("text", {
5502
- fg: theme.dim,
5503
- children: [
5504
- provCol,
5505
- " \u2502 "
5506
- ]
5507
- }, undefined, true, undefined, this),
5508
- /* @__PURE__ */ jsxDEV14(BarChart, {
5509
- value: f1000 === Infinity ? maxF1000 : f1000,
5510
- max: maxF1000,
5511
- width: BAR_W2,
5512
- color: theme.primary
5513
- }, undefined, false, undefined, this)
5514
- ]
5515
- }, `f1000-${s.model.id}-${s.model.providerId}`, true, undefined, this));
5529
+ rows.push(/* @__PURE__ */ jsxDEV14(RankingRow, {
5530
+ rank,
5531
+ rankFg,
5532
+ metrics: [
5533
+ { text: f1000Str, fg: theme.primary, width: 7 },
5534
+ { text: `${tps.toFixed(0)} tok/s`, fg: theme.accent, width: 12 }
5535
+ ],
5536
+ model: s.model.name,
5537
+ modelFg: theme.text,
5538
+ provider: s.model.providerName,
5539
+ providerFg: theme.dim,
5540
+ bar: { value: f1000 === Infinity ? maxF1000 : f1000, max: maxF1000, width: BAR_W2, color: theme.primary },
5541
+ theme
5542
+ }, `f1000-${s.model.id}-${s.model.providerId}`, false, undefined, this));
5516
5543
  }
5517
5544
  }
5518
5545
  if (allDone && errors.length > 0) {
5519
5546
  rows.push(/* @__PURE__ */ jsxDEV14("box", {
5520
5547
  height: 1,
5521
- backgroundColor: theme.border
5548
+ children: /* @__PURE__ */ jsxDEV14("text", {
5549
+ fg: theme.border,
5550
+ children: "\u2500".repeat(150)
5551
+ }, undefined, false, undefined, this)
5522
5552
  }, "div-errors", false, undefined, this));
5523
5553
  rows.push(/* @__PURE__ */ jsxDEV14("box", {
5524
5554
  height: 1,
@@ -5579,7 +5609,10 @@ function BenchmarkScreen() {
5579
5609
  }
5580
5610
  rows.push(/* @__PURE__ */ jsxDEV14("box", {
5581
5611
  height: 1,
5582
- backgroundColor: theme.border
5612
+ children: /* @__PURE__ */ jsxDEV14("text", {
5613
+ fg: theme.border,
5614
+ children: "\u2500".repeat(150)
5615
+ }, undefined, false, undefined, this)
5583
5616
  }, "div-results", false, undefined, this));
5584
5617
  rows.push(/* @__PURE__ */ jsxDEV14("box", {
5585
5618
  height: 1,
@@ -5685,7 +5718,7 @@ function BenchmarkScreen() {
5685
5718
  /* @__PURE__ */ jsxDEV14("box", {
5686
5719
  flexDirection: "column",
5687
5720
  border: true,
5688
- borderStyle: "rounded",
5721
+ borderStyle: "single",
5689
5722
  borderColor: theme.border,
5690
5723
  backgroundColor: theme.background,
5691
5724
  flexGrow: 1,
@@ -5705,7 +5738,10 @@ function BenchmarkScreen() {
5705
5738
  }, undefined, true, undefined, this),
5706
5739
  /* @__PURE__ */ jsxDEV14("box", {
5707
5740
  height: 1,
5708
- backgroundColor: theme.border
5741
+ children: /* @__PURE__ */ jsxDEV14("text", {
5742
+ fg: theme.border,
5743
+ children: "\u2500".repeat(150)
5744
+ }, undefined, false, undefined, this)
5709
5745
  }, undefined, false, undefined, this),
5710
5746
  /* @__PURE__ */ jsxDEV14("scrollbox", {
5711
5747
  focused: true,
@@ -5725,9 +5761,9 @@ var init_BenchmarkScreen = __esm(() => {
5725
5761
  init_useAppKeyboard();
5726
5762
  init_AppContext();
5727
5763
  init_ThemeContext();
5728
- init_BarChart();
5729
5764
  init_GlowBar();
5730
5765
  init_ResultsTable();
5766
+ init_RankingRow();
5731
5767
  });
5732
5768
 
5733
5769
  // src/tui/screens/AddVerifiedScreen.tsx
@@ -5890,7 +5926,7 @@ function AddVerifiedScreen() {
5890
5926
  children: /* @__PURE__ */ jsxDEV15("box", {
5891
5927
  flexDirection: "column",
5892
5928
  border: true,
5893
- borderStyle: "rounded",
5929
+ borderStyle: "single",
5894
5930
  borderColor: theme.border,
5895
5931
  backgroundColor: theme.background,
5896
5932
  width: CARD_W,
@@ -5906,7 +5942,10 @@ function AddVerifiedScreen() {
5906
5942
  }, undefined, false, undefined, this),
5907
5943
  /* @__PURE__ */ jsxDEV15("box", {
5908
5944
  height: 1,
5909
- backgroundColor: theme.border
5945
+ children: /* @__PURE__ */ jsxDEV15("text", {
5946
+ fg: theme.border,
5947
+ children: "\u2500".repeat(150)
5948
+ }, undefined, false, undefined, this)
5910
5949
  }, undefined, false, undefined, this),
5911
5950
  /* @__PURE__ */ jsxDEV15("box", {
5912
5951
  flexDirection: "column",
@@ -5978,7 +6017,10 @@ function AddVerifiedScreen() {
5978
6017
  }, undefined, true, undefined, this),
5979
6018
  /* @__PURE__ */ jsxDEV15("box", {
5980
6019
  height: 1,
5981
- backgroundColor: theme.border
6020
+ children: /* @__PURE__ */ jsxDEV15("text", {
6021
+ fg: theme.border,
6022
+ children: "\u2500".repeat(150)
6023
+ }, undefined, false, undefined, this)
5982
6024
  }, undefined, false, undefined, this),
5983
6025
  saveSuccess ? /* @__PURE__ */ jsxDEV15("box", {
5984
6026
  flexDirection: "column",
@@ -6054,6 +6096,42 @@ function AddVerifiedScreen() {
6054
6096
  }, undefined, false, undefined, this)
6055
6097
  }, undefined, false, undefined, this)
6056
6098
  ]
6099
+ }, undefined, true, undefined, this),
6100
+ /* @__PURE__ */ jsxDEV15("box", {
6101
+ height: 1,
6102
+ children: /* @__PURE__ */ jsxDEV15("text", {
6103
+ fg: theme.border,
6104
+ children: "\u2500".repeat(150)
6105
+ }, undefined, false, undefined, this)
6106
+ }, undefined, false, undefined, this),
6107
+ /* @__PURE__ */ jsxDEV15("box", {
6108
+ height: 1,
6109
+ flexDirection: "row",
6110
+ paddingLeft: 2,
6111
+ paddingRight: 2,
6112
+ paddingTop: 1,
6113
+ paddingBottom: 1,
6114
+ onMouseDown: () => {
6115
+ setStep("list");
6116
+ setSelectedProvider(null);
6117
+ setApiKey("");
6118
+ setSaveSuccess(false);
6119
+ setSaveError("");
6120
+ },
6121
+ children: [
6122
+ /* @__PURE__ */ jsxDEV15("text", {
6123
+ fg: theme.dim,
6124
+ children: "\u2190 "
6125
+ }, undefined, false, undefined, this),
6126
+ /* @__PURE__ */ jsxDEV15("text", {
6127
+ fg: theme.accent,
6128
+ children: "Back to list"
6129
+ }, undefined, false, undefined, this),
6130
+ /* @__PURE__ */ jsxDEV15("text", {
6131
+ fg: theme.dim,
6132
+ children: " [Esc]"
6133
+ }, undefined, false, undefined, this)
6134
+ ]
6057
6135
  }, undefined, true, undefined, this)
6058
6136
  ]
6059
6137
  }, undefined, true, undefined, this)
@@ -6067,7 +6145,7 @@ function AddVerifiedScreen() {
6067
6145
  children: /* @__PURE__ */ jsxDEV15("box", {
6068
6146
  flexDirection: "column",
6069
6147
  border: true,
6070
- borderStyle: "rounded",
6148
+ borderStyle: "single",
6071
6149
  borderColor: theme.border,
6072
6150
  backgroundColor: theme.background,
6073
6151
  width: CARD_W,
@@ -6094,7 +6172,10 @@ function AddVerifiedScreen() {
6094
6172
  }, undefined, true, undefined, this),
6095
6173
  /* @__PURE__ */ jsxDEV15("box", {
6096
6174
  height: 1,
6097
- backgroundColor: theme.border
6175
+ children: /* @__PURE__ */ jsxDEV15("text", {
6176
+ fg: theme.border,
6177
+ children: "\u2500".repeat(150)
6178
+ }, undefined, false, undefined, this)
6098
6179
  }, undefined, false, undefined, this),
6099
6180
  /* @__PURE__ */ jsxDEV15("scrollbox", {
6100
6181
  ref: scrollboxRef,
@@ -6127,6 +6208,12 @@ function AddVerifiedScreen() {
6127
6208
  width: "100%",
6128
6209
  flexDirection: "row",
6129
6210
  backgroundColor: isActive ? theme.border : "transparent",
6211
+ onMouseOver: () => setCursor(i),
6212
+ onMouseDown: () => {
6213
+ setCursor(i);
6214
+ setSelectedProvider(prov);
6215
+ setStep("confirm");
6216
+ },
6130
6217
  children: [
6131
6218
  /* @__PURE__ */ jsxDEV15("text", {
6132
6219
  fg: theme.dim,
@@ -6155,7 +6242,10 @@ function AddVerifiedScreen() {
6155
6242
  }, undefined, true, undefined, this),
6156
6243
  /* @__PURE__ */ jsxDEV15("box", {
6157
6244
  height: 1,
6158
- backgroundColor: theme.border
6245
+ children: /* @__PURE__ */ jsxDEV15("text", {
6246
+ fg: theme.border,
6247
+ children: "\u2500".repeat(150)
6248
+ }, undefined, false, undefined, this)
6159
6249
  }, undefined, false, undefined, this),
6160
6250
  /* @__PURE__ */ jsxDEV15("box", {
6161
6251
  flexDirection: "row",
@@ -6176,6 +6266,36 @@ function AddVerifiedScreen() {
6176
6266
  children: " [\u2191\u2193/PgUp/PgDn/wheel] scroll"
6177
6267
  }, undefined, false, undefined, this)
6178
6268
  ]
6269
+ }, undefined, true, undefined, this),
6270
+ /* @__PURE__ */ jsxDEV15("box", {
6271
+ height: 1,
6272
+ children: /* @__PURE__ */ jsxDEV15("text", {
6273
+ fg: theme.border,
6274
+ children: "\u2500".repeat(150)
6275
+ }, undefined, false, undefined, this)
6276
+ }, undefined, false, undefined, this),
6277
+ /* @__PURE__ */ jsxDEV15("box", {
6278
+ height: 1,
6279
+ flexDirection: "row",
6280
+ paddingLeft: 2,
6281
+ paddingRight: 2,
6282
+ paddingTop: 1,
6283
+ paddingBottom: 1,
6284
+ onMouseDown: () => navigate("model-menu"),
6285
+ children: [
6286
+ /* @__PURE__ */ jsxDEV15("text", {
6287
+ fg: theme.dim,
6288
+ children: "\u2190 "
6289
+ }, undefined, false, undefined, this),
6290
+ /* @__PURE__ */ jsxDEV15("text", {
6291
+ fg: theme.accent,
6292
+ children: "Back"
6293
+ }, undefined, false, undefined, this),
6294
+ /* @__PURE__ */ jsxDEV15("text", {
6295
+ fg: theme.dim,
6296
+ children: " [Q] or [Esc]"
6297
+ }, undefined, false, undefined, this)
6298
+ ]
6179
6299
  }, undefined, true, undefined, this)
6180
6300
  ]
6181
6301
  }, undefined, true, undefined, this)
@@ -6419,7 +6539,7 @@ function AddCustomScreen() {
6419
6539
  children: /* @__PURE__ */ jsxDEV16("box", {
6420
6540
  flexDirection: "column",
6421
6541
  border: true,
6422
- borderStyle: "rounded",
6542
+ borderStyle: "single",
6423
6543
  borderColor: theme.border,
6424
6544
  backgroundColor: theme.background,
6425
6545
  width: CARD_W,
@@ -6464,7 +6584,7 @@ function AddCustomScreen() {
6464
6584
  children: /* @__PURE__ */ jsxDEV16("box", {
6465
6585
  flexDirection: "column",
6466
6586
  border: true,
6467
- borderStyle: "rounded",
6587
+ borderStyle: "single",
6468
6588
  borderColor: theme.border,
6469
6589
  backgroundColor: theme.background,
6470
6590
  width: CARD_W,
@@ -6488,7 +6608,7 @@ function AddCustomScreen() {
6488
6608
  children: /* @__PURE__ */ jsxDEV16("box", {
6489
6609
  flexDirection: "column",
6490
6610
  border: true,
6491
- borderStyle: "rounded",
6611
+ borderStyle: "single",
6492
6612
  borderColor: theme.border,
6493
6613
  backgroundColor: theme.background,
6494
6614
  width: CARD_W,
@@ -6504,7 +6624,10 @@ function AddCustomScreen() {
6504
6624
  }, undefined, false, undefined, this),
6505
6625
  /* @__PURE__ */ jsxDEV16("box", {
6506
6626
  height: 1,
6507
- backgroundColor: theme.border
6627
+ children: /* @__PURE__ */ jsxDEV16("text", {
6628
+ fg: theme.border,
6629
+ children: "\u2500".repeat(150)
6630
+ }, undefined, false, undefined, this)
6508
6631
  }, undefined, false, undefined, this),
6509
6632
  /* @__PURE__ */ jsxDEV16("box", {
6510
6633
  paddingTop: 1,
@@ -6513,7 +6636,10 @@ function AddCustomScreen() {
6513
6636
  }, undefined, false, undefined, this),
6514
6637
  /* @__PURE__ */ jsxDEV16("box", {
6515
6638
  height: 1,
6516
- backgroundColor: theme.border
6639
+ children: /* @__PURE__ */ jsxDEV16("text", {
6640
+ fg: theme.border,
6641
+ children: "\u2500".repeat(150)
6642
+ }, undefined, false, undefined, this)
6517
6643
  }, undefined, false, undefined, this),
6518
6644
  /* @__PURE__ */ jsxDEV16("box", {
6519
6645
  flexDirection: "column",
@@ -6529,6 +6655,16 @@ function AddCustomScreen() {
6529
6655
  width: "100%",
6530
6656
  flexDirection: "row",
6531
6657
  backgroundColor: i === typeCursor ? theme.border : "transparent",
6658
+ onMouseOver: () => setTypeCursor(i),
6659
+ onMouseDown: () => {
6660
+ setTypeCursor(i);
6661
+ if (i === 2) {
6662
+ navigate("model-menu");
6663
+ } else {
6664
+ setProviderType(i === 1 ? "anthropic" : "openai-compatible");
6665
+ setStep("id");
6666
+ }
6667
+ },
6532
6668
  children: [
6533
6669
  /* @__PURE__ */ jsxDEV16("text", {
6534
6670
  fg: i === typeCursor ? theme.text : theme.dim,
@@ -6730,6 +6866,46 @@ function AddCustomScreen() {
6730
6866
  }, undefined, false, undefined, this)
6731
6867
  }, undefined, false, undefined, this) : null
6732
6868
  ]
6869
+ }, undefined, true, undefined, this),
6870
+ /* @__PURE__ */ jsxDEV16("box", {
6871
+ height: 1,
6872
+ marginTop: 1,
6873
+ children: /* @__PURE__ */ jsxDEV16("text", {
6874
+ fg: theme.border,
6875
+ children: "\u2500".repeat(Math.min(CARD_W, 70))
6876
+ }, undefined, false, undefined, this)
6877
+ }, undefined, false, undefined, this),
6878
+ /* @__PURE__ */ jsxDEV16("box", {
6879
+ height: 1,
6880
+ flexDirection: "row",
6881
+ paddingLeft: 1,
6882
+ paddingRight: 1,
6883
+ onMouseDown: () => {
6884
+ if (step === "type")
6885
+ navigate("model-menu");
6886
+ else {
6887
+ setInputError("");
6888
+ const idx = stepIndex(step);
6889
+ if (idx <= 1)
6890
+ setStep("type");
6891
+ else
6892
+ setStep(STEPS[idx - 1]);
6893
+ }
6894
+ },
6895
+ children: [
6896
+ /* @__PURE__ */ jsxDEV16("text", {
6897
+ fg: theme.dim,
6898
+ children: "\u2190 "
6899
+ }, undefined, false, undefined, this),
6900
+ /* @__PURE__ */ jsxDEV16("text", {
6901
+ fg: theme.accent,
6902
+ children: "Back"
6903
+ }, undefined, false, undefined, this),
6904
+ /* @__PURE__ */ jsxDEV16("text", {
6905
+ fg: theme.dim,
6906
+ children: " [Esc]"
6907
+ }, undefined, false, undefined, this)
6908
+ ]
6733
6909
  }, undefined, true, undefined, this)
6734
6910
  ]
6735
6911
  }, undefined, true, undefined, this)
@@ -6870,42 +7046,74 @@ function AddModelsScreen() {
6870
7046
  children: /* @__PURE__ */ jsxDEV17("box", {
6871
7047
  flexDirection: "column",
6872
7048
  border: true,
6873
- borderStyle: "rounded",
7049
+ borderStyle: "single",
6874
7050
  borderColor: theme.border,
6875
7051
  backgroundColor: theme.background,
6876
7052
  width: CARD_W,
6877
- children: /* @__PURE__ */ jsxDEV17("box", {
6878
- flexDirection: "column",
6879
- paddingLeft: 2,
6880
- paddingRight: 2,
6881
- paddingTop: 1,
6882
- paddingBottom: 1,
6883
- children: [
6884
- /* @__PURE__ */ jsxDEV17("box", {
6885
- height: 1,
6886
- children: /* @__PURE__ */ jsxDEV17("text", {
6887
- fg: theme.success,
6888
- children: [
6889
- "Done! Added ",
6890
- addedModels.length,
6891
- " model",
6892
- addedModels.length !== 1 ? "s" : "",
6893
- " to ",
6894
- selectedProvider?.name,
6895
- "."
6896
- ]
6897
- }, undefined, true, undefined, this)
6898
- }, undefined, false, undefined, this),
6899
- /* @__PURE__ */ jsxDEV17("box", {
6900
- height: 1,
6901
- children: /* @__PURE__ */ jsxDEV17("text", {
6902
- fg: theme.dim,
6903
- children: "Press [Enter] to return"
7053
+ children: [
7054
+ /* @__PURE__ */ jsxDEV17("box", {
7055
+ flexDirection: "column",
7056
+ paddingLeft: 2,
7057
+ paddingRight: 2,
7058
+ paddingTop: 1,
7059
+ paddingBottom: 1,
7060
+ children: [
7061
+ /* @__PURE__ */ jsxDEV17("box", {
7062
+ height: 1,
7063
+ children: /* @__PURE__ */ jsxDEV17("text", {
7064
+ fg: theme.success,
7065
+ children: [
7066
+ "Done! Added ",
7067
+ addedModels.length,
7068
+ " model",
7069
+ addedModels.length !== 1 ? "s" : "",
7070
+ " to ",
7071
+ selectedProvider?.name,
7072
+ "."
7073
+ ]
7074
+ }, undefined, true, undefined, this)
7075
+ }, undefined, false, undefined, this),
7076
+ /* @__PURE__ */ jsxDEV17("box", {
7077
+ height: 1,
7078
+ children: /* @__PURE__ */ jsxDEV17("text", {
7079
+ fg: theme.dim,
7080
+ children: "Press [Enter] to return"
7081
+ }, undefined, false, undefined, this)
6904
7082
  }, undefined, false, undefined, this)
7083
+ ]
7084
+ }, undefined, true, undefined, this),
7085
+ /* @__PURE__ */ jsxDEV17("box", {
7086
+ height: 1,
7087
+ children: /* @__PURE__ */ jsxDEV17("text", {
7088
+ fg: theme.border,
7089
+ children: "\u2500".repeat(150)
6905
7090
  }, undefined, false, undefined, this)
6906
- ]
6907
- }, undefined, true, undefined, this)
6908
- }, undefined, false, undefined, this)
7091
+ }, undefined, false, undefined, this),
7092
+ /* @__PURE__ */ jsxDEV17("box", {
7093
+ height: 1,
7094
+ flexDirection: "row",
7095
+ paddingLeft: 2,
7096
+ paddingRight: 2,
7097
+ paddingTop: 1,
7098
+ paddingBottom: 1,
7099
+ onMouseDown: () => navigate("model-menu"),
7100
+ children: [
7101
+ /* @__PURE__ */ jsxDEV17("text", {
7102
+ fg: theme.dim,
7103
+ children: "\u2190 "
7104
+ }, undefined, false, undefined, this),
7105
+ /* @__PURE__ */ jsxDEV17("text", {
7106
+ fg: theme.accent,
7107
+ children: "Back to menu"
7108
+ }, undefined, false, undefined, this),
7109
+ /* @__PURE__ */ jsxDEV17("text", {
7110
+ fg: theme.dim,
7111
+ children: " [Enter]"
7112
+ }, undefined, false, undefined, this)
7113
+ ]
7114
+ }, undefined, true, undefined, this)
7115
+ ]
7116
+ }, undefined, true, undefined, this)
6909
7117
  }, undefined, false, undefined, this);
6910
7118
  }
6911
7119
  if (step === "add" && selectedProvider) {
@@ -6917,7 +7125,7 @@ function AddModelsScreen() {
6917
7125
  children: /* @__PURE__ */ jsxDEV17("box", {
6918
7126
  flexDirection: "column",
6919
7127
  border: true,
6920
- borderStyle: "rounded",
7128
+ borderStyle: "single",
6921
7129
  borderColor: theme.border,
6922
7130
  backgroundColor: theme.background,
6923
7131
  width: CARD_W,
@@ -6940,7 +7148,10 @@ function AddModelsScreen() {
6940
7148
  }, undefined, true, undefined, this),
6941
7149
  /* @__PURE__ */ jsxDEV17("box", {
6942
7150
  height: 1,
6943
- backgroundColor: theme.border
7151
+ children: /* @__PURE__ */ jsxDEV17("text", {
7152
+ fg: theme.border,
7153
+ children: "\u2500".repeat(150)
7154
+ }, undefined, false, undefined, this)
6944
7155
  }, undefined, false, undefined, this),
6945
7156
  /* @__PURE__ */ jsxDEV17("box", {
6946
7157
  flexDirection: "column",
@@ -7030,6 +7241,43 @@ function AddModelsScreen() {
7030
7241
  }, undefined, false, undefined, this)
7031
7242
  }, undefined, false, undefined, this)
7032
7243
  ]
7244
+ }, undefined, true, undefined, this),
7245
+ /* @__PURE__ */ jsxDEV17("box", {
7246
+ height: 1,
7247
+ children: /* @__PURE__ */ jsxDEV17("text", {
7248
+ fg: theme.border,
7249
+ children: "\u2500".repeat(150)
7250
+ }, undefined, false, undefined, this)
7251
+ }, undefined, false, undefined, this),
7252
+ /* @__PURE__ */ jsxDEV17("box", {
7253
+ height: 1,
7254
+ flexDirection: "row",
7255
+ paddingLeft: 2,
7256
+ paddingRight: 2,
7257
+ paddingTop: 1,
7258
+ paddingBottom: 1,
7259
+ onMouseDown: () => {
7260
+ setStep("pick");
7261
+ setSelectedProvider(null);
7262
+ setModelInput("");
7263
+ setAddedModels([]);
7264
+ setSaveError("");
7265
+ setInputError("");
7266
+ },
7267
+ children: [
7268
+ /* @__PURE__ */ jsxDEV17("text", {
7269
+ fg: theme.dim,
7270
+ children: "\u2190 "
7271
+ }, undefined, false, undefined, this),
7272
+ /* @__PURE__ */ jsxDEV17("text", {
7273
+ fg: theme.accent,
7274
+ children: "Back"
7275
+ }, undefined, false, undefined, this),
7276
+ /* @__PURE__ */ jsxDEV17("text", {
7277
+ fg: theme.dim,
7278
+ children: " [Esc]"
7279
+ }, undefined, false, undefined, this)
7280
+ ]
7033
7281
  }, undefined, true, undefined, this)
7034
7282
  ]
7035
7283
  }, undefined, true, undefined, this)
@@ -7043,7 +7291,7 @@ function AddModelsScreen() {
7043
7291
  children: /* @__PURE__ */ jsxDEV17("box", {
7044
7292
  flexDirection: "column",
7045
7293
  border: true,
7046
- borderStyle: "rounded",
7294
+ borderStyle: "single",
7047
7295
  borderColor: theme.border,
7048
7296
  backgroundColor: theme.background,
7049
7297
  width: CARD_W,
@@ -7059,7 +7307,10 @@ function AddModelsScreen() {
7059
7307
  }, undefined, false, undefined, this),
7060
7308
  /* @__PURE__ */ jsxDEV17("box", {
7061
7309
  height: 1,
7062
- backgroundColor: theme.border
7310
+ children: /* @__PURE__ */ jsxDEV17("text", {
7311
+ fg: theme.border,
7312
+ children: "\u2500".repeat(150)
7313
+ }, undefined, false, undefined, this)
7063
7314
  }, undefined, false, undefined, this),
7064
7315
  /* @__PURE__ */ jsxDEV17("box", {
7065
7316
  flexDirection: "column",
@@ -7092,6 +7343,16 @@ function AddModelsScreen() {
7092
7343
  width: "100%",
7093
7344
  flexDirection: "row",
7094
7345
  backgroundColor: isActive ? theme.border : "transparent",
7346
+ onMouseOver: () => setCursor(i),
7347
+ onMouseDown: () => {
7348
+ setCursor(i);
7349
+ setSelectedProvider(prov);
7350
+ setModelInput("");
7351
+ setAddedModels([]);
7352
+ setSaveError("");
7353
+ setInputError("");
7354
+ setStep("add");
7355
+ },
7095
7356
  children: [
7096
7357
  /* @__PURE__ */ jsxDEV17("text", {
7097
7358
  fg: theme.dim,
@@ -7120,6 +7381,36 @@ function AddModelsScreen() {
7120
7381
  }, prov.id, true, undefined, this);
7121
7382
  })
7122
7383
  ]
7384
+ }, undefined, true, undefined, this),
7385
+ /* @__PURE__ */ jsxDEV17("box", {
7386
+ height: 1,
7387
+ children: /* @__PURE__ */ jsxDEV17("text", {
7388
+ fg: theme.border,
7389
+ children: "\u2500".repeat(150)
7390
+ }, undefined, false, undefined, this)
7391
+ }, undefined, false, undefined, this),
7392
+ /* @__PURE__ */ jsxDEV17("box", {
7393
+ height: 1,
7394
+ flexDirection: "row",
7395
+ paddingLeft: 2,
7396
+ paddingRight: 2,
7397
+ paddingTop: 1,
7398
+ paddingBottom: 1,
7399
+ onMouseDown: () => navigate("model-menu"),
7400
+ children: [
7401
+ /* @__PURE__ */ jsxDEV17("text", {
7402
+ fg: theme.dim,
7403
+ children: "\u2190 "
7404
+ }, undefined, false, undefined, this),
7405
+ /* @__PURE__ */ jsxDEV17("text", {
7406
+ fg: theme.accent,
7407
+ children: "Back"
7408
+ }, undefined, false, undefined, this),
7409
+ /* @__PURE__ */ jsxDEV17("text", {
7410
+ fg: theme.dim,
7411
+ children: " [Esc]"
7412
+ }, undefined, false, undefined, this)
7413
+ ]
7123
7414
  }, undefined, true, undefined, this)
7124
7415
  ]
7125
7416
  }, undefined, true, undefined, this)
@@ -7138,9 +7429,12 @@ function ListProvidersScreen() {
7138
7429
  const { state } = useAppContext();
7139
7430
  const navigate = useNavigate();
7140
7431
  const theme = useTheme();
7432
+ function goBack() {
7433
+ navigate("model-menu");
7434
+ }
7141
7435
  useAppKeyboard((key) => {
7142
7436
  if (key.name === "escape" || key.name === "q") {
7143
- navigate("model-menu");
7437
+ goBack();
7144
7438
  }
7145
7439
  });
7146
7440
  if (state.isLoadingConfig) {
@@ -7155,44 +7449,37 @@ function ListProvidersScreen() {
7155
7449
  }, undefined, false, undefined, this);
7156
7450
  }
7157
7451
  const providers = state.config?.providers ?? [];
7158
- if (providers.length === 0) {
7159
- return /* @__PURE__ */ jsxDEV18("box", {
7160
- flexDirection: "column",
7161
- flexGrow: 1,
7162
- padding: 1,
7163
- children: [
7164
- /* @__PURE__ */ jsxDEV18("text", {
7165
- fg: theme.primary,
7166
- children: "Configured Providers"
7167
- }, undefined, false, undefined, this),
7168
- /* @__PURE__ */ jsxDEV18("box", {
7169
- marginTop: 1,
7170
- children: /* @__PURE__ */ jsxDEV18("text", {
7171
- fg: theme.warning,
7172
- children: "No providers configured yet."
7173
- }, undefined, false, undefined, this)
7174
- }, undefined, false, undefined, this)
7175
- ]
7176
- }, undefined, true, undefined, this);
7177
- }
7178
7452
  return /* @__PURE__ */ jsxDEV18("box", {
7179
7453
  flexDirection: "column",
7180
7454
  flexGrow: 1,
7181
7455
  padding: 1,
7182
7456
  children: [
7183
- /* @__PURE__ */ jsxDEV18("text", {
7184
- fg: theme.primary,
7185
- children: "Configured Providers"
7186
- }, undefined, false, undefined, this),
7187
7457
  /* @__PURE__ */ jsxDEV18("box", {
7188
- marginTop: 1,
7458
+ flexDirection: "row",
7459
+ marginBottom: 1,
7460
+ children: /* @__PURE__ */ jsxDEV18("text", {
7461
+ fg: theme.primary,
7462
+ bold: true,
7463
+ children: "Configured Providers"
7464
+ }, undefined, false, undefined, this)
7465
+ }, undefined, false, undefined, this),
7466
+ providers.length === 0 ? /* @__PURE__ */ jsxDEV18("box", {
7467
+ flexDirection: "column",
7468
+ flexGrow: 1,
7469
+ alignItems: "center",
7470
+ justifyContent: "center",
7471
+ children: /* @__PURE__ */ jsxDEV18("text", {
7472
+ fg: theme.warning,
7473
+ children: "No providers configured yet."
7474
+ }, undefined, false, undefined, this)
7475
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV18("box", {
7189
7476
  flexGrow: 1,
7190
7477
  children: /* @__PURE__ */ jsxDEV18("scrollbox", {
7191
7478
  focused: true,
7192
7479
  children: providers.map((provider, i) => /* @__PURE__ */ jsxDEV18("box", {
7193
7480
  flexDirection: "column",
7194
7481
  border: true,
7195
- borderStyle: "rounded",
7482
+ borderStyle: "single",
7196
7483
  borderColor: theme.border,
7197
7484
  backgroundColor: theme.background,
7198
7485
  marginBottom: 1,
@@ -7225,7 +7512,36 @@ function ListProvidersScreen() {
7225
7512
  ]
7226
7513
  }, i, true, undefined, this))
7227
7514
  }, undefined, false, undefined, this)
7228
- }, undefined, false, undefined, this)
7515
+ }, undefined, false, undefined, this),
7516
+ /* @__PURE__ */ jsxDEV18("box", {
7517
+ height: 1,
7518
+ marginTop: 1,
7519
+ children: /* @__PURE__ */ jsxDEV18("text", {
7520
+ fg: theme.border,
7521
+ children: "\u2500".repeat(70)
7522
+ }, undefined, false, undefined, this)
7523
+ }, undefined, false, undefined, this),
7524
+ /* @__PURE__ */ jsxDEV18("box", {
7525
+ height: 1,
7526
+ flexDirection: "row",
7527
+ paddingLeft: 1,
7528
+ paddingRight: 1,
7529
+ onMouseDown: goBack,
7530
+ children: [
7531
+ /* @__PURE__ */ jsxDEV18("text", {
7532
+ fg: theme.dim,
7533
+ children: "\u2190 "
7534
+ }, undefined, false, undefined, this),
7535
+ /* @__PURE__ */ jsxDEV18("text", {
7536
+ fg: theme.accent,
7537
+ children: "Back"
7538
+ }, undefined, false, undefined, this),
7539
+ /* @__PURE__ */ jsxDEV18("text", {
7540
+ fg: theme.dim,
7541
+ children: " [Q] or [Esc]"
7542
+ }, undefined, false, undefined, this)
7543
+ ]
7544
+ }, undefined, true, undefined, this)
7229
7545
  ]
7230
7546
  }, undefined, true, undefined, this);
7231
7547
  }
@@ -7240,9 +7556,12 @@ import { jsxDEV as jsxDEV19 } from "@opentui/react/jsx-dev-runtime";
7240
7556
  function FAQScreen() {
7241
7557
  const navigate = useNavigate();
7242
7558
  const theme = useTheme();
7559
+ function goBack() {
7560
+ navigate("main-menu");
7561
+ }
7243
7562
  useAppKeyboard((key) => {
7244
7563
  if (key.name === "escape" || key.name === "q") {
7245
- navigate("main-menu");
7564
+ goBack();
7246
7565
  }
7247
7566
  });
7248
7567
  return /* @__PURE__ */ jsxDEV19("box", {
@@ -7253,6 +7572,7 @@ function FAQScreen() {
7253
7572
  children: /* @__PURE__ */ jsxDEV19("box", {
7254
7573
  flexDirection: "column",
7255
7574
  width: 70,
7575
+ flexGrow: 1,
7256
7576
  children: [
7257
7577
  /* @__PURE__ */ jsxDEV19("box", {
7258
7578
  marginBottom: 1,
@@ -7265,13 +7585,14 @@ function FAQScreen() {
7265
7585
  /* @__PURE__ */ jsxDEV19("scrollbox", {
7266
7586
  focused: true,
7267
7587
  flexGrow: 1,
7588
+ style: { scrollbarOptions: { showArrows: true, trackOptions: { foregroundColor: theme.primary, backgroundColor: theme.border } } },
7268
7589
  children: /* @__PURE__ */ jsxDEV19("box", {
7269
7590
  flexDirection: "column",
7270
7591
  children: [
7271
7592
  /* @__PURE__ */ jsxDEV19("box", {
7272
7593
  flexDirection: "column",
7273
7594
  border: true,
7274
- borderStyle: "rounded",
7595
+ borderStyle: "single",
7275
7596
  borderColor: theme.border,
7276
7597
  padding: 1,
7277
7598
  marginBottom: 1,
@@ -7382,7 +7703,7 @@ function FAQScreen() {
7382
7703
  /* @__PURE__ */ jsxDEV19("box", {
7383
7704
  flexDirection: "column",
7384
7705
  border: true,
7385
- borderStyle: "rounded",
7706
+ borderStyle: "single",
7386
7707
  borderColor: theme.border,
7387
7708
  padding: 1,
7388
7709
  marginBottom: 1,
@@ -7448,7 +7769,7 @@ function FAQScreen() {
7448
7769
  /* @__PURE__ */ jsxDEV19("box", {
7449
7770
  flexDirection: "column",
7450
7771
  border: true,
7451
- borderStyle: "rounded",
7772
+ borderStyle: "single",
7452
7773
  borderColor: theme.border,
7453
7774
  padding: 1,
7454
7775
  marginBottom: 1,
@@ -7479,19 +7800,40 @@ function FAQScreen() {
7479
7800
  children: " \u2022 [*] in results means token count was estimated"
7480
7801
  }, undefined, false, undefined, this)
7481
7802
  ]
7482
- }, undefined, true, undefined, this),
7483
- /* @__PURE__ */ jsxDEV19("box", {
7484
- flexDirection: "row",
7485
- justifyContent: "center",
7486
- marginTop: 1,
7487
- children: /* @__PURE__ */ jsxDEV19("text", {
7488
- fg: theme.dim,
7489
- children: "Press [Q] or [Esc] to return to main menu"
7490
- }, undefined, false, undefined, this)
7491
- }, undefined, false, undefined, this)
7803
+ }, undefined, true, undefined, this)
7492
7804
  ]
7493
7805
  }, undefined, true, undefined, this)
7494
- }, undefined, false, undefined, this)
7806
+ }, undefined, false, undefined, this),
7807
+ /* @__PURE__ */ jsxDEV19("box", {
7808
+ height: 1,
7809
+ marginTop: 1,
7810
+ children: /* @__PURE__ */ jsxDEV19("text", {
7811
+ fg: theme.border,
7812
+ children: "\u2500".repeat(70)
7813
+ }, undefined, false, undefined, this)
7814
+ }, undefined, false, undefined, this),
7815
+ /* @__PURE__ */ jsxDEV19("box", {
7816
+ height: 1,
7817
+ width: "100%",
7818
+ flexDirection: "row",
7819
+ paddingLeft: 1,
7820
+ paddingRight: 1,
7821
+ onMouseDown: goBack,
7822
+ children: [
7823
+ /* @__PURE__ */ jsxDEV19("text", {
7824
+ fg: theme.dim,
7825
+ children: "\u2190 "
7826
+ }, undefined, false, undefined, this),
7827
+ /* @__PURE__ */ jsxDEV19("text", {
7828
+ fg: theme.accent,
7829
+ children: "Back to main menu"
7830
+ }, undefined, false, undefined, this),
7831
+ /* @__PURE__ */ jsxDEV19("text", {
7832
+ fg: theme.dim,
7833
+ children: " [Q] or [Esc]"
7834
+ }, undefined, false, undefined, this)
7835
+ ]
7836
+ }, undefined, true, undefined, this)
7495
7837
  ]
7496
7838
  }, undefined, true, undefined, this)
7497
7839
  }, undefined, false, undefined, this);
@@ -7512,7 +7854,7 @@ function getHints(screen, benchResults) {
7512
7854
  case "model-menu":
7513
7855
  return ["[\u2191\u2193] navigate", "[Enter] select", "[Q] back"];
7514
7856
  case "model-select":
7515
- return ["[\u2191\u2193] navigate", "[Tab] select", "[Enter] run", "[A] all", "[N] none", "[R] recent", "[Esc] back"];
7857
+ return ["[\u2191\u2193] nav [Tab] sel [Enter] run", "[A]ll [N]one [R]ecent [Esc] back"];
7516
7858
  case "benchmark": {
7517
7859
  const allDone = benchResults.length > 0 && benchResults.every((r) => r.status === "done" || r.status === "error");
7518
7860
  return allDone ? ["[R] rerun", "[Enter] back to menu", "[Q] back to menu"] : ["Benchmark in progress..."];