ai-speedometer 2.2.0 → 2.3.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.
Files changed (2) hide show
  1. package/dist/ai-speedometer +2030 -807
  2. package/package.json +1 -1
@@ -390,9 +390,11 @@ var init_models_dev = __esm(() => {
390
390
  // ../core/src/ai-config.ts
391
391
  var exports_ai_config = {};
392
392
  __export(exports_ai_config, {
393
+ writeThemeToConfig: () => writeThemeToConfig,
393
394
  writeAIConfig: () => writeAIConfig,
394
395
  removeVerifiedProvider: () => removeVerifiedProvider,
395
396
  removeCustomProvider: () => removeCustomProvider,
397
+ readThemeFromConfig: () => readThemeFromConfig,
396
398
  readAIConfig: () => readAIConfig,
397
399
  getVerifiedProvidersFromConfig: () => getVerifiedProvidersFromConfig,
398
400
  getRecentModels: () => getRecentModels,
@@ -433,6 +435,12 @@ var getAIConfigPaths = () => {
433
435
  console.warn("Warning: Could not read ai-benchmark-config.json:", error.message);
434
436
  return { verifiedProviders: {}, customProviders: [] };
435
437
  }
438
+ }, readThemeFromConfig = async () => {
439
+ const config = await readAIConfig();
440
+ return config.theme ?? "tokyonight";
441
+ }, writeThemeToConfig = async (theme) => {
442
+ const config = await readAIConfig();
443
+ await writeAIConfig({ ...config, theme });
436
444
  }, writeAIConfig = async (config) => {
437
445
  const { configJson } = getAIConfigPaths();
438
446
  try {
@@ -1924,6 +1932,7 @@ async function benchmarkSingleModelRest(model, logger) {
1924
1932
  const finalInputTokens = inputTokens || Math.round(TEST_PROMPT.length / 4);
1925
1933
  const totalTokens = finalInputTokens + finalOutputTokens;
1926
1934
  const tokensPerSecond = generationTime > 0 ? finalOutputTokens / generationTime * 1000 : 0;
1935
+ const f1000 = tokensPerSecond > 0 ? 1000 * (timeToFirstToken / 1000 + 300 / tokensPerSecond) / 3600 : Infinity;
1927
1936
  return {
1928
1937
  model: model.name,
1929
1938
  provider: model.providerName,
@@ -1931,6 +1940,7 @@ async function benchmarkSingleModelRest(model, logger) {
1931
1940
  timeToFirstToken,
1932
1941
  tokenCount: finalOutputTokens,
1933
1942
  tokensPerSecond,
1943
+ f1000,
1934
1944
  promptTokens: finalInputTokens,
1935
1945
  totalTokens,
1936
1946
  usedEstimateForOutput,
@@ -1946,6 +1956,7 @@ async function benchmarkSingleModelRest(model, logger) {
1946
1956
  timeToFirstToken: 0,
1947
1957
  tokenCount: 0,
1948
1958
  tokensPerSecond: 0,
1959
+ f1000: Infinity,
1949
1960
  promptTokens: 0,
1950
1961
  totalTokens: 0,
1951
1962
  usedEstimateForOutput: true,
@@ -2011,6 +2022,8 @@ function buildJsonOutput(providerName, providerId, modelName, modelId, result, f
2011
2022
  timeToFirstToken: result.timeToFirstToken,
2012
2023
  timeToFirstTokenSeconds: result.timeToFirstToken / 1000,
2013
2024
  tokensPerSecond: result.tokensPerSecond,
2025
+ f1000: result.f1000,
2026
+ f1000Hours: result.f1000 === Infinity ? null : result.f1000,
2014
2027
  outputTokens: result.tokenCount,
2015
2028
  promptTokens: result.promptTokens,
2016
2029
  totalTokens: result.totalTokens,
@@ -2283,12 +2296,727 @@ var init_AppContext = __esm(() => {
2283
2296
  AppContext = createContext(null);
2284
2297
  });
2285
2298
 
2299
+ // src/tui/theme/themes.ts
2300
+ function getTheme(name) {
2301
+ return THEMES[name] ?? THEMES[DEFAULT_THEME];
2302
+ }
2303
+ var THEMES, DEFAULT_THEME = "tokyonight", THEME_NAMES;
2304
+ var init_themes = __esm(() => {
2305
+ THEMES = {
2306
+ tokyonight: {
2307
+ background: "#1a1b26",
2308
+ surface: "#1e2030",
2309
+ border: "#292e42",
2310
+ dim: "#565f89",
2311
+ text: "#c0caf5",
2312
+ primary: "#7aa2f7",
2313
+ accent: "#7dcfff",
2314
+ secondary: "#bb9af7",
2315
+ success: "#9ece6a",
2316
+ error: "#f7768e",
2317
+ warning: "#ff9e64"
2318
+ },
2319
+ dracula: {
2320
+ background: "#282a36",
2321
+ surface: "#21222c",
2322
+ border: "#44475a",
2323
+ dim: "#6272a4",
2324
+ text: "#f8f8f2",
2325
+ primary: "#bd93f9",
2326
+ accent: "#8be9fd",
2327
+ secondary: "#ff79c6",
2328
+ success: "#50fa7b",
2329
+ error: "#ff5555",
2330
+ warning: "#f1fa8c"
2331
+ },
2332
+ catppuccin: {
2333
+ background: "#1e1e2e",
2334
+ surface: "#181825",
2335
+ border: "#313244",
2336
+ dim: "#585b70",
2337
+ text: "#cdd6f4",
2338
+ primary: "#89b4fa",
2339
+ accent: "#89dceb",
2340
+ secondary: "#cba6f7",
2341
+ success: "#a6e3a1",
2342
+ error: "#f38ba8",
2343
+ warning: "#fab387"
2344
+ },
2345
+ "catppuccin-frappe": {
2346
+ background: "#303446",
2347
+ surface: "#292c3c",
2348
+ border: "#414559",
2349
+ dim: "#b5bfe2",
2350
+ text: "#c6d0f5",
2351
+ primary: "#8da4e2",
2352
+ accent: "#f4b8e4",
2353
+ secondary: "#ca9ee6",
2354
+ success: "#a6d189",
2355
+ error: "#e78284",
2356
+ warning: "#e5c890"
2357
+ },
2358
+ "catppuccin-macchiato": {
2359
+ background: "#24273a",
2360
+ surface: "#1e2030",
2361
+ border: "#363a4f",
2362
+ dim: "#b8c0e0",
2363
+ text: "#cad3f5",
2364
+ primary: "#8aadf4",
2365
+ accent: "#f5bde6",
2366
+ secondary: "#c6a0f6",
2367
+ success: "#a6da95",
2368
+ error: "#ed8796",
2369
+ warning: "#eed49f"
2370
+ },
2371
+ kanagawa: {
2372
+ background: "#1F1F28",
2373
+ surface: "#2A2A37",
2374
+ border: "#54546D",
2375
+ dim: "#727169",
2376
+ text: "#DCD7BA",
2377
+ primary: "#7E9CD8",
2378
+ accent: "#7FB4CA",
2379
+ secondary: "#957FB8",
2380
+ success: "#98BB6C",
2381
+ error: "#E82424",
2382
+ warning: "#D7A657"
2383
+ },
2384
+ rosepine: {
2385
+ background: "#191724",
2386
+ surface: "#1f1d2e",
2387
+ border: "#403d52",
2388
+ dim: "#6e6a86",
2389
+ text: "#e0def4",
2390
+ primary: "#9ccfd8",
2391
+ accent: "#ebbcba",
2392
+ secondary: "#c4a7e7",
2393
+ success: "#31748f",
2394
+ error: "#eb6f92",
2395
+ warning: "#f6c177"
2396
+ },
2397
+ nord: {
2398
+ background: "#2E3440",
2399
+ surface: "#3B4252",
2400
+ border: "#434C5E",
2401
+ dim: "#8B95A7",
2402
+ text: "#ECEFF4",
2403
+ primary: "#88C0D0",
2404
+ accent: "#8FBCBB",
2405
+ secondary: "#81A1C1",
2406
+ success: "#A3BE8C",
2407
+ error: "#BF616A",
2408
+ warning: "#D08770"
2409
+ },
2410
+ aura: {
2411
+ background: "#0f0f0f",
2412
+ surface: "#15141b",
2413
+ border: "#2d2d2d",
2414
+ dim: "#6d6d6d",
2415
+ text: "#edecee",
2416
+ primary: "#a277ff",
2417
+ accent: "#a277ff",
2418
+ secondary: "#f694ff",
2419
+ success: "#61ffca",
2420
+ error: "#ff6767",
2421
+ warning: "#ffca85"
2422
+ },
2423
+ ayu: {
2424
+ background: "#0B0E14",
2425
+ surface: "#0F131A",
2426
+ border: "#6C7380",
2427
+ dim: "#565B66",
2428
+ text: "#BFBDB6",
2429
+ primary: "#59C2FF",
2430
+ accent: "#E6B450",
2431
+ secondary: "#D2A6FF",
2432
+ success: "#7FD962",
2433
+ error: "#D95757",
2434
+ warning: "#E6B673"
2435
+ },
2436
+ carbonfox: {
2437
+ background: "#161616",
2438
+ surface: "#1a1a1a",
2439
+ border: "#303030",
2440
+ dim: "#7d848f",
2441
+ text: "#f2f4f8",
2442
+ primary: "#33b1ff",
2443
+ accent: "#ff7eb6",
2444
+ secondary: "#78a9ff",
2445
+ success: "#25be6a",
2446
+ error: "#ee5396",
2447
+ warning: "#f1c21b"
2448
+ },
2449
+ cobalt2: {
2450
+ background: "#193549",
2451
+ surface: "#122738",
2452
+ border: "#1f4662",
2453
+ dim: "#adb7c9",
2454
+ text: "#ffffff",
2455
+ primary: "#0088ff",
2456
+ accent: "#2affdf",
2457
+ secondary: "#9a5feb",
2458
+ success: "#9eff80",
2459
+ error: "#ff0088",
2460
+ warning: "#ffc600"
2461
+ },
2462
+ cursor: {
2463
+ background: "#181818",
2464
+ surface: "#141414",
2465
+ border: "#333333",
2466
+ dim: "#666666",
2467
+ text: "#e4e4e4",
2468
+ primary: "#88c0d0",
2469
+ accent: "#88c0d0",
2470
+ secondary: "#81a1c1",
2471
+ success: "#3fa266",
2472
+ error: "#e34671",
2473
+ warning: "#f1b467"
2474
+ },
2475
+ gruvbox: {
2476
+ background: "#282828",
2477
+ surface: "#3c3836",
2478
+ border: "#665c54",
2479
+ dim: "#928374",
2480
+ text: "#ebdbb2",
2481
+ primary: "#83a598",
2482
+ accent: "#8ec07c",
2483
+ secondary: "#d3869b",
2484
+ success: "#b8bb26",
2485
+ error: "#fb4934",
2486
+ warning: "#fe8019"
2487
+ },
2488
+ material: {
2489
+ background: "#263238",
2490
+ surface: "#1e272c",
2491
+ border: "#37474f",
2492
+ dim: "#546e7a",
2493
+ text: "#eeffff",
2494
+ primary: "#82aaff",
2495
+ accent: "#89ddff",
2496
+ secondary: "#c792ea",
2497
+ success: "#c3e88d",
2498
+ error: "#f07178",
2499
+ warning: "#ffcb6b"
2500
+ },
2501
+ matrix: {
2502
+ background: "#0a0e0a",
2503
+ surface: "#0e130d",
2504
+ border: "#1e2a1b",
2505
+ dim: "#8ca391",
2506
+ text: "#62ff94",
2507
+ primary: "#2eff6a",
2508
+ accent: "#c770ff",
2509
+ secondary: "#00efff",
2510
+ success: "#62ff94",
2511
+ error: "#ff4b4b",
2512
+ warning: "#e6ff57"
2513
+ },
2514
+ monokai: {
2515
+ background: "#272822",
2516
+ surface: "#1e1f1c",
2517
+ border: "#3e3d32",
2518
+ dim: "#75715e",
2519
+ text: "#f8f8f2",
2520
+ primary: "#66d9ef",
2521
+ accent: "#a6e22e",
2522
+ secondary: "#ae81ff",
2523
+ success: "#a6e22e",
2524
+ error: "#f92672",
2525
+ warning: "#e6db74"
2526
+ },
2527
+ nightowl: {
2528
+ background: "#011627",
2529
+ surface: "#0b253a",
2530
+ border: "#5f7e97",
2531
+ dim: "#5f7e97",
2532
+ text: "#d6deeb",
2533
+ primary: "#82AAFF",
2534
+ accent: "#c792ea",
2535
+ secondary: "#7fdbca",
2536
+ success: "#c5e478",
2537
+ error: "#EF5350",
2538
+ warning: "#ecc48d"
2539
+ },
2540
+ "one-dark": {
2541
+ background: "#282c34",
2542
+ surface: "#21252b",
2543
+ border: "#393f4a",
2544
+ dim: "#5c6370",
2545
+ text: "#abb2bf",
2546
+ primary: "#61afef",
2547
+ accent: "#56b6c2",
2548
+ secondary: "#c678dd",
2549
+ success: "#98c379",
2550
+ error: "#e06c75",
2551
+ warning: "#e5c07b"
2552
+ },
2553
+ opencode: {
2554
+ background: "#0a0a0a",
2555
+ surface: "#141414",
2556
+ border: "#484848",
2557
+ dim: "#808080",
2558
+ text: "#eeeeee",
2559
+ primary: "#fab283",
2560
+ accent: "#9d7cd8",
2561
+ secondary: "#5c9cf5",
2562
+ success: "#7fd88f",
2563
+ error: "#e06c75",
2564
+ warning: "#f5a742"
2565
+ },
2566
+ "osaka-jade": {
2567
+ background: "#111c18",
2568
+ surface: "#1a2520",
2569
+ border: "#3d4a44",
2570
+ dim: "#53685B",
2571
+ text: "#C1C497",
2572
+ primary: "#2DD5B7",
2573
+ accent: "#549e6a",
2574
+ secondary: "#D2689C",
2575
+ success: "#549e6a",
2576
+ error: "#FF5345",
2577
+ warning: "#E5C736"
2578
+ },
2579
+ palenight: {
2580
+ background: "#292d3e",
2581
+ surface: "#1e2132",
2582
+ border: "#32364a",
2583
+ dim: "#676e95",
2584
+ text: "#a6accd",
2585
+ primary: "#82aaff",
2586
+ accent: "#89ddff",
2587
+ secondary: "#c792ea",
2588
+ success: "#c3e88d",
2589
+ error: "#f07178",
2590
+ warning: "#ffcb6b"
2591
+ },
2592
+ synthwave84: {
2593
+ background: "#262335",
2594
+ surface: "#1e1a29",
2595
+ border: "#495495",
2596
+ dim: "#848bbd",
2597
+ text: "#ffffff",
2598
+ primary: "#36f9f6",
2599
+ accent: "#b084eb",
2600
+ secondary: "#ff7edb",
2601
+ success: "#72f1b8",
2602
+ error: "#fe4450",
2603
+ warning: "#fede5d"
2604
+ },
2605
+ vesper: {
2606
+ background: "#101010",
2607
+ surface: "#181818",
2608
+ border: "#282828",
2609
+ dim: "#A0A0A0",
2610
+ text: "#ffffff",
2611
+ primary: "#FFC799",
2612
+ accent: "#FFC799",
2613
+ secondary: "#99FFE4",
2614
+ success: "#99FFE4",
2615
+ error: "#FF8080",
2616
+ warning: "#FFC799"
2617
+ },
2618
+ zenburn: {
2619
+ background: "#3f3f3f",
2620
+ surface: "#4f4f4f",
2621
+ border: "#5f5f5f",
2622
+ dim: "#9f9f9f",
2623
+ text: "#dcdccc",
2624
+ primary: "#8cd0d3",
2625
+ accent: "#93e0e3",
2626
+ secondary: "#dc8cc3",
2627
+ success: "#7f9f7f",
2628
+ error: "#cc9393",
2629
+ warning: "#f0dfaf"
2630
+ },
2631
+ orng: {
2632
+ background: "#0a0a0a",
2633
+ surface: "#141414",
2634
+ border: "#EC5B2B",
2635
+ dim: "#808080",
2636
+ text: "#eeeeee",
2637
+ primary: "#EC5B2B",
2638
+ accent: "#FFF7F1",
2639
+ secondary: "#EE7948",
2640
+ success: "#6ba1e6",
2641
+ error: "#e06c75",
2642
+ warning: "#EC5B2B"
2643
+ },
2644
+ "lucent-orng": {
2645
+ background: "#000000",
2646
+ surface: "#0a0a0a",
2647
+ border: "#EC5B2B",
2648
+ dim: "#808080",
2649
+ text: "#eeeeee",
2650
+ primary: "#EC5B2B",
2651
+ accent: "#FFF7F1",
2652
+ secondary: "#EE7948",
2653
+ success: "#6ba1e6",
2654
+ error: "#e06c75",
2655
+ warning: "#EC5B2B"
2656
+ },
2657
+ github: {
2658
+ background: "#ffffff",
2659
+ surface: "#f6f8fa",
2660
+ border: "#d0d7de",
2661
+ dim: "#57606a",
2662
+ text: "#24292f",
2663
+ primary: "#0969da",
2664
+ accent: "#1b7c83",
2665
+ secondary: "#8250df",
2666
+ success: "#1a7f37",
2667
+ error: "#cf222e",
2668
+ warning: "#9a6700"
2669
+ },
2670
+ everforest: {
2671
+ background: "#fdf6e3",
2672
+ surface: "#efebd4",
2673
+ border: "#939f91",
2674
+ dim: "#a6b0a0",
2675
+ text: "#5c6a72",
2676
+ primary: "#8da101",
2677
+ accent: "#3a94c5",
2678
+ secondary: "#df69ba",
2679
+ success: "#8da101",
2680
+ error: "#f85552",
2681
+ warning: "#f57d26"
2682
+ },
2683
+ solarized: {
2684
+ background: "#fdf6e3",
2685
+ surface: "#eee8d5",
2686
+ border: "#cdc8b1",
2687
+ dim: "#93a1a1",
2688
+ text: "#657b83",
2689
+ primary: "#268bd2",
2690
+ accent: "#2aa198",
2691
+ secondary: "#6c71c4",
2692
+ success: "#859900",
2693
+ error: "#dc322f",
2694
+ warning: "#b58900"
2695
+ },
2696
+ flexoki: {
2697
+ background: "#FFFCF0",
2698
+ surface: "#F2F0E5",
2699
+ border: "#B7B5AC",
2700
+ dim: "#6F6E69",
2701
+ text: "#100F0F",
2702
+ primary: "#205EA6",
2703
+ accent: "#BC5215",
2704
+ secondary: "#5E409D",
2705
+ success: "#66800B",
2706
+ error: "#AF3029",
2707
+ warning: "#BC5215"
2708
+ },
2709
+ mercury: {
2710
+ background: "#ffffff",
2711
+ surface: "#fbfcfd",
2712
+ border: "#e0e0e8",
2713
+ dim: "#70707d",
2714
+ text: "#363644",
2715
+ primary: "#5266eb",
2716
+ accent: "#8da4f5",
2717
+ secondary: "#465bd1",
2718
+ success: "#036e43",
2719
+ error: "#b0175f",
2720
+ warning: "#a44200"
2721
+ },
2722
+ vercel: {
2723
+ background: "#FFFFFF",
2724
+ surface: "#FAFAFA",
2725
+ border: "#EAEAEA",
2726
+ dim: "#666666",
2727
+ text: "#171717",
2728
+ primary: "#0070F3",
2729
+ accent: "#8E4EC6",
2730
+ secondary: "#0062D1",
2731
+ success: "#388E3C",
2732
+ error: "#DC3545",
2733
+ warning: "#FF9500"
2734
+ }
2735
+ };
2736
+ THEME_NAMES = Object.keys(THEMES);
2737
+ });
2738
+
2739
+ // src/tui/theme/ThemeContext.tsx
2740
+ import { createContext as createContext2, useContext as useContext2, useState, useCallback } from "react";
2741
+ import { jsxDEV as jsxDEV2 } from "@opentui/react/jsx-dev-runtime";
2742
+ function ThemeProvider({ name, children }) {
2743
+ const [themeName, setThemeName] = useState(name);
2744
+ const setTheme = useCallback(async (next) => {
2745
+ setThemeName(next);
2746
+ try {
2747
+ const { writeThemeToConfig: writeThemeToConfig2 } = await Promise.resolve().then(() => (init_ai_config(), exports_ai_config));
2748
+ await writeThemeToConfig2(next);
2749
+ } catch {}
2750
+ }, []);
2751
+ return /* @__PURE__ */ jsxDEV2(ThemeContext.Provider, {
2752
+ value: { theme: getTheme(themeName), themeName, setTheme },
2753
+ children
2754
+ }, undefined, false, undefined, this);
2755
+ }
2756
+ function useTheme() {
2757
+ return useContext2(ThemeContext).theme;
2758
+ }
2759
+ function useThemeCtx() {
2760
+ return useContext2(ThemeContext);
2761
+ }
2762
+ var ThemeContext;
2763
+ var init_ThemeContext = __esm(() => {
2764
+ init_themes();
2765
+ ThemeContext = createContext2({
2766
+ theme: getTheme(DEFAULT_THEME),
2767
+ themeName: DEFAULT_THEME,
2768
+ setTheme: () => {}
2769
+ });
2770
+ });
2771
+
2772
+ // src/tui/context/ModalContext.tsx
2773
+ import { createContext as createContext3, useContext as useContext3, useState as useState2 } from "react";
2774
+ import { jsxDEV as jsxDEV3 } from "@opentui/react/jsx-dev-runtime";
2775
+ function ModalProvider({ children }) {
2776
+ const [modalOpen, setModalOpen] = useState2(false);
2777
+ return /* @__PURE__ */ jsxDEV3(ModalContext.Provider, {
2778
+ value: { modalOpen, setModalOpen },
2779
+ children
2780
+ }, undefined, false, undefined, this);
2781
+ }
2782
+ function useModal() {
2783
+ return useContext3(ModalContext);
2784
+ }
2785
+ var ModalContext;
2786
+ var init_ModalContext = __esm(() => {
2787
+ ModalContext = createContext3({ modalOpen: false, setModalOpen: () => {} });
2788
+ });
2789
+
2790
+ // src/tui/components/ThemePicker.tsx
2791
+ import { useState as useState3, useEffect as useEffect2, useRef } from "react";
2792
+ import { useKeyboard } from "@opentui/react";
2793
+ import { jsxDEV as jsxDEV4 } from "@opentui/react/jsx-dev-runtime";
2794
+ function ThemePicker({ onClose }) {
2795
+ const { theme, themeName, setTheme } = useThemeCtx();
2796
+ const [query, setQuery] = useState3("");
2797
+ const [cursor, setCursor] = useState3(0);
2798
+ const scrollRef = useRef(null);
2799
+ const filtered = THEME_NAMES.filter((n) => n.includes(query.toLowerCase()));
2800
+ useEffect2(() => {
2801
+ setCursor(0);
2802
+ const name = filtered[0];
2803
+ if (name)
2804
+ setTheme(name);
2805
+ }, [query]);
2806
+ useEffect2(() => {
2807
+ const sb = scrollRef.current;
2808
+ if (!sb)
2809
+ return;
2810
+ if (cursor < sb.scrollTop)
2811
+ sb.scrollTo(cursor);
2812
+ else if (cursor >= sb.scrollTop + LIST_H)
2813
+ sb.scrollTo(cursor - LIST_H + 1);
2814
+ }, [cursor]);
2815
+ useEffect2(() => {
2816
+ const idx = filtered.indexOf(themeName);
2817
+ if (idx >= 0)
2818
+ setCursor(idx);
2819
+ }, []);
2820
+ useKeyboard((key) => {
2821
+ if (key.name === "escape" || !key.ctrl && key.sequence === "T") {
2822
+ onClose();
2823
+ return;
2824
+ }
2825
+ if (key.name === "up") {
2826
+ const n = Math.max(0, cursor - 1);
2827
+ setCursor(n);
2828
+ const name = filtered[n];
2829
+ if (name)
2830
+ setTheme(name);
2831
+ return;
2832
+ }
2833
+ if (key.name === "down") {
2834
+ const n = Math.min(filtered.length - 1, cursor + 1);
2835
+ setCursor(n);
2836
+ const name = filtered[n];
2837
+ if (name)
2838
+ setTheme(name);
2839
+ return;
2840
+ }
2841
+ if (key.name === "return" || key.name === "enter") {
2842
+ onClose();
2843
+ return;
2844
+ }
2845
+ if (key.name === "backspace" || key.name === "delete") {
2846
+ setQuery((q) => q.slice(0, -1));
2847
+ return;
2848
+ }
2849
+ if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ") {
2850
+ setQuery((q) => q + key.sequence);
2851
+ }
2852
+ });
2853
+ const W = 32;
2854
+ const LIST_H = 9;
2855
+ return /* @__PURE__ */ jsxDEV4("box", {
2856
+ position: "absolute",
2857
+ top: 3,
2858
+ right: 3,
2859
+ width: W,
2860
+ flexDirection: "column",
2861
+ border: true,
2862
+ borderStyle: "rounded",
2863
+ borderColor: theme.primary,
2864
+ backgroundColor: theme.surface,
2865
+ zIndex: 100,
2866
+ children: [
2867
+ /* @__PURE__ */ jsxDEV4("box", {
2868
+ height: 1,
2869
+ flexDirection: "row",
2870
+ paddingLeft: 2,
2871
+ paddingRight: 2,
2872
+ paddingTop: 1,
2873
+ children: [
2874
+ /* @__PURE__ */ jsxDEV4("text", {
2875
+ fg: theme.primary,
2876
+ children: "\uDB80\uDFD8 "
2877
+ }, undefined, false, undefined, this),
2878
+ /* @__PURE__ */ jsxDEV4("text", {
2879
+ fg: theme.text,
2880
+ children: "Themes"
2881
+ }, undefined, false, undefined, this),
2882
+ /* @__PURE__ */ jsxDEV4("text", {
2883
+ fg: theme.dim,
2884
+ children: [
2885
+ " ",
2886
+ themeName
2887
+ ]
2888
+ }, undefined, true, undefined, this)
2889
+ ]
2890
+ }, undefined, true, undefined, this),
2891
+ /* @__PURE__ */ jsxDEV4("box", {
2892
+ height: 1,
2893
+ backgroundColor: theme.border
2894
+ }, undefined, false, undefined, this),
2895
+ /* @__PURE__ */ jsxDEV4("box", {
2896
+ height: 1,
2897
+ flexDirection: "row",
2898
+ paddingLeft: 2,
2899
+ paddingRight: 2,
2900
+ paddingTop: 1,
2901
+ paddingBottom: 1,
2902
+ children: [
2903
+ /* @__PURE__ */ jsxDEV4("text", {
2904
+ fg: theme.dim,
2905
+ children: " "
2906
+ }, undefined, false, undefined, this),
2907
+ /* @__PURE__ */ jsxDEV4("text", {
2908
+ fg: query ? theme.text : theme.dim,
2909
+ children: query || "search..."
2910
+ }, undefined, false, undefined, this),
2911
+ query.length > 0 && /* @__PURE__ */ jsxDEV4("text", {
2912
+ fg: theme.accent,
2913
+ children: "_"
2914
+ }, undefined, false, undefined, this)
2915
+ ]
2916
+ }, undefined, true, undefined, this),
2917
+ /* @__PURE__ */ jsxDEV4("box", {
2918
+ height: 1,
2919
+ backgroundColor: theme.border
2920
+ }, undefined, false, undefined, this),
2921
+ /* @__PURE__ */ jsxDEV4("scrollbox", {
2922
+ ref: scrollRef,
2923
+ height: LIST_H,
2924
+ focused: false,
2925
+ children: filtered.length === 0 ? /* @__PURE__ */ jsxDEV4("box", {
2926
+ height: 1,
2927
+ paddingLeft: 3,
2928
+ children: /* @__PURE__ */ jsxDEV4("text", {
2929
+ fg: theme.dim,
2930
+ children: "no match"
2931
+ }, undefined, false, undefined, this)
2932
+ }, undefined, false, undefined, this) : filtered.map((name, i) => {
2933
+ const isActive = i === cursor;
2934
+ const isCurrent = name === themeName;
2935
+ const isDark = !LIGHT_THEMES.has(name);
2936
+ const tag = isDark ? "\u25C6" : "\u25C7";
2937
+ const tagColor = isDark ? theme.secondary : theme.accent;
2938
+ return /* @__PURE__ */ jsxDEV4("box", {
2939
+ height: 1,
2940
+ flexDirection: "row",
2941
+ backgroundColor: isActive ? theme.border : "transparent",
2942
+ paddingLeft: 2,
2943
+ paddingRight: 2,
2944
+ children: [
2945
+ /* @__PURE__ */ jsxDEV4("text", {
2946
+ fg: isCurrent ? theme.success : theme.dim,
2947
+ width: 2,
2948
+ children: isCurrent ? "\u2713" : " "
2949
+ }, undefined, false, undefined, this),
2950
+ /* @__PURE__ */ jsxDEV4("text", {
2951
+ fg: tagColor,
2952
+ width: 2,
2953
+ children: tag
2954
+ }, undefined, false, undefined, this),
2955
+ /* @__PURE__ */ jsxDEV4("text", {
2956
+ fg: isActive ? theme.text : theme.dim,
2957
+ children: [
2958
+ " ",
2959
+ name
2960
+ ]
2961
+ }, undefined, true, undefined, this),
2962
+ isActive && /* @__PURE__ */ jsxDEV4("text", {
2963
+ fg: theme.primary,
2964
+ children: " \u203A"
2965
+ }, undefined, false, undefined, this)
2966
+ ]
2967
+ }, name, true, undefined, this);
2968
+ })
2969
+ }, undefined, false, undefined, this),
2970
+ /* @__PURE__ */ jsxDEV4("box", {
2971
+ height: 1,
2972
+ backgroundColor: theme.border
2973
+ }, undefined, false, undefined, this),
2974
+ /* @__PURE__ */ jsxDEV4("box", {
2975
+ height: 1,
2976
+ flexDirection: "row",
2977
+ paddingLeft: 2,
2978
+ paddingRight: 2,
2979
+ paddingTop: 1,
2980
+ paddingBottom: 1,
2981
+ children: [
2982
+ /* @__PURE__ */ jsxDEV4("text", {
2983
+ fg: theme.secondary,
2984
+ children: "\u25C6"
2985
+ }, undefined, false, undefined, this),
2986
+ /* @__PURE__ */ jsxDEV4("text", {
2987
+ fg: theme.dim,
2988
+ children: " dark "
2989
+ }, undefined, false, undefined, this),
2990
+ /* @__PURE__ */ jsxDEV4("text", {
2991
+ fg: theme.accent,
2992
+ children: "\u25C7"
2993
+ }, undefined, false, undefined, this),
2994
+ /* @__PURE__ */ jsxDEV4("text", {
2995
+ fg: theme.dim,
2996
+ children: " light "
2997
+ }, undefined, false, undefined, this),
2998
+ /* @__PURE__ */ jsxDEV4("text", {
2999
+ fg: theme.dim,
3000
+ children: " [\u2191\u2193] [Esc]"
3001
+ }, undefined, false, undefined, this)
3002
+ ]
3003
+ }, undefined, true, undefined, this)
3004
+ ]
3005
+ }, undefined, true, undefined, this);
3006
+ }
3007
+ var LIGHT_THEMES;
3008
+ var init_ThemePicker = __esm(() => {
3009
+ init_ThemeContext();
3010
+ init_themes();
3011
+ LIGHT_THEMES = new Set(["github", "everforest", "solarized", "flexoki", "mercury", "vercel"]);
3012
+ });
3013
+
2286
3014
  // package.json
2287
3015
  var package_default;
2288
3016
  var init_package = __esm(() => {
2289
3017
  package_default = {
2290
3018
  name: "ai-speedometer",
2291
- version: "2.2.0",
3019
+ version: "2.3.0",
2292
3020
  description: "A comprehensive CLI tool for benchmarking AI models across multiple providers with parallel execution and professional metrics",
2293
3021
  bin: {
2294
3022
  "ai-speedometer": "dist/ai-speedometer",
@@ -2349,27 +3077,28 @@ var init_package = __esm(() => {
2349
3077
  });
2350
3078
 
2351
3079
  // src/tui/components/Header.tsx
2352
- import { jsxDEV as jsxDEV2 } from "@opentui/react/jsx-dev-runtime";
3080
+ import { jsxDEV as jsxDEV5 } from "@opentui/react/jsx-dev-runtime";
2353
3081
  function Header({ screen }) {
3082
+ const theme = useTheme();
2354
3083
  if (screen === "main-menu")
2355
3084
  return null;
2356
- return /* @__PURE__ */ jsxDEV2("box", {
3085
+ return /* @__PURE__ */ jsxDEV5("box", {
2357
3086
  height: 1,
2358
3087
  flexDirection: "row",
2359
3088
  alignItems: "center",
2360
3089
  paddingLeft: 2,
2361
- backgroundColor: "#16161e",
3090
+ backgroundColor: theme.background,
2362
3091
  children: [
2363
- /* @__PURE__ */ jsxDEV2("text", {
2364
- fg: "#7aa2f7",
3092
+ /* @__PURE__ */ jsxDEV5("text", {
3093
+ fg: theme.primary,
2365
3094
  children: "AI-SPEEDOMETER"
2366
3095
  }, undefined, false, undefined, this),
2367
- /* @__PURE__ */ jsxDEV2("text", {
2368
- fg: "#292e42",
3096
+ /* @__PURE__ */ jsxDEV5("text", {
3097
+ fg: theme.border,
2369
3098
  children: " \xB7 "
2370
3099
  }, undefined, false, undefined, this),
2371
- /* @__PURE__ */ jsxDEV2("text", {
2372
- fg: "#565f89",
3100
+ /* @__PURE__ */ jsxDEV5("text", {
3101
+ fg: theme.dim,
2373
3102
  children: [
2374
3103
  "v",
2375
3104
  package_default.version
@@ -2380,37 +3109,61 @@ function Header({ screen }) {
2380
3109
  }
2381
3110
  var init_Header = __esm(() => {
2382
3111
  init_package();
3112
+ init_ThemeContext();
2383
3113
  });
2384
3114
 
2385
3115
  // src/tui/components/Footer.tsx
2386
- import { jsxDEV as jsxDEV3 } from "@opentui/react/jsx-dev-runtime";
3116
+ import { jsxDEV as jsxDEV6 } from "@opentui/react/jsx-dev-runtime";
2387
3117
  function Footer({ hints }) {
3118
+ const theme = useTheme();
2388
3119
  const joined = hints.join(" \xB7 ");
2389
- return /* @__PURE__ */ jsxDEV3("box", {
3120
+ return /* @__PURE__ */ jsxDEV6("box", {
2390
3121
  height: 1,
2391
3122
  flexDirection: "row",
2392
3123
  alignItems: "center",
2393
3124
  paddingLeft: 1,
2394
3125
  paddingRight: 1,
2395
- backgroundColor: "#16161e",
2396
- children: /* @__PURE__ */ jsxDEV3("text", {
2397
- fg: "#565f89",
3126
+ backgroundColor: theme.background,
3127
+ children: /* @__PURE__ */ jsxDEV6("text", {
3128
+ fg: theme.dim,
2398
3129
  children: joined
2399
3130
  }, undefined, false, undefined, this)
2400
3131
  }, undefined, false, undefined, this);
2401
3132
  }
2402
- var init_Footer = () => {};
3133
+ var init_Footer = __esm(() => {
3134
+ init_ThemeContext();
3135
+ });
3136
+
3137
+ // src/tui/hooks/useAppKeyboard.ts
3138
+ import { useKeyboard as useKeyboard2 } from "@opentui/react";
3139
+ function useAppKeyboard(handler) {
3140
+ const { modalOpen } = useModal();
3141
+ useKeyboard2((key) => {
3142
+ if (modalOpen)
3143
+ return;
3144
+ handler(key);
3145
+ });
3146
+ }
3147
+ var init_useAppKeyboard = __esm(() => {
3148
+ init_ModalContext();
3149
+ });
2403
3150
 
2404
3151
  // src/tui/screens/MainMenuScreen.tsx
2405
- import { useState } from "react";
3152
+ import { useState as useState4 } from "react";
2406
3153
  import { useRenderer } from "@opentui/react";
2407
- import { useKeyboard } from "@opentui/react";
2408
- import { jsxDEV as jsxDEV4 } from "@opentui/react/jsx-dev-runtime";
3154
+ import { jsxDEV as jsxDEV7 } from "@opentui/react/jsx-dev-runtime";
2409
3155
  function MainMenuScreen() {
2410
3156
  const navigate = useNavigate();
2411
3157
  const renderer = useRenderer();
2412
- const [cursor, setCursor] = useState(0);
2413
- useKeyboard((key) => {
3158
+ const theme = useTheme();
3159
+ const [cursor, setCursor] = useState4(0);
3160
+ const ITEMS = [
3161
+ { label: "\u26A1 Run Benchmark", desc: "test model speed & throughput", color: theme.accent },
3162
+ { label: "\u2699 Manage Models", desc: "add providers and configure", color: theme.secondary },
3163
+ { label: "? FAQ / Learn", desc: "how metrics work & resources", color: theme.primary },
3164
+ { label: "\u2715 Exit", desc: "quit the application", color: theme.error }
3165
+ ];
3166
+ useAppKeyboard((key) => {
2414
3167
  if (key.name === "up") {
2415
3168
  setCursor((i) => (i - 1 + ITEMS.length) % ITEMS.length);
2416
3169
  } else if (key.name === "down") {
@@ -2421,27 +3174,29 @@ function MainMenuScreen() {
2421
3174
  else if (cursor === 1)
2422
3175
  navigate("model-menu");
2423
3176
  else if (cursor === 2)
3177
+ navigate("faq");
3178
+ else if (cursor === 3)
2424
3179
  renderer.destroy();
2425
3180
  }
2426
3181
  });
2427
- return /* @__PURE__ */ jsxDEV4("box", {
3182
+ return /* @__PURE__ */ jsxDEV7("box", {
2428
3183
  flexDirection: "column",
2429
3184
  flexGrow: 1,
2430
3185
  alignItems: "center",
2431
3186
  justifyContent: "center",
2432
3187
  children: [
2433
- /* @__PURE__ */ jsxDEV4("box", {
3188
+ /* @__PURE__ */ jsxDEV7("box", {
2434
3189
  flexDirection: "column",
2435
3190
  alignItems: "center",
2436
3191
  marginBottom: 2,
2437
3192
  children: [
2438
- /* @__PURE__ */ jsxDEV4("ascii-font", {
3193
+ /* @__PURE__ */ jsxDEV7("ascii-font", {
2439
3194
  text: "AI-SPEEDOMETER",
2440
3195
  font: "tiny",
2441
- color: "#7aa2f7"
3196
+ color: theme.primary
2442
3197
  }, undefined, false, undefined, this),
2443
- /* @__PURE__ */ jsxDEV4("text", {
2444
- fg: "#565f89",
3198
+ /* @__PURE__ */ jsxDEV7("text", {
3199
+ fg: theme.dim,
2445
3200
  children: [
2446
3201
  "v",
2447
3202
  package_default.version
@@ -2449,39 +3204,39 @@ function MainMenuScreen() {
2449
3204
  }, undefined, true, undefined, this)
2450
3205
  ]
2451
3206
  }, undefined, true, undefined, this),
2452
- /* @__PURE__ */ jsxDEV4("box", {
3207
+ /* @__PURE__ */ jsxDEV7("box", {
2453
3208
  flexDirection: "column",
2454
3209
  border: true,
2455
3210
  borderStyle: "rounded",
2456
- borderColor: "#292e42",
2457
- backgroundColor: "#16161e",
2458
- width: 46,
3211
+ borderColor: theme.border,
3212
+ backgroundColor: theme.background,
3213
+ width: 48,
2459
3214
  children: ITEMS.map((item, i) => {
2460
3215
  const active = i === cursor;
2461
- return /* @__PURE__ */ jsxDEV4("box", {
3216
+ return /* @__PURE__ */ jsxDEV7("box", {
2462
3217
  flexDirection: "row",
2463
3218
  alignItems: "center",
2464
- backgroundColor: active ? "#292e42" : "transparent",
3219
+ backgroundColor: active ? theme.border : "transparent",
2465
3220
  paddingLeft: 2,
2466
3221
  paddingRight: 2,
2467
3222
  paddingTop: 1,
2468
3223
  paddingBottom: 1,
2469
3224
  children: [
2470
- /* @__PURE__ */ jsxDEV4("box", {
3225
+ /* @__PURE__ */ jsxDEV7("box", {
2471
3226
  flexDirection: "column",
2472
3227
  flexGrow: 1,
2473
3228
  children: [
2474
- /* @__PURE__ */ jsxDEV4("text", {
2475
- fg: active ? item.color : "#565f89",
3229
+ /* @__PURE__ */ jsxDEV7("text", {
3230
+ fg: active ? item.color : theme.dim,
2476
3231
  children: item.label
2477
3232
  }, undefined, false, undefined, this),
2478
- /* @__PURE__ */ jsxDEV4("text", {
2479
- fg: active ? "#565f89" : "#292e42",
3233
+ /* @__PURE__ */ jsxDEV7("text", {
3234
+ fg: active ? theme.dim : theme.border,
2480
3235
  children: item.desc
2481
3236
  }, undefined, false, undefined, this)
2482
3237
  ]
2483
3238
  }, undefined, true, undefined, this),
2484
- active && /* @__PURE__ */ jsxDEV4("text", {
3239
+ active && /* @__PURE__ */ jsxDEV7("text", {
2485
3240
  fg: item.color,
2486
3241
  children: "\u203A"
2487
3242
  }, undefined, false, undefined, this)
@@ -2492,24 +3247,20 @@ function MainMenuScreen() {
2492
3247
  ]
2493
3248
  }, undefined, true, undefined, this);
2494
3249
  }
2495
- var ITEMS;
2496
3250
  var init_MainMenuScreen = __esm(() => {
3251
+ init_useAppKeyboard();
2497
3252
  init_AppContext();
3253
+ init_ThemeContext();
2498
3254
  init_package();
2499
- ITEMS = [
2500
- { label: "\u26A1 Run Benchmark", desc: "test model speed & throughput", color: "#7dcfff" },
2501
- { label: "\u2699 Manage Models", desc: "add providers and configure", color: "#bb9af7" },
2502
- { label: "\u2715 Exit", desc: "quit the application", color: "#f7768e" }
2503
- ];
2504
3255
  });
2505
3256
 
2506
3257
  // src/tui/components/MenuList.tsx
2507
- import { useState as useState2 } from "react";
2508
- import { useKeyboard as useKeyboard2 } from "@opentui/react";
2509
- import { jsxDEV as jsxDEV5 } from "@opentui/react/jsx-dev-runtime";
3258
+ import { useState as useState5 } from "react";
3259
+ import { jsxDEV as jsxDEV8 } from "@opentui/react/jsx-dev-runtime";
2510
3260
  function MenuList({ items, selectedIndex: initialIndex = 0, onSelect, onNavigate }) {
2511
- const [cursor, setCursor] = useState2(initialIndex);
2512
- useKeyboard2((key) => {
3261
+ const theme = useTheme();
3262
+ const [cursor, setCursor] = useState5(initialIndex);
3263
+ useAppKeyboard((key) => {
2513
3264
  if (key.name === "up") {
2514
3265
  const next = (cursor - 1 + items.length) % items.length;
2515
3266
  setCursor(next);
@@ -2522,33 +3273,33 @@ function MenuList({ items, selectedIndex: initialIndex = 0, onSelect, onNavigate
2522
3273
  onSelect(cursor);
2523
3274
  }
2524
3275
  });
2525
- return /* @__PURE__ */ jsxDEV5("box", {
3276
+ return /* @__PURE__ */ jsxDEV8("box", {
2526
3277
  flexDirection: "column",
2527
3278
  children: items.map((item, i) => {
2528
3279
  const isSelected = i === cursor;
2529
- return /* @__PURE__ */ jsxDEV5("box", {
3280
+ return /* @__PURE__ */ jsxDEV8("box", {
2530
3281
  flexDirection: "row",
2531
3282
  alignItems: "center",
2532
- backgroundColor: isSelected ? "#292e42" : "transparent",
3283
+ backgroundColor: isSelected ? theme.border : "transparent",
2533
3284
  paddingLeft: 1,
2534
3285
  paddingRight: 1,
2535
3286
  children: [
2536
- /* @__PURE__ */ jsxDEV5("box", {
3287
+ /* @__PURE__ */ jsxDEV8("box", {
2537
3288
  flexDirection: "column",
2538
3289
  flexGrow: 1,
2539
3290
  children: [
2540
- /* @__PURE__ */ jsxDEV5("text", {
2541
- fg: isSelected ? "#c0caf5" : "#565f89",
3291
+ /* @__PURE__ */ jsxDEV8("text", {
3292
+ fg: isSelected ? theme.text : theme.dim,
2542
3293
  children: item.label
2543
3294
  }, undefined, false, undefined, this),
2544
- item.description ? /* @__PURE__ */ jsxDEV5("text", {
2545
- fg: isSelected ? "#565f89" : "#292e42",
3295
+ item.description ? /* @__PURE__ */ jsxDEV8("text", {
3296
+ fg: isSelected ? theme.dim : theme.border,
2546
3297
  children: item.description
2547
3298
  }, undefined, false, undefined, this) : null
2548
3299
  ]
2549
3300
  }, undefined, true, undefined, this),
2550
- isSelected && /* @__PURE__ */ jsxDEV5("text", {
2551
- fg: "#7aa2f7",
3301
+ isSelected && /* @__PURE__ */ jsxDEV8("text", {
3302
+ fg: theme.primary,
2552
3303
  children: "\u203A"
2553
3304
  }, undefined, false, undefined, this)
2554
3305
  ]
@@ -2556,14 +3307,17 @@ function MenuList({ items, selectedIndex: initialIndex = 0, onSelect, onNavigate
2556
3307
  })
2557
3308
  }, undefined, false, undefined, this);
2558
3309
  }
2559
- var init_MenuList = () => {};
3310
+ var init_MenuList = __esm(() => {
3311
+ init_useAppKeyboard();
3312
+ init_ThemeContext();
3313
+ });
2560
3314
 
2561
3315
  // src/tui/screens/ModelMenuScreen.tsx
2562
- import { useKeyboard as useKeyboard3 } from "@opentui/react";
2563
- import { jsxDEV as jsxDEV6 } from "@opentui/react/jsx-dev-runtime";
3316
+ import { jsxDEV as jsxDEV9 } from "@opentui/react/jsx-dev-runtime";
2564
3317
  function ModelMenuScreen() {
2565
3318
  const navigate = useNavigate();
2566
- useKeyboard3((key) => {
3319
+ const theme = useTheme();
3320
+ useAppKeyboard((key) => {
2567
3321
  if (key.name === "escape" || key.name === "q") {
2568
3322
  navigate("main-menu");
2569
3323
  }
@@ -2580,30 +3334,32 @@ function ModelMenuScreen() {
2580
3334
  else if (index === 4)
2581
3335
  navigate("main-menu");
2582
3336
  }
2583
- return /* @__PURE__ */ jsxDEV6("box", {
3337
+ return /* @__PURE__ */ jsxDEV9("box", {
2584
3338
  flexDirection: "column",
2585
3339
  flexGrow: 1,
2586
3340
  padding: 1,
2587
3341
  children: [
2588
- /* @__PURE__ */ jsxDEV6("text", {
2589
- fg: "#7aa2f7",
3342
+ /* @__PURE__ */ jsxDEV9("text", {
3343
+ fg: theme.primary,
2590
3344
  children: "Model Management"
2591
3345
  }, undefined, false, undefined, this),
2592
- /* @__PURE__ */ jsxDEV6("box", {
3346
+ /* @__PURE__ */ jsxDEV9("box", {
2593
3347
  marginTop: 1,
2594
- children: /* @__PURE__ */ jsxDEV6(MenuList, {
2595
- items: ITEMS2,
3348
+ children: /* @__PURE__ */ jsxDEV9(MenuList, {
3349
+ items: ITEMS,
2596
3350
  onSelect: handleSelect
2597
3351
  }, undefined, false, undefined, this)
2598
3352
  }, undefined, false, undefined, this)
2599
3353
  ]
2600
3354
  }, undefined, true, undefined, this);
2601
3355
  }
2602
- var ITEMS2;
3356
+ var ITEMS;
2603
3357
  var init_ModelMenuScreen = __esm(() => {
3358
+ init_useAppKeyboard();
2604
3359
  init_AppContext();
3360
+ init_ThemeContext();
2605
3361
  init_MenuList();
2606
- ITEMS2 = [
3362
+ ITEMS = [
2607
3363
  { label: "Add Verified Provider" },
2608
3364
  { label: "Add Custom Provider" },
2609
3365
  { label: "Add Models to Provider" },
@@ -2613,13 +3369,13 @@ var init_ModelMenuScreen = __esm(() => {
2613
3369
  });
2614
3370
 
2615
3371
  // src/tui/hooks/usePaste.ts
2616
- import { useEffect as useEffect2, useRef } from "react";
3372
+ import { useEffect as useEffect3, useRef as useRef2 } from "react";
2617
3373
  import { useRenderer as useRenderer2 } from "@opentui/react";
2618
3374
  function usePaste(onPaste) {
2619
3375
  const renderer = useRenderer2();
2620
- const callbackRef = useRef(onPaste);
3376
+ const callbackRef = useRef2(onPaste);
2621
3377
  callbackRef.current = onPaste;
2622
- useEffect2(() => {
3378
+ useEffect3(() => {
2623
3379
  const handler = (event) => callbackRef.current(event.text);
2624
3380
  renderer.keyInput.on("paste", handler);
2625
3381
  return () => {
@@ -2630,36 +3386,29 @@ function usePaste(onPaste) {
2630
3386
  var init_usePaste = () => {};
2631
3387
 
2632
3388
  // src/tui/screens/ModelSelectScreen.tsx
2633
- import { useState as useState3, useEffect as useEffect3, useCallback, useRef as useRef2 } from "react";
2634
- import { useKeyboard as useKeyboard4, useTerminalDimensions } from "@opentui/react";
2635
- import { jsxDEV as jsxDEV7 } from "@opentui/react/jsx-dev-runtime";
3389
+ import { useState as useState6, useEffect as useEffect4, useCallback as useCallback2, useRef as useRef3 } from "react";
3390
+ import { useTerminalDimensions } from "@opentui/react";
3391
+ import { jsxDEV as jsxDEV10 } from "@opentui/react/jsx-dev-runtime";
2636
3392
  function ModelSelectScreen() {
2637
3393
  const { state, dispatch } = useAppContext();
2638
3394
  const navigate = useNavigate();
3395
+ const theme = useTheme();
2639
3396
  const { height, width } = useTerminalDimensions();
2640
- const [searchQuery, setSearchQuery] = useState3("");
2641
- const [cursor, setCursor] = useState3(0);
2642
- const [selected, setSelected] = useState3(new Set);
2643
- const [allModels, setAllModels] = useState3([]);
2644
- const [recentKeys, setRecentKeys] = useState3(new Set);
2645
- const [debouncedQuery, setDebouncedQuery] = useState3("");
2646
- const scrollboxRef = useRef2(null);
3397
+ const [searchQuery, setSearchQuery] = useState6("");
3398
+ const [cursor, setCursor] = useState6(0);
3399
+ const [selected, setSelected] = useState6(new Set);
3400
+ const [allModels, setAllModels] = useState6([]);
3401
+ const [recentKeys, setRecentKeys] = useState6(new Set);
3402
+ const [debouncedQuery, setDebouncedQuery] = useState6("");
3403
+ const scrollboxRef = useRef3(null);
2647
3404
  const PAGE_SIZE = Math.max(3, height - 14);
2648
3405
  const CARD_W = Math.min(60, width - 4);
2649
- useEffect3(() => {
3406
+ useEffect4(() => {
2650
3407
  const providers = state.config?.providers ?? [];
2651
3408
  const models = [];
2652
3409
  for (const provider of providers) {
2653
3410
  for (const m of provider.models) {
2654
- models.push({
2655
- id: m.id,
2656
- name: m.name || m.id,
2657
- providerName: provider.name,
2658
- providerType: provider.type,
2659
- providerId: provider.id,
2660
- providerConfig: { baseUrl: provider.baseUrl, apiKey: provider.apiKey },
2661
- key: `${provider.id}::${m.id}`
2662
- });
3411
+ models.push({ id: m.id, name: m.name || m.id, providerName: provider.name, providerType: provider.type, providerId: provider.id, providerConfig: { baseUrl: provider.baseUrl, apiKey: provider.apiKey }, key: `${provider.id}::${m.id}` });
2663
3412
  }
2664
3413
  }
2665
3414
  setAllModels(models);
@@ -2681,11 +3430,11 @@ function ModelSelectScreen() {
2681
3430
  }
2682
3431
  loadRecents();
2683
3432
  }, [state.config]);
2684
- useEffect3(() => {
3433
+ useEffect4(() => {
2685
3434
  const t = setTimeout(() => setDebouncedQuery(searchQuery), DEBOUNCE_MS);
2686
3435
  return () => clearTimeout(t);
2687
3436
  }, [searchQuery]);
2688
- useEffect3(() => {
3437
+ useEffect4(() => {
2689
3438
  setCursor(0);
2690
3439
  }, [debouncedQuery]);
2691
3440
  function isRecent(m) {
@@ -2693,14 +3442,13 @@ function ModelSelectScreen() {
2693
3442
  }
2694
3443
  const orderedModels = (() => {
2695
3444
  if (!debouncedQuery) {
2696
- const recents = allModels.filter((m) => isRecent(m));
2697
- const rest = allModels.filter((m) => !isRecent(m));
2698
- return [...recents, ...rest];
3445
+ const r = allModels.filter((m) => isRecent(m));
3446
+ return [...r, ...allModels.filter((m) => !isRecent(m))];
2699
3447
  }
2700
3448
  const words = debouncedQuery.toLowerCase().split(/\s+/).filter((w) => w.length > 0);
2701
3449
  return allModels.filter((m) => {
2702
- const haystack = `${m.name} ${m.providerName} ${m.providerId} ${m.id}`.toLowerCase();
2703
- return words.every((w) => haystack.includes(w));
3450
+ const h = `${m.name} ${m.providerName} ${m.providerId} ${m.id}`.toLowerCase();
3451
+ return words.every((w) => h.includes(w));
2704
3452
  });
2705
3453
  })();
2706
3454
  const recentCount = !debouncedQuery ? orderedModels.filter((m) => isRecent(m)).length : 0;
@@ -2712,11 +3460,10 @@ function ModelSelectScreen() {
2712
3460
  const mIsRecent = isRecent(m);
2713
3461
  const prevIsRecent = i > 0 ? isRecent(orderedModels[i - 1]) : false;
2714
3462
  if (!debouncedQuery && recentCount > 0) {
2715
- if (i === 0 && mIsRecent) {
3463
+ if (i === 0 && mIsRecent)
2716
3464
  rows.push({ kind: "separator", label: "\u2500\u2500 recent \u2500\u2500" });
2717
- } else if (!mIsRecent && prevIsRecent) {
3465
+ else if (!mIsRecent && prevIsRecent)
2718
3466
  rows.push({ kind: "separator", label: "\u2500\u2500 all models \u2500\u2500" });
2719
- }
2720
3467
  }
2721
3468
  rows.push({ kind: "model", model: m, idx: modelIdx++ });
2722
3469
  }
@@ -2724,26 +3471,25 @@ function ModelSelectScreen() {
2724
3471
  })();
2725
3472
  const allModelRows = allRows.filter((r) => r.kind === "model");
2726
3473
  const cursorModel = allModelRows[cursor]?.model;
2727
- useEffect3(() => {
3474
+ useEffect4(() => {
2728
3475
  const sb = scrollboxRef.current;
2729
3476
  if (!sb)
2730
3477
  return;
2731
3478
  const top = sb.scrollTop;
2732
3479
  const visible = PAGE_SIZE;
2733
- if (cursor < top) {
3480
+ if (cursor < top)
2734
3481
  sb.scrollTo(cursor);
2735
- } else if (cursor >= top + visible) {
3482
+ else if (cursor >= top + visible)
2736
3483
  sb.scrollTo(cursor - visible + 1);
2737
- }
2738
3484
  }, [cursor, PAGE_SIZE]);
2739
- const launchBench = useCallback((models) => {
3485
+ const launchBench = useCallback2((models) => {
2740
3486
  dispatch({ type: "BENCH_START", models });
2741
3487
  navigate("benchmark");
2742
3488
  }, [dispatch, navigate]);
2743
3489
  usePaste((text) => {
2744
3490
  setSearchQuery((q) => q + text.replace(/[\r\n]/g, ""));
2745
3491
  });
2746
- useKeyboard4((key) => {
3492
+ useAppKeyboard((key) => {
2747
3493
  if (key.name === "escape") {
2748
3494
  navigate("main-menu");
2749
3495
  return;
@@ -2778,11 +3524,10 @@ function ModelSelectScreen() {
2778
3524
  return;
2779
3525
  }
2780
3526
  if (key.name === "return" || key.name === "enter") {
2781
- if (selected.size > 0) {
3527
+ if (selected.size > 0)
2782
3528
  launchBench(allModels.filter((m) => selected.has(m.key)));
2783
- } else if (cursorModel) {
3529
+ else if (cursorModel)
2784
3530
  launchBench([cursorModel]);
2785
- }
2786
3531
  return;
2787
3532
  }
2788
3533
  if (!searchQuery && key.sequence === "A") {
@@ -2801,50 +3546,49 @@ function ModelSelectScreen() {
2801
3546
  setSearchQuery((q) => q.slice(0, -1));
2802
3547
  return;
2803
3548
  }
2804
- if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ") {
3549
+ if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ")
2805
3550
  setSearchQuery((q) => q + key.sequence);
2806
- }
2807
3551
  });
2808
3552
  if (state.isLoadingConfig) {
2809
- return /* @__PURE__ */ jsxDEV7("box", {
3553
+ return /* @__PURE__ */ jsxDEV10("box", {
2810
3554
  flexDirection: "column",
2811
3555
  flexGrow: 1,
2812
3556
  alignItems: "center",
2813
3557
  justifyContent: "center",
2814
- children: /* @__PURE__ */ jsxDEV7("text", {
2815
- fg: "#565f89",
3558
+ children: /* @__PURE__ */ jsxDEV10("text", {
3559
+ fg: theme.dim,
2816
3560
  children: "Loading config..."
2817
3561
  }, undefined, false, undefined, this)
2818
3562
  }, undefined, false, undefined, this);
2819
3563
  }
2820
3564
  const nameW = Math.floor((CARD_W - 10) / 2);
2821
3565
  const provW = CARD_W - nameW - 10;
2822
- return /* @__PURE__ */ jsxDEV7("box", {
3566
+ return /* @__PURE__ */ jsxDEV10("box", {
2823
3567
  flexDirection: "column",
2824
3568
  flexGrow: 1,
2825
3569
  alignItems: "center",
2826
3570
  justifyContent: "center",
2827
- children: /* @__PURE__ */ jsxDEV7("box", {
3571
+ children: /* @__PURE__ */ jsxDEV10("box", {
2828
3572
  flexDirection: "column",
2829
3573
  border: true,
2830
3574
  borderStyle: "rounded",
2831
- borderColor: "#292e42",
2832
- backgroundColor: "#16161e",
3575
+ borderColor: theme.border,
3576
+ backgroundColor: theme.background,
2833
3577
  width: CARD_W,
2834
3578
  children: [
2835
- /* @__PURE__ */ jsxDEV7("box", {
3579
+ /* @__PURE__ */ jsxDEV10("box", {
2836
3580
  flexDirection: "row",
2837
3581
  paddingLeft: 2,
2838
3582
  paddingRight: 2,
2839
3583
  paddingTop: 1,
2840
3584
  paddingBottom: 1,
2841
3585
  children: [
2842
- /* @__PURE__ */ jsxDEV7("text", {
2843
- fg: "#7dcfff",
3586
+ /* @__PURE__ */ jsxDEV10("text", {
3587
+ fg: theme.accent,
2844
3588
  children: "Search: "
2845
3589
  }, undefined, false, undefined, this),
2846
- /* @__PURE__ */ jsxDEV7("text", {
2847
- fg: "#c0caf5",
3590
+ /* @__PURE__ */ jsxDEV10("text", {
3591
+ fg: theme.text,
2848
3592
  children: [
2849
3593
  searchQuery,
2850
3594
  "_"
@@ -2852,74 +3596,73 @@ function ModelSelectScreen() {
2852
3596
  }, undefined, true, undefined, this)
2853
3597
  ]
2854
3598
  }, undefined, true, undefined, this),
2855
- /* @__PURE__ */ jsxDEV7("box", {
3599
+ /* @__PURE__ */ jsxDEV10("box", {
2856
3600
  height: 1,
2857
- backgroundColor: "#292e42"
3601
+ backgroundColor: theme.border
2858
3602
  }, undefined, false, undefined, this),
2859
- /* @__PURE__ */ jsxDEV7("scrollbox", {
3603
+ /* @__PURE__ */ jsxDEV10("scrollbox", {
2860
3604
  ref: scrollboxRef,
2861
3605
  height: PAGE_SIZE,
2862
- style: { scrollbarOptions: { showArrows: true, trackOptions: { foregroundColor: "#7aa2f7", backgroundColor: "#292e42" } } },
3606
+ style: { scrollbarOptions: { showArrows: true, trackOptions: { foregroundColor: theme.primary, backgroundColor: theme.border } } },
2863
3607
  children: [
2864
- allRows.length === 0 && /* @__PURE__ */ jsxDEV7("box", {
3608
+ allRows.length === 0 && /* @__PURE__ */ jsxDEV10("box", {
2865
3609
  height: 1,
2866
3610
  paddingLeft: 2,
2867
- children: /* @__PURE__ */ jsxDEV7("text", {
2868
- fg: "#565f89",
3611
+ children: /* @__PURE__ */ jsxDEV10("text", {
3612
+ fg: theme.dim,
2869
3613
  children: "No models found"
2870
3614
  }, undefined, false, undefined, this)
2871
3615
  }, undefined, false, undefined, this),
2872
3616
  (() => {
2873
3617
  let modelCursor = 0;
2874
3618
  return allRows.map((row, i) => {
2875
- if (row.kind === "separator") {
2876
- return /* @__PURE__ */ jsxDEV7("box", {
3619
+ if (row.kind === "separator")
3620
+ return /* @__PURE__ */ jsxDEV10("box", {
2877
3621
  height: 1,
2878
3622
  paddingLeft: 2,
2879
- children: /* @__PURE__ */ jsxDEV7("text", {
2880
- fg: "#565f89",
3623
+ children: /* @__PURE__ */ jsxDEV10("text", {
3624
+ fg: theme.dim,
2881
3625
  children: row.label
2882
3626
  }, undefined, false, undefined, this)
2883
3627
  }, `sep-${i}`, false, undefined, this);
2884
- }
2885
3628
  const localCursor = modelCursor++;
2886
3629
  const isActive = localCursor === cursor;
2887
3630
  const isSel = selected.has(row.model.key);
2888
- let nameFg = "#565f89";
3631
+ let nameFg = theme.dim;
2889
3632
  if (isActive && isSel)
2890
- nameFg = "#7dcfff";
3633
+ nameFg = theme.accent;
2891
3634
  else if (isActive)
2892
- nameFg = "#c0caf5";
3635
+ nameFg = theme.text;
2893
3636
  else if (isSel)
2894
- nameFg = "#9ece6a";
2895
- return /* @__PURE__ */ jsxDEV7("box", {
3637
+ nameFg = theme.success;
3638
+ return /* @__PURE__ */ jsxDEV10("box", {
2896
3639
  height: 1,
2897
3640
  width: "100%",
2898
3641
  flexDirection: "row",
2899
- backgroundColor: isActive ? "#292e42" : "transparent",
3642
+ backgroundColor: isActive ? theme.border : "transparent",
2900
3643
  children: [
2901
- /* @__PURE__ */ jsxDEV7("text", {
2902
- fg: "#565f89",
3644
+ /* @__PURE__ */ jsxDEV10("text", {
3645
+ fg: theme.dim,
2903
3646
  width: 2,
2904
3647
  children: " "
2905
3648
  }, undefined, false, undefined, this),
2906
- /* @__PURE__ */ jsxDEV7("text", {
3649
+ /* @__PURE__ */ jsxDEV10("text", {
2907
3650
  fg: nameFg,
2908
3651
  width: nameW,
2909
3652
  children: row.model.name
2910
3653
  }, undefined, false, undefined, this),
2911
- /* @__PURE__ */ jsxDEV7("text", {
2912
- fg: isActive ? "#7aa2f7" : "#565f89",
3654
+ /* @__PURE__ */ jsxDEV10("text", {
3655
+ fg: isActive ? theme.primary : theme.dim,
2913
3656
  width: provW,
2914
3657
  children: row.model.providerName
2915
3658
  }, undefined, false, undefined, this),
2916
- /* @__PURE__ */ jsxDEV7("text", {
2917
- fg: "#9ece6a",
3659
+ /* @__PURE__ */ jsxDEV10("text", {
3660
+ fg: theme.success,
2918
3661
  width: 2,
2919
3662
  children: isSel ? "\u2713" : " "
2920
3663
  }, undefined, false, undefined, this),
2921
- /* @__PURE__ */ jsxDEV7("text", {
2922
- fg: "#7dcfff",
3664
+ /* @__PURE__ */ jsxDEV10("text", {
3665
+ fg: theme.accent,
2923
3666
  width: 2,
2924
3667
  children: isActive ? "\u203A" : " "
2925
3668
  }, undefined, false, undefined, this)
@@ -2929,19 +3672,19 @@ function ModelSelectScreen() {
2929
3672
  })()
2930
3673
  ]
2931
3674
  }, undefined, true, undefined, this),
2932
- /* @__PURE__ */ jsxDEV7("box", {
3675
+ /* @__PURE__ */ jsxDEV10("box", {
2933
3676
  height: 1,
2934
- backgroundColor: "#292e42"
3677
+ backgroundColor: theme.border
2935
3678
  }, undefined, false, undefined, this),
2936
- /* @__PURE__ */ jsxDEV7("box", {
3679
+ /* @__PURE__ */ jsxDEV10("box", {
2937
3680
  flexDirection: "row",
2938
3681
  paddingLeft: 2,
2939
3682
  paddingRight: 2,
2940
3683
  paddingTop: 1,
2941
3684
  paddingBottom: 1,
2942
3685
  children: [
2943
- /* @__PURE__ */ jsxDEV7("text", {
2944
- fg: "#bb9af7",
3686
+ /* @__PURE__ */ jsxDEV10("text", {
3687
+ fg: theme.secondary,
2945
3688
  children: [
2946
3689
  "Selected: ",
2947
3690
  selected.size,
@@ -2949,16 +3692,16 @@ function ModelSelectScreen() {
2949
3692
  selected.size !== 1 ? "s" : ""
2950
3693
  ]
2951
3694
  }, undefined, true, undefined, this),
2952
- recentCount > 0 && /* @__PURE__ */ jsxDEV7("text", {
2953
- fg: "#565f89",
3695
+ recentCount > 0 && /* @__PURE__ */ jsxDEV10("text", {
3696
+ fg: theme.dim,
2954
3697
  children: [
2955
3698
  " [R] recent (",
2956
3699
  recentCount,
2957
3700
  ")"
2958
3701
  ]
2959
3702
  }, undefined, true, undefined, this),
2960
- /* @__PURE__ */ jsxDEV7("text", {
2961
- fg: "#565f89",
3703
+ /* @__PURE__ */ jsxDEV10("text", {
3704
+ fg: theme.dim,
2962
3705
  children: " [\u2191\u2193/PgUp/PgDn/wheel] scroll"
2963
3706
  }, undefined, false, undefined, this)
2964
3707
  ]
@@ -2969,98 +3712,252 @@ function ModelSelectScreen() {
2969
3712
  }
2970
3713
  var DEBOUNCE_MS = 50;
2971
3714
  var init_ModelSelectScreen = __esm(() => {
3715
+ init_useAppKeyboard();
2972
3716
  init_AppContext();
3717
+ init_ThemeContext();
2973
3718
  init_usePaste();
2974
3719
  });
2975
3720
 
2976
3721
  // src/tui/components/BarChart.tsx
2977
- import { jsxDEV as jsxDEV8 } from "@opentui/react/jsx-dev-runtime";
2978
- function BarChart({ value, max, width, color }) {
2979
- const filled = max === 0 ? 0 : Math.round(value / max * width);
3722
+ import { jsxDEV as jsxDEV11 } from "@opentui/react/jsx-dev-runtime";
3723
+ function BarChart({ value, max, width, color, inverted = false }) {
3724
+ const normalizedValue = inverted && max > 0 ? Math.max(0, max - value) : value;
3725
+ const filled = max === 0 ? 0 : Math.round(normalizedValue / max * width);
2980
3726
  const empty = width - filled;
2981
3727
  const bar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
2982
- return /* @__PURE__ */ jsxDEV8("text", {
3728
+ return /* @__PURE__ */ jsxDEV11("text", {
2983
3729
  fg: color,
2984
3730
  children: bar
2985
3731
  }, undefined, false, undefined, this);
2986
3732
  }
2987
3733
  var init_BarChart = () => {};
2988
3734
 
2989
- // src/tui/components/ResultsTable.tsx
2990
- import { jsxDEV as jsxDEV9 } from "@opentui/react/jsx-dev-runtime";
2991
- function lpad(s, w) {
2992
- return s.length >= w ? s.slice(0, w) : " ".repeat(w - s.length) + s;
2993
- }
2994
- function rpad(s, w) {
2995
- return s.length >= w ? s.slice(0, w) : s + " ".repeat(w - s.length);
2996
- }
2997
- function trunc(s, w) {
2998
- return s.length > w ? s.slice(0, w - 1) + "\u2026" : s;
3735
+ // src/tui/components/GlowBar.tsx
3736
+ import { useState as useState7, useEffect as useEffect5 } from "react";
3737
+ import { engine, Timeline } from "@opentui/core";
3738
+ import { jsxDEV as jsxDEV12 } from "@opentui/react/jsx-dev-runtime";
3739
+ function blendHex(hex, toward, t) {
3740
+ const parse3 = (h) => [
3741
+ parseInt(h.slice(1, 3), 16),
3742
+ parseInt(h.slice(3, 5), 16),
3743
+ parseInt(h.slice(5, 7), 16)
3744
+ ];
3745
+ const [r1, g1, b1] = parse3(hex.length === 7 ? hex : "#ffffff");
3746
+ const [r2, g2, b2] = parse3(toward.length === 7 ? toward : "#ffffff");
3747
+ const r = Math.round(r1 + (r2 - r1) * t);
3748
+ const g = Math.round(g1 + (g2 - g1) * t);
3749
+ const b = Math.round(b1 + (b2 - b1) * t);
3750
+ return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
2999
3751
  }
3000
- function ResultsTable({ results, pendingCount }) {
3001
- const sorted = [...results].sort((a, b) => b.tokensPerSecond - a.tokensPerSecond);
3002
- const C = { rank: 4, model: 18, prov: 12, time: 10, ttft: 8, tps: 11, out: 8, inp: 8, tot: 8 };
3003
- const totalW = C.rank + C.model + C.prov + C.time + C.ttft + C.tps + C.out + C.inp + C.tot + 9;
3752
+ function GlowBar({ done, total, running }) {
3753
+ const theme = useTheme();
3754
+ const [pos, setPos] = useState7(0);
3755
+ useEffect5(() => {
3756
+ const tl = new Timeline({ loop: true, duration: 2200 });
3757
+ const target = { pos: 0 };
3758
+ tl.add(target, { pos: 1, duration: 2200, ease: "linear", onUpdate: (anim) => {
3759
+ setPos(anim.targets[0].pos);
3760
+ } }, 0);
3761
+ tl.play();
3762
+ engine.register(tl);
3763
+ return () => {
3764
+ tl.pause();
3765
+ engine.unregister(tl);
3766
+ };
3767
+ }, []);
3768
+ const filled = Math.round(done / (total || 1) * BAR_W);
3769
+ const barChars = Array.from({ length: BAR_W }, (_, i) => {
3770
+ if (i >= filled)
3771
+ return { ch: "\u2591", fg: theme.border };
3772
+ const phase = pos - i / BAR_W;
3773
+ const intensity = Math.sin(Math.PI * phase * 1.5);
3774
+ const fg = intensity >= 0 ? blendHex(theme.accent, "#ffffff", intensity * 0.55) : blendHex(theme.accent, theme.background, Math.abs(intensity) * 0.5);
3775
+ return { ch: "\u2588", fg };
3776
+ });
3777
+ return /* @__PURE__ */ jsxDEV12("box", {
3778
+ height: 1,
3779
+ flexDirection: "row",
3780
+ paddingLeft: 2,
3781
+ children: [
3782
+ /* @__PURE__ */ jsxDEV12("text", {
3783
+ fg: theme.dim,
3784
+ children: "Benchmarking "
3785
+ }, undefined, false, undefined, this),
3786
+ /* @__PURE__ */ jsxDEV12("text", {
3787
+ fg: theme.accent,
3788
+ children: [
3789
+ done,
3790
+ "/",
3791
+ total,
3792
+ " "
3793
+ ]
3794
+ }, undefined, true, undefined, this),
3795
+ barChars.map((b, i) => /* @__PURE__ */ jsxDEV12("text", {
3796
+ fg: b.fg,
3797
+ children: b.ch
3798
+ }, i, false, undefined, this)),
3799
+ /* @__PURE__ */ jsxDEV12("text", {
3800
+ fg: theme.warning,
3801
+ children: [
3802
+ " ",
3803
+ running,
3804
+ " running..."
3805
+ ]
3806
+ }, undefined, true, undefined, this)
3807
+ ]
3808
+ }, undefined, true, undefined, this);
3809
+ }
3810
+ var BAR_W = 25;
3811
+ var init_GlowBar = __esm(() => {
3812
+ init_ThemeContext();
3813
+ });
3814
+
3815
+ // src/tui/components/ResultsTable.tsx
3816
+ import { jsxDEV as jsxDEV13 } from "@opentui/react/jsx-dev-runtime";
3817
+ function lpad(s, w) {
3818
+ return s.length >= w ? s.slice(0, w) : " ".repeat(w - s.length) + s;
3819
+ }
3820
+ function rpad(s, w) {
3821
+ return s.length >= w ? s.slice(0, w) : s + " ".repeat(w - s.length);
3822
+ }
3823
+ function trunc(s, w) {
3824
+ return s.length > w ? s.slice(0, w - 1) + "\u2026" : s;
3825
+ }
3826
+ function ResultsTable({ results, pendingCount }) {
3827
+ const theme = useTheme();
3828
+ const sorted = [...results].sort((a, b) => b.tokensPerSecond - a.tokensPerSecond);
3829
+ const C = { rank: 4, model: 16, prov: 10, time: 8, ttft: 7, tps: 9, f1000: 8, out: 6, inp: 6, tot: 6 };
3830
+ const totalW = C.rank + C.model + C.prov + C.time + C.ttft + C.tps + C.f1000 + C.out + C.inp + C.tot + 10;
3004
3831
  const sep = "\u2500".repeat(totalW);
3005
- function row(rank, model, prov, time, ttft, tps, out, inp, tot) {
3006
- 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(out, C.out) + " \u2502 " + lpad(inp, C.inp) + " \u2502 " + lpad(tot, C.tot);
3832
+ const maxTps = Math.max(...results.map((r) => r.tokensPerSecond), 0);
3833
+ const minTtft = Math.min(...results.map((r) => r.timeToFirstToken), Infinity);
3834
+ const validF1000s = results.map((r) => r.f1000).filter((f) => f !== Infinity);
3835
+ const minF1000 = validF1000s.length > 0 ? Math.min(...validF1000s) : Infinity;
3836
+ function row(rank, model, prov, time, ttft, tps, f1000, out, inp, tot) {
3837
+ 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);
3007
3838
  }
3008
- const header = row("#", "Model", "Provider", "Time(s)", "TTFT(s)", "Tokens/Sec", "Out", "In", "Total");
3009
- return /* @__PURE__ */ jsxDEV9("box", {
3839
+ const header = row("#", "Model", "Provider", "Time(s)", "TTFT(s)", "Tok/s", "F1000(h)", "Out", "In", "Total");
3840
+ return /* @__PURE__ */ jsxDEV13("box", {
3010
3841
  flexDirection: "column",
3011
3842
  paddingLeft: 1,
3012
3843
  paddingRight: 1,
3013
3844
  children: [
3014
- /* @__PURE__ */ jsxDEV9("box", {
3845
+ /* @__PURE__ */ jsxDEV13("box", {
3015
3846
  height: 1,
3016
- children: /* @__PURE__ */ jsxDEV9("text", {
3017
- fg: "#7dcfff",
3847
+ children: /* @__PURE__ */ jsxDEV13("text", {
3848
+ fg: theme.accent,
3018
3849
  children: header
3019
3850
  }, undefined, false, undefined, this)
3020
3851
  }, undefined, false, undefined, this),
3021
- /* @__PURE__ */ jsxDEV9("box", {
3852
+ /* @__PURE__ */ jsxDEV13("box", {
3022
3853
  height: 1,
3023
- children: /* @__PURE__ */ jsxDEV9("text", {
3024
- fg: "#292e42",
3854
+ children: /* @__PURE__ */ jsxDEV13("text", {
3855
+ fg: theme.border,
3025
3856
  children: sep
3026
3857
  }, undefined, false, undefined, this)
3027
3858
  }, undefined, false, undefined, this),
3028
3859
  sorted.map((r, i) => {
3029
3860
  const rank = `${i + 1}`;
3030
- const timeSec = (r.totalTime / 1000).toFixed(2);
3861
+ const timeSec = (r.totalTime / 1000).toFixed(1);
3031
3862
  const ttftSec = (r.timeToFirstToken / 1000).toFixed(2);
3032
- const tps = r.tokensPerSecond.toFixed(1);
3033
- const outTok = r.tokenCount.toString() + (r.usedEstimateForOutput ? "[e]" : "");
3034
- const inTok = r.promptTokens.toString() + (r.usedEstimateForInput ? "[e]" : "");
3035
- const totTok = r.totalTokens.toString() + (r.usedEstimateForOutput || r.usedEstimateForInput ? "[e]" : "");
3863
+ const tps = r.tokensPerSecond.toFixed(0);
3864
+ const f1000Val = r.f1000 === Infinity ? "\u221E" : r.f1000.toFixed(2);
3865
+ const outTok = r.tokenCount.toString() + (r.usedEstimateForOutput ? "*" : "");
3866
+ const inTok = r.promptTokens.toString() + (r.usedEstimateForInput ? "*" : "");
3867
+ const totTok = r.totalTokens.toString() + (r.usedEstimateForOutput || r.usedEstimateForInput ? "*" : "");
3036
3868
  const hasEst = r.usedEstimateForOutput || r.usedEstimateForInput;
3037
- const line = row(rank, trunc(r.model, C.model), trunc(r.provider, C.prov), timeSec, ttftSec, tps, outTok, inTok, totTok);
3038
- return /* @__PURE__ */ jsxDEV9("box", {
3869
+ const isBestTps = r.tokensPerSecond === maxTps && maxTps > 0;
3870
+ const isBestTtft = r.timeToFirstToken === minTtft;
3871
+ const isBestF1000 = r.f1000 === minF1000 && r.f1000 !== Infinity;
3872
+ return /* @__PURE__ */ jsxDEV13("box", {
3039
3873
  height: 1,
3040
3874
  flexDirection: "row",
3041
3875
  children: [
3042
- /* @__PURE__ */ jsxDEV9("text", {
3043
- fg: "#c0caf5",
3044
- children: line
3876
+ /* @__PURE__ */ jsxDEV13("text", {
3877
+ fg: theme.dim,
3878
+ children: [
3879
+ lpad(rank, C.rank),
3880
+ " \u2502 "
3881
+ ]
3882
+ }, undefined, true, undefined, this),
3883
+ /* @__PURE__ */ jsxDEV13("text", {
3884
+ fg: theme.text,
3885
+ children: [
3886
+ rpad(trunc(r.model, C.model), C.model),
3887
+ " \u2502 "
3888
+ ]
3889
+ }, undefined, true, undefined, this),
3890
+ /* @__PURE__ */ jsxDEV13("text", {
3891
+ fg: theme.dim,
3892
+ children: [
3893
+ rpad(trunc(r.provider, C.prov), C.prov),
3894
+ " \u2502 "
3895
+ ]
3896
+ }, undefined, true, undefined, this),
3897
+ /* @__PURE__ */ jsxDEV13("text", {
3898
+ fg: theme.dim,
3899
+ children: [
3900
+ lpad(timeSec, C.time),
3901
+ " \u2502 "
3902
+ ]
3903
+ }, undefined, true, undefined, this),
3904
+ /* @__PURE__ */ jsxDEV13("text", {
3905
+ fg: isBestTtft ? theme.success : theme.dim,
3906
+ children: [
3907
+ lpad(ttftSec, C.ttft),
3908
+ " \u2502 "
3909
+ ]
3910
+ }, undefined, true, undefined, this),
3911
+ /* @__PURE__ */ jsxDEV13("text", {
3912
+ fg: isBestTps ? theme.success : theme.dim,
3913
+ children: [
3914
+ lpad(tps, C.tps),
3915
+ " \u2502 "
3916
+ ]
3917
+ }, undefined, true, undefined, this),
3918
+ /* @__PURE__ */ jsxDEV13("text", {
3919
+ fg: isBestF1000 ? theme.success : theme.dim,
3920
+ children: [
3921
+ lpad(f1000Val, C.f1000),
3922
+ " \u2502 "
3923
+ ]
3924
+ }, undefined, true, undefined, this),
3925
+ /* @__PURE__ */ jsxDEV13("text", {
3926
+ fg: theme.dim,
3927
+ children: [
3928
+ lpad(outTok, C.out),
3929
+ " \u2502 "
3930
+ ]
3931
+ }, undefined, true, undefined, this),
3932
+ /* @__PURE__ */ jsxDEV13("text", {
3933
+ fg: theme.dim,
3934
+ children: [
3935
+ lpad(inTok, C.inp),
3936
+ " \u2502 "
3937
+ ]
3938
+ }, undefined, true, undefined, this),
3939
+ /* @__PURE__ */ jsxDEV13("text", {
3940
+ fg: theme.dim,
3941
+ children: lpad(totTok, C.tot)
3045
3942
  }, undefined, false, undefined, this),
3046
- hasEst && /* @__PURE__ */ jsxDEV9("text", {
3047
- fg: "#ff9e64",
3943
+ hasEst && /* @__PURE__ */ jsxDEV13("text", {
3944
+ fg: theme.warning,
3048
3945
  children: " [est]"
3049
3946
  }, undefined, false, undefined, this)
3050
3947
  ]
3051
3948
  }, `${r.model}-${r.provider}-${i}`, true, undefined, this);
3052
3949
  }),
3053
- /* @__PURE__ */ jsxDEV9("box", {
3950
+ /* @__PURE__ */ jsxDEV13("box", {
3054
3951
  height: 1,
3055
- children: /* @__PURE__ */ jsxDEV9("text", {
3056
- fg: "#292e42",
3952
+ children: /* @__PURE__ */ jsxDEV13("text", {
3953
+ fg: theme.border,
3057
3954
  children: sep
3058
3955
  }, undefined, false, undefined, this)
3059
3956
  }, undefined, false, undefined, this),
3060
- pendingCount > 0 && /* @__PURE__ */ jsxDEV9("box", {
3957
+ pendingCount > 0 && /* @__PURE__ */ jsxDEV13("box", {
3061
3958
  height: 1,
3062
- children: /* @__PURE__ */ jsxDEV9("text", {
3063
- fg: "#565f89",
3959
+ children: /* @__PURE__ */ jsxDEV13("text", {
3960
+ fg: theme.dim,
3064
3961
  children: [
3065
3962
  " Waiting for ",
3066
3963
  pendingCount,
@@ -3073,13 +3970,13 @@ function ResultsTable({ results, pendingCount }) {
3073
3970
  ]
3074
3971
  }, undefined, true, undefined, this);
3075
3972
  }
3076
- var init_ResultsTable = () => {};
3973
+ var init_ResultsTable = __esm(() => {
3974
+ init_ThemeContext();
3975
+ });
3077
3976
 
3078
3977
  // src/tui/screens/BenchmarkScreen.tsx
3079
- import { useState as useState4, useEffect as useEffect4, useRef as useRef3, useMemo } from "react";
3080
- import { useKeyboard as useKeyboard5 } from "@opentui/react";
3081
- import { engine, Timeline } from "@opentui/core";
3082
- import { jsxDEV as jsxDEV10 } from "@opentui/react/jsx-dev-runtime";
3978
+ import { useState as useState8, useEffect as useEffect6, useRef as useRef4, useMemo } from "react";
3979
+ import { jsxDEV as jsxDEV14 } from "@opentui/react/jsx-dev-runtime";
3083
3980
  function rankBadge(rank) {
3084
3981
  if (rank === 1)
3085
3982
  return "1st";
@@ -3089,35 +3986,16 @@ function rankBadge(rank) {
3089
3986
  return "3rd";
3090
3987
  return `${rank}th`;
3091
3988
  }
3092
- function Divider() {
3093
- return /* @__PURE__ */ jsxDEV10("box", {
3094
- height: 1,
3095
- backgroundColor: "#292e42"
3096
- }, undefined, false, undefined, this);
3097
- }
3098
3989
  function BenchmarkScreen() {
3099
3990
  const { state, dispatch } = useAppContext();
3100
3991
  const navigate = useNavigate();
3101
- const [modelStates, setModelStates] = useState4([]);
3102
- const [spinnerFrame, setSpinnerFrame] = useState4(0);
3103
- const [shimmerPos, setShimmerPos] = useState4(0);
3104
- const [allDone, setAllDone] = useState4(false);
3105
- const spinnerRef = useRef3(null);
3106
- const startedRef = useRef3(false);
3107
- useEffect4(() => {
3108
- const tl = new Timeline({ loop: true, duration: 1400 });
3109
- const target = { pos: 0 };
3110
- tl.add(target, { pos: 1, duration: 1400, ease: "inOutSine", onUpdate: (anim) => {
3111
- setShimmerPos(anim.targets[0].pos);
3112
- } }, 0);
3113
- tl.play();
3114
- engine.register(tl);
3115
- return () => {
3116
- tl.pause();
3117
- engine.unregister(tl);
3118
- };
3119
- }, []);
3120
- useEffect4(() => {
3992
+ const theme = useTheme();
3993
+ const [modelStates, setModelStates] = useState8([]);
3994
+ const [spinnerFrame, setSpinnerFrame] = useState8(0);
3995
+ const [allDone, setAllDone] = useState8(false);
3996
+ const spinnerRef = useRef4(null);
3997
+ const startedRef = useRef4(false);
3998
+ useEffect6(() => {
3121
3999
  if (startedRef.current)
3122
4000
  return;
3123
4001
  startedRef.current = true;
@@ -3176,95 +4054,46 @@ function BenchmarkScreen() {
3176
4054
  const maxTtft = Math.max(...done.map((m) => (m.result?.timeToFirstToken ?? 0) / 1000), 1);
3177
4055
  const tpsRanked = done.slice().sort((a, b) => (b.result?.tokensPerSecond ?? 0) - (a.result?.tokensPerSecond ?? 0));
3178
4056
  const ttftRanked = done.slice().sort((a, b) => (a.result?.timeToFirstToken ?? 0) - (b.result?.timeToFirstToken ?? 0));
4057
+ const f1000Ranked = done.slice().sort((a, b) => (a.result?.f1000 ?? Infinity) - (b.result?.f1000 ?? Infinity));
3179
4058
  const maxTtftForBar = Math.max(...done.map((m) => (m.result?.timeToFirstToken ?? 0) / 1000), 1);
4059
+ const maxF1000 = Math.max(...done.map((m) => m.result?.f1000 ?? 0), 1);
3180
4060
  const doneResults = tpsRanked.map((m) => m.result);
3181
4061
  const pendingCount = running.length + pending.length;
3182
4062
  const allRows = useMemo(() => {
3183
4063
  const rows = [];
3184
4064
  if (!allDone) {
3185
- const total = modelStates.length || 1;
3186
- const filled = Math.round((done.length + errors.length) / total * BAR_W);
3187
- const empty = BAR_W - filled;
3188
- const shimmerCenter = shimmerPos * (BAR_W - 1);
3189
- const shimmerHalf = 1.5;
3190
- const barChars = Array.from({ length: BAR_W }, (_, i) => {
3191
- const isFilled = i < filled;
3192
- const dist = Math.abs(i - shimmerCenter);
3193
- const inWindow = dist <= shimmerHalf;
3194
- const intensity = inWindow ? 1 - dist / shimmerHalf : 0;
3195
- if (isFilled) {
3196
- if (intensity > 0.6)
3197
- return { ch: "\u2588", fg: "#c8eeff" };
3198
- if (intensity > 0)
3199
- return { ch: "\u2593", fg: "#a0d8f0" };
3200
- return { ch: "\u2588", fg: "#4a9abb" };
3201
- } else {
3202
- if (intensity > 0.6)
3203
- return { ch: "\u2591", fg: "#2a3a52" };
3204
- if (intensity > 0)
3205
- return { ch: "\u2591", fg: "#222d40" };
3206
- return { ch: "\u2591", fg: "#1a2030" };
3207
- }
3208
- });
3209
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
3210
- height: 1,
3211
- flexDirection: "row",
3212
- paddingLeft: 2,
3213
- children: [
3214
- /* @__PURE__ */ jsxDEV10("text", {
3215
- fg: "#565f89",
3216
- children: "Benchmarking "
3217
- }, undefined, false, undefined, this),
3218
- /* @__PURE__ */ jsxDEV10("text", {
3219
- fg: "#7dcfff",
3220
- children: [
3221
- done.length + errors.length,
3222
- "/",
3223
- modelStates.length,
3224
- " "
3225
- ]
3226
- }, undefined, true, undefined, this),
3227
- barChars.map((b, i) => /* @__PURE__ */ jsxDEV10("text", {
3228
- fg: b.fg,
3229
- children: b.ch
3230
- }, i, false, undefined, this)),
3231
- /* @__PURE__ */ jsxDEV10("text", {
3232
- fg: "#ff9e64",
3233
- children: [
3234
- " ",
3235
- running.length,
3236
- " running..."
3237
- ]
3238
- }, undefined, true, undefined, this)
3239
- ]
3240
- }, "progress-bar", true, undefined, this));
4065
+ rows.push(/* @__PURE__ */ jsxDEV14(GlowBar, {
4066
+ done: done.length + errors.length,
4067
+ total: modelStates.length,
4068
+ running: running.length
4069
+ }, "progress-bar", false, undefined, this));
3241
4070
  for (const s of modelStates.filter((s2) => s2.status === "done" || s2.status === "error")) {
3242
4071
  if (s.status === "done") {
3243
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4072
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3244
4073
  height: 1,
3245
4074
  flexDirection: "row",
3246
4075
  paddingLeft: 2,
3247
4076
  children: [
3248
- /* @__PURE__ */ jsxDEV10("text", {
3249
- fg: "#9ece6a",
4077
+ /* @__PURE__ */ jsxDEV14("text", {
4078
+ fg: theme.success,
3250
4079
  children: " \u2713 "
3251
4080
  }, undefined, false, undefined, this),
3252
- /* @__PURE__ */ jsxDEV10("text", {
3253
- fg: "#c0caf5",
4081
+ /* @__PURE__ */ jsxDEV14("text", {
4082
+ fg: theme.text,
3254
4083
  children: [
3255
4084
  s.model.name,
3256
4085
  " "
3257
4086
  ]
3258
4087
  }, undefined, true, undefined, this),
3259
- /* @__PURE__ */ jsxDEV10("text", {
3260
- fg: "#7dcfff",
4088
+ /* @__PURE__ */ jsxDEV14("text", {
4089
+ fg: theme.accent,
3261
4090
  children: [
3262
4091
  (s.result?.tokensPerSecond ?? 0).toFixed(1),
3263
4092
  " tok/s "
3264
4093
  ]
3265
4094
  }, undefined, true, undefined, this),
3266
- /* @__PURE__ */ jsxDEV10("text", {
3267
- fg: "#bb9af7",
4095
+ /* @__PURE__ */ jsxDEV14("text", {
4096
+ fg: theme.secondary,
3268
4097
  children: [
3269
4098
  ((s.result?.timeToFirstToken ?? 0) / 1000).toFixed(2),
3270
4099
  "s TTFT"
@@ -3273,213 +4102,310 @@ function BenchmarkScreen() {
3273
4102
  ]
3274
4103
  }, `prog-${s.model.id}-${s.model.providerId}`, true, undefined, this));
3275
4104
  } else {
3276
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4105
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3277
4106
  height: 1,
3278
4107
  flexDirection: "row",
3279
4108
  paddingLeft: 2,
3280
4109
  children: [
3281
- /* @__PURE__ */ jsxDEV10("text", {
3282
- fg: "#f7768e",
4110
+ /* @__PURE__ */ jsxDEV14("text", {
4111
+ fg: theme.error,
3283
4112
  children: " \u2717 "
3284
4113
  }, undefined, false, undefined, this),
3285
- /* @__PURE__ */ jsxDEV10("text", {
3286
- fg: "#c0caf5",
4114
+ /* @__PURE__ */ jsxDEV14("text", {
4115
+ fg: theme.text,
3287
4116
  children: [
3288
4117
  s.model.name,
3289
4118
  " "
3290
4119
  ]
3291
4120
  }, undefined, true, undefined, this),
3292
- /* @__PURE__ */ jsxDEV10("text", {
3293
- fg: "#f7768e",
4121
+ /* @__PURE__ */ jsxDEV14("text", {
4122
+ fg: theme.error,
3294
4123
  children: s.error ?? "error"
3295
4124
  }, undefined, false, undefined, this)
3296
4125
  ]
3297
4126
  }, `prog-${s.model.id}-${s.model.providerId}`, true, undefined, this));
3298
4127
  }
3299
4128
  }
3300
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4129
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3301
4130
  height: 1
3302
4131
  }, "prog-spacer", false, undefined, this));
3303
4132
  }
3304
4133
  if (tpsRanked.length > 0) {
3305
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4134
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3306
4135
  height: 1,
3307
- backgroundColor: "#292e42"
4136
+ backgroundColor: theme.border
3308
4137
  }, "div-tps", false, undefined, this));
3309
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4138
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3310
4139
  height: 1,
3311
4140
  flexDirection: "row",
3312
4141
  paddingLeft: 1,
3313
- children: /* @__PURE__ */ jsxDEV10("text", {
3314
- fg: "#7aa2f7",
4142
+ children: /* @__PURE__ */ jsxDEV14("text", {
4143
+ fg: theme.primary,
3315
4144
  children: " TOKENS/SEC RANKING (higher is better) "
3316
4145
  }, undefined, false, undefined, this)
3317
4146
  }, "hdr-tps", false, undefined, this));
3318
4147
  for (const [i, s] of tpsRanked.entries()) {
3319
4148
  const rank = i + 1;
3320
- const rankFg = rank === 1 ? "#7dcfff" : rank === 2 ? "#bb9af7" : "#565f89";
4149
+ const rankFg = rank === 1 ? theme.accent : rank === 2 ? theme.secondary : theme.dim;
3321
4150
  const tps = s.result?.tokensPerSecond ?? 0;
3322
4151
  const timeSec = (s.result?.totalTime ?? 0) / 1000;
3323
4152
  const badge = rankBadge(rank).padStart(3);
3324
4153
  const modelCol = s.model.name.padEnd(18).slice(0, 18);
3325
4154
  const provCol = s.model.providerName.padEnd(12).slice(0, 12);
3326
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4155
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3327
4156
  height: 1,
3328
4157
  flexDirection: "row",
3329
4158
  paddingLeft: 2,
3330
4159
  children: [
3331
- /* @__PURE__ */ jsxDEV10("text", {
4160
+ /* @__PURE__ */ jsxDEV14("text", {
3332
4161
  fg: rankFg,
3333
4162
  children: [
3334
4163
  badge,
3335
4164
  " "
3336
4165
  ]
3337
4166
  }, undefined, true, undefined, this),
3338
- /* @__PURE__ */ jsxDEV10("text", {
3339
- fg: "#565f89",
4167
+ /* @__PURE__ */ jsxDEV14("text", {
4168
+ fg: theme.dim,
3340
4169
  children: " \u2502 "
3341
4170
  }, undefined, false, undefined, this),
3342
- /* @__PURE__ */ jsxDEV10("text", {
3343
- fg: "#7dcfff",
4171
+ /* @__PURE__ */ jsxDEV14("text", {
4172
+ fg: theme.accent,
3344
4173
  children: [
3345
4174
  tps.toFixed(1).padStart(8),
3346
4175
  " tok/s "
3347
4176
  ]
3348
4177
  }, undefined, true, undefined, this),
3349
- /* @__PURE__ */ jsxDEV10("text", {
3350
- fg: "#565f89",
4178
+ /* @__PURE__ */ jsxDEV14("text", {
4179
+ fg: theme.dim,
3351
4180
  children: " \u2502 "
3352
4181
  }, undefined, false, undefined, this),
3353
- /* @__PURE__ */ jsxDEV10("text", {
3354
- fg: "#bb9af7",
4182
+ /* @__PURE__ */ jsxDEV14("text", {
4183
+ fg: theme.secondary,
3355
4184
  children: [
3356
4185
  timeSec.toFixed(2).padStart(6),
3357
4186
  "s "
3358
4187
  ]
3359
4188
  }, undefined, true, undefined, this),
3360
- /* @__PURE__ */ jsxDEV10("text", {
3361
- fg: "#565f89",
4189
+ /* @__PURE__ */ jsxDEV14("text", {
4190
+ fg: theme.dim,
3362
4191
  children: " \u2502 "
3363
4192
  }, undefined, false, undefined, this),
3364
- /* @__PURE__ */ jsxDEV10("text", {
3365
- fg: "#c0caf5",
4193
+ /* @__PURE__ */ jsxDEV14("text", {
4194
+ fg: theme.text,
3366
4195
  children: [
3367
4196
  modelCol,
3368
4197
  " "
3369
4198
  ]
3370
4199
  }, undefined, true, undefined, this),
3371
- /* @__PURE__ */ jsxDEV10("text", {
3372
- fg: "#565f89",
4200
+ /* @__PURE__ */ jsxDEV14("text", {
4201
+ fg: theme.dim,
3373
4202
  children: [
3374
4203
  provCol,
3375
4204
  " \u2502 "
3376
4205
  ]
3377
4206
  }, undefined, true, undefined, this),
3378
- /* @__PURE__ */ jsxDEV10(BarChart, {
4207
+ /* @__PURE__ */ jsxDEV14(BarChart, {
3379
4208
  value: tps,
3380
4209
  max: maxTps,
3381
- width: BAR_W,
3382
- color: "#7dcfff"
4210
+ width: BAR_W2,
4211
+ color: theme.accent
3383
4212
  }, undefined, false, undefined, this)
3384
4213
  ]
3385
4214
  }, `tps-${s.model.id}-${s.model.providerId}`, true, undefined, this));
3386
4215
  }
3387
4216
  }
3388
4217
  if (ttftRanked.length > 0) {
3389
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4218
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3390
4219
  height: 1,
3391
- backgroundColor: "#292e42"
4220
+ backgroundColor: theme.border
3392
4221
  }, "div-ttft", false, undefined, this));
3393
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4222
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3394
4223
  height: 1,
3395
4224
  flexDirection: "row",
3396
4225
  paddingLeft: 1,
3397
- children: /* @__PURE__ */ jsxDEV10("text", {
3398
- fg: "#7aa2f7",
4226
+ children: /* @__PURE__ */ jsxDEV14("text", {
4227
+ fg: theme.primary,
3399
4228
  children: " TIME TO FIRST TOKEN RANKING (lower is better) "
3400
4229
  }, undefined, false, undefined, this)
3401
4230
  }, "hdr-ttft", false, undefined, this));
3402
4231
  for (const [i, s] of ttftRanked.entries()) {
3403
4232
  const rank = i + 1;
3404
- const rankFg = rank === 1 ? "#7dcfff" : rank === 2 ? "#bb9af7" : "#565f89";
4233
+ const rankFg = rank === 1 ? theme.accent : rank === 2 ? theme.secondary : theme.dim;
3405
4234
  const ttft = (s.result?.timeToFirstToken ?? 0) / 1000;
3406
4235
  const tps = s.result?.tokensPerSecond ?? 0;
3407
4236
  const badge = rankBadge(rank).padStart(3);
3408
4237
  const modelCol = s.model.name.padEnd(18).slice(0, 18);
3409
4238
  const provCol = s.model.providerName.padEnd(12).slice(0, 12);
3410
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4239
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3411
4240
  height: 1,
3412
4241
  flexDirection: "row",
3413
4242
  paddingLeft: 2,
3414
4243
  children: [
3415
- /* @__PURE__ */ jsxDEV10("text", {
4244
+ /* @__PURE__ */ jsxDEV14("text", {
3416
4245
  fg: rankFg,
3417
4246
  children: [
3418
4247
  badge,
3419
4248
  " "
3420
4249
  ]
3421
4250
  }, undefined, true, undefined, this),
3422
- /* @__PURE__ */ jsxDEV10("text", {
3423
- fg: "#565f89",
4251
+ /* @__PURE__ */ jsxDEV14("text", {
4252
+ fg: theme.dim,
3424
4253
  children: " \u2502 "
3425
4254
  }, undefined, false, undefined, this),
3426
- /* @__PURE__ */ jsxDEV10("text", {
3427
- fg: "#bb9af7",
4255
+ /* @__PURE__ */ jsxDEV14("text", {
4256
+ fg: theme.secondary,
3428
4257
  children: [
3429
4258
  ttft.toFixed(2).padStart(7),
3430
4259
  "s "
3431
4260
  ]
3432
4261
  }, undefined, true, undefined, this),
3433
- /* @__PURE__ */ jsxDEV10("text", {
3434
- fg: "#565f89",
4262
+ /* @__PURE__ */ jsxDEV14("text", {
4263
+ fg: theme.dim,
3435
4264
  children: " \u2502 "
3436
4265
  }, undefined, false, undefined, this),
3437
- /* @__PURE__ */ jsxDEV10("text", {
3438
- fg: "#7dcfff",
4266
+ /* @__PURE__ */ jsxDEV14("text", {
4267
+ fg: theme.accent,
3439
4268
  children: [
3440
4269
  tps.toFixed(1).padStart(8),
3441
4270
  " tok/s "
3442
4271
  ]
3443
4272
  }, undefined, true, undefined, this),
3444
- /* @__PURE__ */ jsxDEV10("text", {
3445
- fg: "#565f89",
4273
+ /* @__PURE__ */ jsxDEV14("text", {
4274
+ fg: theme.dim,
3446
4275
  children: " \u2502 "
3447
4276
  }, undefined, false, undefined, this),
3448
- /* @__PURE__ */ jsxDEV10("text", {
3449
- fg: "#c0caf5",
4277
+ /* @__PURE__ */ jsxDEV14("text", {
4278
+ fg: theme.text,
3450
4279
  children: [
3451
4280
  modelCol,
3452
4281
  " "
3453
4282
  ]
3454
4283
  }, undefined, true, undefined, this),
3455
- /* @__PURE__ */ jsxDEV10("text", {
3456
- fg: "#565f89",
4284
+ /* @__PURE__ */ jsxDEV14("text", {
4285
+ fg: theme.dim,
3457
4286
  children: [
3458
4287
  provCol,
3459
4288
  " \u2502 "
3460
4289
  ]
3461
4290
  }, undefined, true, undefined, this),
3462
- /* @__PURE__ */ jsxDEV10(BarChart, {
4291
+ /* @__PURE__ */ jsxDEV14(BarChart, {
3463
4292
  value: ttft,
3464
4293
  max: maxTtftForBar,
3465
- width: BAR_W,
3466
- color: "#bb9af7"
4294
+ width: BAR_W2,
4295
+ color: theme.secondary
3467
4296
  }, undefined, false, undefined, this)
3468
4297
  ]
3469
4298
  }, `ttft-${s.model.id}-${s.model.providerId}`, true, undefined, this));
3470
4299
  }
3471
4300
  }
4301
+ if (f1000Ranked.length > 0) {
4302
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
4303
+ height: 1,
4304
+ backgroundColor: theme.border
4305
+ }, "div-f1000", false, undefined, this));
4306
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
4307
+ height: 1,
4308
+ flexDirection: "row",
4309
+ paddingLeft: 1,
4310
+ children: /* @__PURE__ */ jsxDEV14("text", {
4311
+ fg: theme.primary,
4312
+ children: " F1000 RANKING - First to 1000 Requests (lower is better) "
4313
+ }, undefined, false, undefined, this)
4314
+ }, "hdr-f1000", false, undefined, this));
4315
+ for (const [i, s] of f1000Ranked.entries()) {
4316
+ const rank = i + 1;
4317
+ const rankFg = rank === 1 ? theme.accent : rank === 2 ? theme.secondary : theme.dim;
4318
+ const f1000 = s.result?.f1000 ?? Infinity;
4319
+ const f1000Str = f1000 === Infinity ? "\u221E" : f1000.toFixed(2);
4320
+ const ttft = (s.result?.timeToFirstToken ?? 0) / 1000;
4321
+ const tps = s.result?.tokensPerSecond ?? 0;
4322
+ const badge = rankBadge(rank).padStart(3);
4323
+ const modelCol = s.model.name.padEnd(18).slice(0, 18);
4324
+ const provCol = s.model.providerName.padEnd(12).slice(0, 12);
4325
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
4326
+ height: 1,
4327
+ flexDirection: "row",
4328
+ paddingLeft: 2,
4329
+ children: [
4330
+ /* @__PURE__ */ jsxDEV14("text", {
4331
+ fg: rankFg,
4332
+ children: [
4333
+ badge,
4334
+ " "
4335
+ ]
4336
+ }, undefined, true, undefined, this),
4337
+ /* @__PURE__ */ jsxDEV14("text", {
4338
+ fg: theme.dim,
4339
+ children: " \u2502 "
4340
+ }, undefined, false, undefined, this),
4341
+ /* @__PURE__ */ jsxDEV14("text", {
4342
+ fg: theme.primary,
4343
+ children: [
4344
+ f1000Str.padStart(7),
4345
+ "h "
4346
+ ]
4347
+ }, undefined, true, undefined, this),
4348
+ /* @__PURE__ */ jsxDEV14("text", {
4349
+ fg: theme.dim,
4350
+ children: " \u2502 "
4351
+ }, undefined, false, undefined, this),
4352
+ /* @__PURE__ */ jsxDEV14("text", {
4353
+ fg: theme.secondary,
4354
+ children: [
4355
+ ttft.toFixed(2).padStart(5),
4356
+ "s "
4357
+ ]
4358
+ }, undefined, true, undefined, this),
4359
+ /* @__PURE__ */ jsxDEV14("text", {
4360
+ fg: theme.dim,
4361
+ children: " \u2502 "
4362
+ }, undefined, false, undefined, this),
4363
+ /* @__PURE__ */ jsxDEV14("text", {
4364
+ fg: theme.accent,
4365
+ children: [
4366
+ tps.toFixed(0).padStart(5),
4367
+ " tok/s "
4368
+ ]
4369
+ }, undefined, true, undefined, this),
4370
+ /* @__PURE__ */ jsxDEV14("text", {
4371
+ fg: theme.dim,
4372
+ children: " \u2502 "
4373
+ }, undefined, false, undefined, this),
4374
+ /* @__PURE__ */ jsxDEV14("text", {
4375
+ fg: theme.text,
4376
+ children: [
4377
+ modelCol,
4378
+ " "
4379
+ ]
4380
+ }, undefined, true, undefined, this),
4381
+ /* @__PURE__ */ jsxDEV14("text", {
4382
+ fg: theme.dim,
4383
+ children: [
4384
+ provCol,
4385
+ " \u2502 "
4386
+ ]
4387
+ }, undefined, true, undefined, this),
4388
+ /* @__PURE__ */ jsxDEV14(BarChart, {
4389
+ value: f1000 === Infinity ? maxF1000 : f1000,
4390
+ max: maxF1000,
4391
+ width: BAR_W2,
4392
+ color: theme.primary
4393
+ }, undefined, false, undefined, this)
4394
+ ]
4395
+ }, `f1000-${s.model.id}-${s.model.providerId}`, true, undefined, this));
4396
+ }
4397
+ }
3472
4398
  if (allDone && errors.length > 0) {
3473
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4399
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3474
4400
  height: 1,
3475
- backgroundColor: "#292e42"
4401
+ backgroundColor: theme.border
3476
4402
  }, "div-errors", false, undefined, this));
3477
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4403
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3478
4404
  height: 1,
3479
4405
  flexDirection: "row",
3480
4406
  paddingLeft: 1,
3481
- children: /* @__PURE__ */ jsxDEV10("text", {
3482
- fg: "#f7768e",
4407
+ children: /* @__PURE__ */ jsxDEV14("text", {
4408
+ fg: theme.error,
3483
4409
  children: [
3484
4410
  " FAILED (",
3485
4411
  errors.length,
@@ -3488,29 +4414,29 @@ function BenchmarkScreen() {
3488
4414
  }, undefined, true, undefined, this)
3489
4415
  }, "hdr-errors", false, undefined, this));
3490
4416
  for (const s of errors) {
3491
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4417
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3492
4418
  flexDirection: "column",
3493
4419
  paddingLeft: 2,
3494
4420
  paddingTop: 1,
3495
4421
  paddingBottom: 1,
3496
4422
  children: [
3497
- /* @__PURE__ */ jsxDEV10("box", {
4423
+ /* @__PURE__ */ jsxDEV14("box", {
3498
4424
  height: 1,
3499
4425
  flexDirection: "row",
3500
4426
  children: [
3501
- /* @__PURE__ */ jsxDEV10("text", {
3502
- fg: "#f7768e",
4427
+ /* @__PURE__ */ jsxDEV14("text", {
4428
+ fg: theme.error,
3503
4429
  children: "\u2717 "
3504
4430
  }, undefined, false, undefined, this),
3505
- /* @__PURE__ */ jsxDEV10("text", {
3506
- fg: "#c0caf5",
4431
+ /* @__PURE__ */ jsxDEV14("text", {
4432
+ fg: theme.text,
3507
4433
  children: [
3508
4434
  s.model.name,
3509
4435
  " "
3510
4436
  ]
3511
4437
  }, undefined, true, undefined, this),
3512
- /* @__PURE__ */ jsxDEV10("text", {
3513
- fg: "#565f89",
4438
+ /* @__PURE__ */ jsxDEV14("text", {
4439
+ fg: theme.dim,
3514
4440
  children: [
3515
4441
  "(",
3516
4442
  s.model.providerName,
@@ -3519,11 +4445,11 @@ function BenchmarkScreen() {
3519
4445
  }, undefined, true, undefined, this)
3520
4446
  ]
3521
4447
  }, undefined, true, undefined, this),
3522
- /* @__PURE__ */ jsxDEV10("box", {
4448
+ /* @__PURE__ */ jsxDEV14("box", {
3523
4449
  height: 1,
3524
4450
  paddingLeft: 3,
3525
- children: /* @__PURE__ */ jsxDEV10("text", {
3526
- fg: "#f7768e",
4451
+ children: /* @__PURE__ */ jsxDEV14("text", {
4452
+ fg: theme.error,
3527
4453
  children: s.error ?? "Unknown error"
3528
4454
  }, undefined, false, undefined, this)
3529
4455
  }, undefined, false, undefined, this)
@@ -3531,40 +4457,40 @@ function BenchmarkScreen() {
3531
4457
  }, `err-${s.model.id}-${s.model.providerId}`, true, undefined, this));
3532
4458
  }
3533
4459
  }
3534
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4460
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3535
4461
  height: 1,
3536
- backgroundColor: "#292e42"
4462
+ backgroundColor: theme.border
3537
4463
  }, "div-results", false, undefined, this));
3538
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4464
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3539
4465
  height: 1,
3540
4466
  flexDirection: "row",
3541
4467
  paddingLeft: 1,
3542
- children: /* @__PURE__ */ jsxDEV10("text", {
3543
- fg: "#7aa2f7",
4468
+ children: /* @__PURE__ */ jsxDEV14("text", {
4469
+ fg: theme.primary,
3544
4470
  children: " RESULTS "
3545
4471
  }, undefined, false, undefined, this)
3546
4472
  }, "hdr-results", false, undefined, this));
3547
4473
  if (doneResults.length > 0) {
3548
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4474
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3549
4475
  flexDirection: "column",
3550
- children: /* @__PURE__ */ jsxDEV10(ResultsTable, {
4476
+ children: /* @__PURE__ */ jsxDEV14(ResultsTable, {
3551
4477
  results: doneResults,
3552
4478
  pendingCount
3553
4479
  }, undefined, false, undefined, this)
3554
4480
  }, "results-table", false, undefined, this));
3555
4481
  } else {
3556
- rows.push(/* @__PURE__ */ jsxDEV10("box", {
4482
+ rows.push(/* @__PURE__ */ jsxDEV14("box", {
3557
4483
  paddingLeft: 2,
3558
4484
  paddingBottom: 1,
3559
- children: /* @__PURE__ */ jsxDEV10("text", {
3560
- fg: "#565f89",
4485
+ children: /* @__PURE__ */ jsxDEV14("text", {
4486
+ fg: theme.dim,
3561
4487
  children: "No results yet..."
3562
4488
  }, undefined, false, undefined, this)
3563
4489
  }, "results-empty", false, undefined, this));
3564
4490
  }
3565
4491
  return rows;
3566
- }, [modelStates, allDone, shimmerPos, tpsRanked, ttftRanked, doneResults, pendingCount, maxTps, maxTtftForBar]);
3567
- useKeyboard5((key) => {
4492
+ }, [modelStates, allDone, tpsRanked, ttftRanked, f1000Ranked, doneResults, pendingCount, maxTps, maxTtftForBar, maxF1000, theme]);
4493
+ useAppKeyboard((key) => {
3568
4494
  if (!allDone)
3569
4495
  return;
3570
4496
  if (key.name === "q" || key.name === "return" || key.name === "enter") {
@@ -3572,94 +4498,97 @@ function BenchmarkScreen() {
3572
4498
  navigate("main-menu");
3573
4499
  }
3574
4500
  });
3575
- const statusLine = allDone ? /* @__PURE__ */ jsxDEV10("box", {
4501
+ const statusLine = allDone ? /* @__PURE__ */ jsxDEV14("box", {
3576
4502
  flexDirection: "row",
3577
4503
  children: [
3578
- /* @__PURE__ */ jsxDEV10("text", {
3579
- fg: "#9ece6a",
4504
+ /* @__PURE__ */ jsxDEV14("text", {
4505
+ fg: theme.success,
3580
4506
  children: "All done! [Enter]/[Q] return [\u2191\u2193/PgUp/PgDn/wheel] scroll"
3581
4507
  }, undefined, false, undefined, this),
3582
- state.logMode && state.logPath && /* @__PURE__ */ jsxDEV10("text", {
3583
- fg: "#565f89",
4508
+ state.logMode && state.logPath && /* @__PURE__ */ jsxDEV14("text", {
4509
+ fg: theme.dim,
3584
4510
  children: [
3585
4511
  " log: ",
3586
4512
  state.logPath
3587
4513
  ]
3588
4514
  }, undefined, true, undefined, this)
3589
4515
  ]
3590
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV10("box", {
4516
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV14("box", {
3591
4517
  flexDirection: "row",
3592
4518
  children: [
3593
- running.length > 0 && /* @__PURE__ */ jsxDEV10("text", {
3594
- fg: "#ff9e64",
4519
+ running.length > 0 && /* @__PURE__ */ jsxDEV14("text", {
4520
+ fg: theme.warning,
3595
4521
  children: [
3596
4522
  running.length,
3597
4523
  " running "
3598
4524
  ]
3599
4525
  }, undefined, true, undefined, this),
3600
- done.length > 0 && /* @__PURE__ */ jsxDEV10("text", {
3601
- fg: "#9ece6a",
4526
+ done.length > 0 && /* @__PURE__ */ jsxDEV14("text", {
4527
+ fg: theme.success,
3602
4528
  children: [
3603
4529
  done.length,
3604
4530
  " done "
3605
4531
  ]
3606
4532
  }, undefined, true, undefined, this),
3607
- errors.length > 0 && /* @__PURE__ */ jsxDEV10("text", {
3608
- fg: "#f7768e",
4533
+ errors.length > 0 && /* @__PURE__ */ jsxDEV14("text", {
4534
+ fg: theme.error,
3609
4535
  children: [
3610
4536
  errors.length,
3611
4537
  " errors "
3612
4538
  ]
3613
4539
  }, undefined, true, undefined, this),
3614
- /* @__PURE__ */ jsxDEV10("text", {
3615
- fg: "#565f89",
4540
+ /* @__PURE__ */ jsxDEV14("text", {
4541
+ fg: theme.dim,
3616
4542
  children: "[\u2191\u2193/wheel] scroll"
3617
4543
  }, undefined, false, undefined, this)
3618
4544
  ]
3619
4545
  }, undefined, true, undefined, this);
3620
- return /* @__PURE__ */ jsxDEV10("box", {
4546
+ return /* @__PURE__ */ jsxDEV14("box", {
3621
4547
  flexDirection: "column",
3622
4548
  flexGrow: 1,
3623
4549
  padding: 1,
3624
4550
  children: [
3625
- /* @__PURE__ */ jsxDEV10("box", {
4551
+ /* @__PURE__ */ jsxDEV14("box", {
3626
4552
  alignItems: "center",
3627
4553
  justifyContent: "center",
3628
4554
  marginBottom: 1,
3629
- children: /* @__PURE__ */ jsxDEV10("ascii-font", {
4555
+ children: /* @__PURE__ */ jsxDEV14("ascii-font", {
3630
4556
  text: "AI-SPEEDOMETER",
3631
4557
  font: "tiny",
3632
- color: "#7aa2f7"
4558
+ color: theme.primary
3633
4559
  }, undefined, false, undefined, this)
3634
4560
  }, undefined, false, undefined, this),
3635
- /* @__PURE__ */ jsxDEV10("box", {
4561
+ /* @__PURE__ */ jsxDEV14("box", {
3636
4562
  flexDirection: "column",
3637
4563
  border: true,
3638
4564
  borderStyle: "rounded",
3639
- borderColor: "#292e42",
3640
- backgroundColor: "#16161e",
4565
+ borderColor: theme.border,
4566
+ backgroundColor: theme.background,
3641
4567
  flexGrow: 1,
3642
4568
  children: [
3643
- /* @__PURE__ */ jsxDEV10("box", {
4569
+ /* @__PURE__ */ jsxDEV14("box", {
3644
4570
  height: 1,
3645
4571
  paddingLeft: 2,
3646
4572
  paddingRight: 2,
3647
4573
  flexDirection: "row",
3648
4574
  children: [
3649
- /* @__PURE__ */ jsxDEV10("text", {
3650
- fg: "#7dcfff",
4575
+ /* @__PURE__ */ jsxDEV14("text", {
4576
+ fg: theme.accent,
3651
4577
  children: "LIVE BENCHMARK "
3652
4578
  }, undefined, false, undefined, this),
3653
4579
  statusLine
3654
4580
  ]
3655
4581
  }, undefined, true, undefined, this),
3656
- /* @__PURE__ */ jsxDEV10(Divider, {}, undefined, false, undefined, this),
3657
- /* @__PURE__ */ jsxDEV10("scrollbox", {
4582
+ /* @__PURE__ */ jsxDEV14("box", {
4583
+ height: 1,
4584
+ backgroundColor: theme.border
4585
+ }, undefined, false, undefined, this),
4586
+ /* @__PURE__ */ jsxDEV14("scrollbox", {
3658
4587
  focused: true,
3659
4588
  flexGrow: 1,
3660
4589
  stickyScroll: true,
3661
4590
  stickyStart: "bottom",
3662
- style: { scrollbarOptions: { showArrows: true, trackOptions: { foregroundColor: "#7aa2f7", backgroundColor: "#292e42" } } },
4591
+ style: { scrollbarOptions: { showArrows: true, trackOptions: { foregroundColor: theme.primary, backgroundColor: theme.border } } },
3663
4592
  children: allRows
3664
4593
  }, undefined, false, undefined, this)
3665
4594
  ]
@@ -3667,36 +4596,40 @@ function BenchmarkScreen() {
3667
4596
  ]
3668
4597
  }, undefined, true, undefined, this);
3669
4598
  }
3670
- var BAR_W = 25;
4599
+ var BAR_W2 = 25;
3671
4600
  var init_BenchmarkScreen = __esm(() => {
4601
+ init_useAppKeyboard();
3672
4602
  init_AppContext();
4603
+ init_ThemeContext();
3673
4604
  init_BarChart();
4605
+ init_GlowBar();
3674
4606
  init_ResultsTable();
3675
4607
  });
3676
4608
 
3677
4609
  // src/tui/screens/AddVerifiedScreen.tsx
3678
- import { useState as useState5, useEffect as useEffect5, useRef as useRef4 } from "react";
3679
- import { useKeyboard as useKeyboard6, useTerminalDimensions as useTerminalDimensions2 } from "@opentui/react";
3680
- import { jsxDEV as jsxDEV11 } from "@opentui/react/jsx-dev-runtime";
4610
+ import { useState as useState9, useEffect as useEffect7, useRef as useRef5 } from "react";
4611
+ import { useTerminalDimensions as useTerminalDimensions2 } from "@opentui/react";
4612
+ import { jsxDEV as jsxDEV15 } from "@opentui/react/jsx-dev-runtime";
3681
4613
  function AddVerifiedScreen() {
3682
4614
  const { dispatch } = useAppContext();
3683
4615
  const navigate = useNavigate();
4616
+ const theme = useTheme();
3684
4617
  const { height, width } = useTerminalDimensions2();
3685
4618
  const PAGE_SIZE = Math.max(3, height - 16);
3686
4619
  const CARD_W = Math.min(62, width - 4);
3687
- const [step, setStep] = useState5("browse");
3688
- const [allProviders, setAllProviders] = useState5([]);
3689
- const [filtered, setFiltered] = useState5([]);
3690
- const [cursor, setCursor] = useState5(0);
3691
- const [searchQuery, setSearchQuery] = useState5("");
3692
- const scrollboxRef = useRef4(null);
3693
- const [selectedProvider, setSelectedProvider] = useState5(null);
3694
- const [apiKey, setApiKey] = useState5("");
3695
- const [saving, setSaving] = useState5(false);
3696
- const [saveError, setSaveError] = useState5("");
3697
- const [saveSuccess, setSaveSuccess] = useState5(false);
3698
- const [loadError, setLoadError] = useState5("");
3699
- useEffect5(() => {
4620
+ const [step, setStep] = useState9("browse");
4621
+ const [allProviders, setAllProviders] = useState9([]);
4622
+ const [filtered, setFiltered] = useState9([]);
4623
+ const [cursor, setCursor] = useState9(0);
4624
+ const [searchQuery, setSearchQuery] = useState9("");
4625
+ const scrollboxRef = useRef5(null);
4626
+ const [selectedProvider, setSelectedProvider] = useState9(null);
4627
+ const [apiKey, setApiKey] = useState9("");
4628
+ const [saving, setSaving] = useState9(false);
4629
+ const [saveError, setSaveError] = useState9("");
4630
+ const [saveSuccess, setSaveSuccess] = useState9(false);
4631
+ const [loadError, setLoadError] = useState9("");
4632
+ useEffect7(() => {
3700
4633
  async function load() {
3701
4634
  try {
3702
4635
  const { getAllProviders: getAllProviders2 } = await Promise.resolve().then(() => (init_models_dev(), exports_models_dev));
@@ -3709,7 +4642,7 @@ function AddVerifiedScreen() {
3709
4642
  }
3710
4643
  load();
3711
4644
  }, []);
3712
- useEffect5(() => {
4645
+ useEffect7(() => {
3713
4646
  if (!searchQuery) {
3714
4647
  setFiltered(allProviders);
3715
4648
  } else {
@@ -3718,7 +4651,7 @@ function AddVerifiedScreen() {
3718
4651
  }
3719
4652
  setCursor(0);
3720
4653
  }, [searchQuery, allProviders]);
3721
- useEffect5(() => {
4654
+ useEffect7(() => {
3722
4655
  const sb = scrollboxRef.current;
3723
4656
  if (!sb)
3724
4657
  return;
@@ -3737,7 +4670,7 @@ function AddVerifiedScreen() {
3737
4670
  setSaveError("");
3738
4671
  try {
3739
4672
  const { addApiKey: addApiKey2 } = await Promise.resolve().then(() => (init_opencode_integration(), exports_opencode_integration));
3740
- const { addVerifiedProvider: addVerifiedProvider2, getVerifiedProvidersFromConfig: getVerifiedProvidersFromConfig2 } = await Promise.resolve().then(() => (init_ai_config(), exports_ai_config));
4673
+ const { addVerifiedProvider: addVerifiedProvider2 } = await Promise.resolve().then(() => (init_ai_config(), exports_ai_config));
3741
4674
  await addApiKey2(selectedProvider.id, apiKey.trim());
3742
4675
  await addVerifiedProvider2(selectedProvider.id, apiKey.trim());
3743
4676
  const { getAllAvailableProviders: getAllAvailableProviders2 } = await Promise.resolve().then(() => (init_opencode_integration(), exports_opencode_integration));
@@ -3757,7 +4690,7 @@ function AddVerifiedScreen() {
3757
4690
  else if (step === "confirm")
3758
4691
  setApiKey((k) => k + clean);
3759
4692
  });
3760
- useKeyboard6((key) => {
4693
+ useAppKeyboard((key) => {
3761
4694
  if (step === "browse") {
3762
4695
  if (key.name === "escape" || key.sequence === "q" || key.sequence === "Q") {
3763
4696
  navigate("model-menu");
@@ -3801,9 +4734,8 @@ function AddVerifiedScreen() {
3801
4734
  }
3802
4735
  if (step === "confirm") {
3803
4736
  if (saveSuccess) {
3804
- if (key.name === "return" || key.name === "enter") {
4737
+ if (key.name === "return" || key.name === "enter")
3805
4738
  navigate("model-menu");
3806
- }
3807
4739
  return;
3808
4740
  }
3809
4741
  if (saving)
@@ -3826,91 +4758,91 @@ function AddVerifiedScreen() {
3826
4758
  }
3827
4759
  });
3828
4760
  if (step === "confirm" && selectedProvider) {
3829
- return /* @__PURE__ */ jsxDEV11("box", {
4761
+ return /* @__PURE__ */ jsxDEV15("box", {
3830
4762
  flexDirection: "column",
3831
4763
  flexGrow: 1,
3832
4764
  alignItems: "center",
3833
4765
  justifyContent: "center",
3834
- children: /* @__PURE__ */ jsxDEV11("box", {
4766
+ children: /* @__PURE__ */ jsxDEV15("box", {
3835
4767
  flexDirection: "column",
3836
4768
  border: true,
3837
4769
  borderStyle: "rounded",
3838
- borderColor: "#292e42",
3839
- backgroundColor: "#16161e",
4770
+ borderColor: theme.border,
4771
+ backgroundColor: theme.background,
3840
4772
  width: CARD_W,
3841
4773
  children: [
3842
- /* @__PURE__ */ jsxDEV11("box", {
4774
+ /* @__PURE__ */ jsxDEV15("box", {
3843
4775
  height: 1,
3844
4776
  paddingLeft: 2,
3845
4777
  paddingTop: 1,
3846
- children: /* @__PURE__ */ jsxDEV11("text", {
3847
- fg: "#7dcfff",
4778
+ children: /* @__PURE__ */ jsxDEV15("text", {
4779
+ fg: theme.accent,
3848
4780
  children: "Add Verified Provider"
3849
4781
  }, undefined, false, undefined, this)
3850
4782
  }, undefined, false, undefined, this),
3851
- /* @__PURE__ */ jsxDEV11("box", {
4783
+ /* @__PURE__ */ jsxDEV15("box", {
3852
4784
  height: 1,
3853
- backgroundColor: "#292e42"
4785
+ backgroundColor: theme.border
3854
4786
  }, undefined, false, undefined, this),
3855
- /* @__PURE__ */ jsxDEV11("box", {
4787
+ /* @__PURE__ */ jsxDEV15("box", {
3856
4788
  flexDirection: "column",
3857
4789
  paddingLeft: 2,
3858
4790
  paddingRight: 2,
3859
4791
  paddingTop: 1,
3860
4792
  paddingBottom: 1,
3861
4793
  children: [
3862
- /* @__PURE__ */ jsxDEV11("box", {
4794
+ /* @__PURE__ */ jsxDEV15("box", {
3863
4795
  height: 1,
3864
4796
  flexDirection: "row",
3865
4797
  children: [
3866
- /* @__PURE__ */ jsxDEV11("text", {
3867
- fg: "#7aa2f7",
4798
+ /* @__PURE__ */ jsxDEV15("text", {
4799
+ fg: theme.primary,
3868
4800
  children: "Provider: "
3869
4801
  }, undefined, false, undefined, this),
3870
- /* @__PURE__ */ jsxDEV11("text", {
3871
- fg: "#c0caf5",
4802
+ /* @__PURE__ */ jsxDEV15("text", {
4803
+ fg: theme.text,
3872
4804
  children: selectedProvider.name
3873
4805
  }, undefined, false, undefined, this)
3874
4806
  ]
3875
4807
  }, undefined, true, undefined, this),
3876
- /* @__PURE__ */ jsxDEV11("box", {
4808
+ /* @__PURE__ */ jsxDEV15("box", {
3877
4809
  height: 1,
3878
4810
  flexDirection: "row",
3879
4811
  children: [
3880
- /* @__PURE__ */ jsxDEV11("text", {
3881
- fg: "#565f89",
4812
+ /* @__PURE__ */ jsxDEV15("text", {
4813
+ fg: theme.dim,
3882
4814
  children: "Type: "
3883
4815
  }, undefined, false, undefined, this),
3884
- /* @__PURE__ */ jsxDEV11("text", {
3885
- fg: "#565f89",
4816
+ /* @__PURE__ */ jsxDEV15("text", {
4817
+ fg: theme.dim,
3886
4818
  children: selectedProvider.type
3887
4819
  }, undefined, false, undefined, this)
3888
4820
  ]
3889
4821
  }, undefined, true, undefined, this),
3890
- /* @__PURE__ */ jsxDEV11("box", {
4822
+ /* @__PURE__ */ jsxDEV15("box", {
3891
4823
  height: 1,
3892
4824
  flexDirection: "row",
3893
4825
  children: [
3894
- /* @__PURE__ */ jsxDEV11("text", {
3895
- fg: "#565f89",
4826
+ /* @__PURE__ */ jsxDEV15("text", {
4827
+ fg: theme.dim,
3896
4828
  children: "URL: "
3897
4829
  }, undefined, false, undefined, this),
3898
- /* @__PURE__ */ jsxDEV11("text", {
3899
- fg: "#565f89",
4830
+ /* @__PURE__ */ jsxDEV15("text", {
4831
+ fg: theme.dim,
3900
4832
  children: selectedProvider.baseUrl
3901
4833
  }, undefined, false, undefined, this)
3902
4834
  ]
3903
4835
  }, undefined, true, undefined, this),
3904
- /* @__PURE__ */ jsxDEV11("box", {
4836
+ /* @__PURE__ */ jsxDEV15("box", {
3905
4837
  height: 1,
3906
4838
  flexDirection: "row",
3907
4839
  children: [
3908
- /* @__PURE__ */ jsxDEV11("text", {
3909
- fg: "#565f89",
4840
+ /* @__PURE__ */ jsxDEV15("text", {
4841
+ fg: theme.dim,
3910
4842
  children: "Models: "
3911
4843
  }, undefined, false, undefined, this),
3912
- /* @__PURE__ */ jsxDEV11("text", {
3913
- fg: "#565f89",
4844
+ /* @__PURE__ */ jsxDEV15("text", {
4845
+ fg: theme.dim,
3914
4846
  children: [
3915
4847
  selectedProvider.models.length,
3916
4848
  " available"
@@ -3920,21 +4852,21 @@ function AddVerifiedScreen() {
3920
4852
  }, undefined, true, undefined, this)
3921
4853
  ]
3922
4854
  }, undefined, true, undefined, this),
3923
- /* @__PURE__ */ jsxDEV11("box", {
4855
+ /* @__PURE__ */ jsxDEV15("box", {
3924
4856
  height: 1,
3925
- backgroundColor: "#292e42"
4857
+ backgroundColor: theme.border
3926
4858
  }, undefined, false, undefined, this),
3927
- saveSuccess ? /* @__PURE__ */ jsxDEV11("box", {
4859
+ saveSuccess ? /* @__PURE__ */ jsxDEV15("box", {
3928
4860
  flexDirection: "column",
3929
4861
  paddingLeft: 2,
3930
4862
  paddingRight: 2,
3931
4863
  paddingTop: 1,
3932
4864
  paddingBottom: 1,
3933
4865
  children: [
3934
- /* @__PURE__ */ jsxDEV11("box", {
4866
+ /* @__PURE__ */ jsxDEV15("box", {
3935
4867
  height: 1,
3936
- children: /* @__PURE__ */ jsxDEV11("text", {
3937
- fg: "#9ece6a",
4868
+ children: /* @__PURE__ */ jsxDEV15("text", {
4869
+ fg: theme.success,
3938
4870
  children: [
3939
4871
  "Provider added! ",
3940
4872
  selectedProvider.models.length,
@@ -3942,31 +4874,31 @@ function AddVerifiedScreen() {
3942
4874
  ]
3943
4875
  }, undefined, true, undefined, this)
3944
4876
  }, undefined, false, undefined, this),
3945
- /* @__PURE__ */ jsxDEV11("box", {
4877
+ /* @__PURE__ */ jsxDEV15("box", {
3946
4878
  height: 1,
3947
- children: /* @__PURE__ */ jsxDEV11("text", {
3948
- fg: "#565f89",
4879
+ children: /* @__PURE__ */ jsxDEV15("text", {
4880
+ fg: theme.dim,
3949
4881
  children: "Press [Enter] to return"
3950
4882
  }, undefined, false, undefined, this)
3951
4883
  }, undefined, false, undefined, this)
3952
4884
  ]
3953
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV11("box", {
4885
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV15("box", {
3954
4886
  flexDirection: "column",
3955
4887
  paddingLeft: 2,
3956
4888
  paddingRight: 2,
3957
4889
  paddingTop: 1,
3958
4890
  paddingBottom: 1,
3959
4891
  children: [
3960
- /* @__PURE__ */ jsxDEV11("box", {
4892
+ /* @__PURE__ */ jsxDEV15("box", {
3961
4893
  height: 1,
3962
4894
  flexDirection: "row",
3963
4895
  children: [
3964
- /* @__PURE__ */ jsxDEV11("text", {
3965
- fg: "#7dcfff",
4896
+ /* @__PURE__ */ jsxDEV15("text", {
4897
+ fg: theme.accent,
3966
4898
  children: "API Key: "
3967
4899
  }, undefined, false, undefined, this),
3968
- /* @__PURE__ */ jsxDEV11("text", {
3969
- fg: "#c0caf5",
4900
+ /* @__PURE__ */ jsxDEV15("text", {
4901
+ fg: theme.text,
3970
4902
  children: [
3971
4903
  apiKey,
3972
4904
  "_"
@@ -3974,26 +4906,26 @@ function AddVerifiedScreen() {
3974
4906
  }, undefined, true, undefined, this)
3975
4907
  ]
3976
4908
  }, undefined, true, undefined, this),
3977
- saveError ? /* @__PURE__ */ jsxDEV11("box", {
4909
+ saveError ? /* @__PURE__ */ jsxDEV15("box", {
3978
4910
  height: 1,
3979
- children: /* @__PURE__ */ jsxDEV11("text", {
3980
- fg: "#f7768e",
4911
+ children: /* @__PURE__ */ jsxDEV15("text", {
4912
+ fg: theme.error,
3981
4913
  children: [
3982
4914
  "Error: ",
3983
4915
  saveError
3984
4916
  ]
3985
4917
  }, undefined, true, undefined, this)
3986
4918
  }, undefined, false, undefined, this) : null,
3987
- saving ? /* @__PURE__ */ jsxDEV11("box", {
4919
+ saving ? /* @__PURE__ */ jsxDEV15("box", {
3988
4920
  height: 1,
3989
- children: /* @__PURE__ */ jsxDEV11("text", {
3990
- fg: "#ff9e64",
4921
+ children: /* @__PURE__ */ jsxDEV15("text", {
4922
+ fg: theme.warning,
3991
4923
  children: "Saving..."
3992
4924
  }, undefined, false, undefined, this)
3993
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV11("box", {
4925
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV15("box", {
3994
4926
  height: 1,
3995
- children: /* @__PURE__ */ jsxDEV11("text", {
3996
- fg: "#565f89",
4927
+ children: /* @__PURE__ */ jsxDEV15("text", {
4928
+ fg: theme.dim,
3997
4929
  children: "[Enter] save [Esc] back to list"
3998
4930
  }, undefined, false, undefined, this)
3999
4931
  }, undefined, false, undefined, this)
@@ -4003,32 +4935,32 @@ function AddVerifiedScreen() {
4003
4935
  }, undefined, true, undefined, this)
4004
4936
  }, undefined, false, undefined, this);
4005
4937
  }
4006
- return /* @__PURE__ */ jsxDEV11("box", {
4938
+ return /* @__PURE__ */ jsxDEV15("box", {
4007
4939
  flexDirection: "column",
4008
4940
  flexGrow: 1,
4009
4941
  alignItems: "center",
4010
4942
  justifyContent: "center",
4011
- children: /* @__PURE__ */ jsxDEV11("box", {
4943
+ children: /* @__PURE__ */ jsxDEV15("box", {
4012
4944
  flexDirection: "column",
4013
4945
  border: true,
4014
4946
  borderStyle: "rounded",
4015
- borderColor: "#292e42",
4016
- backgroundColor: "#16161e",
4947
+ borderColor: theme.border,
4948
+ backgroundColor: theme.background,
4017
4949
  width: CARD_W,
4018
4950
  children: [
4019
- /* @__PURE__ */ jsxDEV11("box", {
4951
+ /* @__PURE__ */ jsxDEV15("box", {
4020
4952
  flexDirection: "row",
4021
4953
  paddingLeft: 2,
4022
4954
  paddingRight: 2,
4023
4955
  paddingTop: 1,
4024
4956
  paddingBottom: 1,
4025
4957
  children: [
4026
- /* @__PURE__ */ jsxDEV11("text", {
4027
- fg: "#7dcfff",
4958
+ /* @__PURE__ */ jsxDEV15("text", {
4959
+ fg: theme.accent,
4028
4960
  children: "Search: "
4029
4961
  }, undefined, false, undefined, this),
4030
- /* @__PURE__ */ jsxDEV11("text", {
4031
- fg: "#c0caf5",
4962
+ /* @__PURE__ */ jsxDEV15("text", {
4963
+ fg: theme.text,
4032
4964
  children: [
4033
4965
  searchQuery,
4034
4966
  "_"
@@ -4036,59 +4968,59 @@ function AddVerifiedScreen() {
4036
4968
  }, undefined, true, undefined, this)
4037
4969
  ]
4038
4970
  }, undefined, true, undefined, this),
4039
- /* @__PURE__ */ jsxDEV11("box", {
4971
+ /* @__PURE__ */ jsxDEV15("box", {
4040
4972
  height: 1,
4041
- backgroundColor: "#292e42"
4973
+ backgroundColor: theme.border
4042
4974
  }, undefined, false, undefined, this),
4043
- /* @__PURE__ */ jsxDEV11("scrollbox", {
4975
+ /* @__PURE__ */ jsxDEV15("scrollbox", {
4044
4976
  ref: scrollboxRef,
4045
4977
  height: PAGE_SIZE,
4046
- style: { scrollbarOptions: { showArrows: true, trackOptions: { foregroundColor: "#7aa2f7", backgroundColor: "#292e42" } } },
4978
+ style: { scrollbarOptions: { showArrows: true, trackOptions: { foregroundColor: theme.primary, backgroundColor: theme.border } } },
4047
4979
  children: [
4048
- loadError && /* @__PURE__ */ jsxDEV11("box", {
4980
+ loadError && /* @__PURE__ */ jsxDEV15("box", {
4049
4981
  height: 1,
4050
4982
  paddingLeft: 2,
4051
- children: /* @__PURE__ */ jsxDEV11("text", {
4052
- fg: "#f7768e",
4983
+ children: /* @__PURE__ */ jsxDEV15("text", {
4984
+ fg: theme.error,
4053
4985
  children: [
4054
4986
  "Error loading providers: ",
4055
4987
  loadError
4056
4988
  ]
4057
4989
  }, undefined, true, undefined, this)
4058
4990
  }, undefined, false, undefined, this),
4059
- !loadError && filtered.length === 0 && /* @__PURE__ */ jsxDEV11("box", {
4991
+ !loadError && filtered.length === 0 && /* @__PURE__ */ jsxDEV15("box", {
4060
4992
  height: 1,
4061
4993
  paddingLeft: 2,
4062
- children: /* @__PURE__ */ jsxDEV11("text", {
4063
- fg: "#565f89",
4994
+ children: /* @__PURE__ */ jsxDEV15("text", {
4995
+ fg: theme.dim,
4064
4996
  children: allProviders.length === 0 ? "Loading..." : "No providers found"
4065
4997
  }, undefined, false, undefined, this)
4066
4998
  }, undefined, false, undefined, this),
4067
4999
  filtered.map((prov, i) => {
4068
5000
  const isActive = i === cursor;
4069
- return /* @__PURE__ */ jsxDEV11("box", {
5001
+ return /* @__PURE__ */ jsxDEV15("box", {
4070
5002
  height: 1,
4071
5003
  width: "100%",
4072
5004
  flexDirection: "row",
4073
- backgroundColor: isActive ? "#292e42" : "transparent",
5005
+ backgroundColor: isActive ? theme.border : "transparent",
4074
5006
  children: [
4075
- /* @__PURE__ */ jsxDEV11("text", {
4076
- fg: "#565f89",
5007
+ /* @__PURE__ */ jsxDEV15("text", {
5008
+ fg: theme.dim,
4077
5009
  width: 2,
4078
5010
  children: " "
4079
5011
  }, undefined, false, undefined, this),
4080
- /* @__PURE__ */ jsxDEV11("text", {
4081
- fg: isActive ? "#c0caf5" : "#565f89",
5012
+ /* @__PURE__ */ jsxDEV15("text", {
5013
+ fg: isActive ? theme.text : theme.dim,
4082
5014
  width: Math.floor((CARD_W - 10) / 2),
4083
5015
  children: prov.name
4084
5016
  }, undefined, false, undefined, this),
4085
- /* @__PURE__ */ jsxDEV11("text", {
4086
- fg: isActive ? "#7aa2f7" : "#292e42",
5017
+ /* @__PURE__ */ jsxDEV15("text", {
5018
+ fg: isActive ? theme.primary : theme.border,
4087
5019
  width: Math.floor((CARD_W - 10) / 2),
4088
5020
  children: prov.type
4089
5021
  }, undefined, false, undefined, this),
4090
- /* @__PURE__ */ jsxDEV11("text", {
4091
- fg: "#7dcfff",
5022
+ /* @__PURE__ */ jsxDEV15("text", {
5023
+ fg: theme.accent,
4092
5024
  width: 2,
4093
5025
  children: isActive ? "\u203A" : " "
4094
5026
  }, undefined, false, undefined, this)
@@ -4097,26 +5029,26 @@ function AddVerifiedScreen() {
4097
5029
  })
4098
5030
  ]
4099
5031
  }, undefined, true, undefined, this),
4100
- /* @__PURE__ */ jsxDEV11("box", {
5032
+ /* @__PURE__ */ jsxDEV15("box", {
4101
5033
  height: 1,
4102
- backgroundColor: "#292e42"
5034
+ backgroundColor: theme.border
4103
5035
  }, undefined, false, undefined, this),
4104
- /* @__PURE__ */ jsxDEV11("box", {
5036
+ /* @__PURE__ */ jsxDEV15("box", {
4105
5037
  flexDirection: "row",
4106
5038
  paddingLeft: 2,
4107
5039
  paddingRight: 2,
4108
5040
  paddingTop: 1,
4109
5041
  paddingBottom: 1,
4110
5042
  children: [
4111
- /* @__PURE__ */ jsxDEV11("text", {
4112
- fg: "#565f89",
5043
+ /* @__PURE__ */ jsxDEV15("text", {
5044
+ fg: theme.dim,
4113
5045
  children: [
4114
5046
  filtered.length,
4115
5047
  " providers"
4116
5048
  ]
4117
5049
  }, undefined, true, undefined, this),
4118
- /* @__PURE__ */ jsxDEV11("text", {
4119
- fg: "#565f89",
5050
+ /* @__PURE__ */ jsxDEV15("text", {
5051
+ fg: theme.dim,
4120
5052
  children: " [\u2191\u2193/PgUp/PgDn/wheel] scroll"
4121
5053
  }, undefined, false, undefined, this)
4122
5054
  ]
@@ -4126,34 +5058,37 @@ function AddVerifiedScreen() {
4126
5058
  }, undefined, false, undefined, this);
4127
5059
  }
4128
5060
  var init_AddVerifiedScreen = __esm(() => {
5061
+ init_useAppKeyboard();
4129
5062
  init_AppContext();
5063
+ init_ThemeContext();
4130
5064
  init_usePaste();
4131
5065
  });
4132
5066
 
4133
5067
  // src/tui/screens/AddCustomScreen.tsx
4134
- import { useState as useState6 } from "react";
4135
- import { useKeyboard as useKeyboard7, useTerminalDimensions as useTerminalDimensions3 } from "@opentui/react";
4136
- import { jsxDEV as jsxDEV12 } from "@opentui/react/jsx-dev-runtime";
5068
+ import { useState as useState10 } from "react";
5069
+ import { useTerminalDimensions as useTerminalDimensions3 } from "@opentui/react";
5070
+ import { jsxDEV as jsxDEV16 } from "@opentui/react/jsx-dev-runtime";
4137
5071
  function stepIndex(s) {
4138
5072
  return STEPS.indexOf(s);
4139
5073
  }
4140
5074
  function AddCustomScreen() {
4141
5075
  const { dispatch } = useAppContext();
4142
5076
  const navigate = useNavigate();
5077
+ const theme = useTheme();
4143
5078
  const { width } = useTerminalDimensions3();
4144
5079
  const CARD_W = Math.min(60, width - 4);
4145
- const [step, setStep] = useState6("type");
4146
- const [providerType, setProviderType] = useState6("openai-compatible");
4147
- const [typeCursor, setTypeCursor] = useState6(0);
4148
- const [providerId, setProviderId] = useState6("");
4149
- const [providerName, setProviderName] = useState6("");
4150
- const [baseUrl, setBaseUrl] = useState6("");
4151
- const [apiKey, setApiKey] = useState6("");
4152
- const [modelInput, setModelInput] = useState6("");
4153
- const [models, setModels] = useState6([]);
4154
- const [saveError, setSaveError] = useState6("");
4155
- const [savedModelCount, setSavedModelCount] = useState6(0);
4156
- const [inputError, setInputError] = useState6("");
5080
+ const [step, setStep] = useState10("type");
5081
+ const [providerType, setProviderType] = useState10("openai-compatible");
5082
+ const [typeCursor, setTypeCursor] = useState10(0);
5083
+ const [providerId, setProviderId] = useState10("");
5084
+ const [providerName, setProviderName] = useState10("");
5085
+ const [baseUrl, setBaseUrl] = useState10("");
5086
+ const [apiKey, setApiKey] = useState10("");
5087
+ const [modelInput, setModelInput] = useState10("");
5088
+ const [models, setModels] = useState10([]);
5089
+ const [saveError, setSaveError] = useState10("");
5090
+ const [savedModelCount, setSavedModelCount] = useState10(0);
5091
+ const [inputError, setInputError] = useState10("");
4157
5092
  const typeItems = ["OpenAI Compatible", "Anthropic", "Back"];
4158
5093
  async function doSave() {
4159
5094
  setStep("saving");
@@ -4166,10 +5101,7 @@ function AddCustomScreen() {
4166
5101
  type: providerType,
4167
5102
  baseUrl: baseUrl.trim(),
4168
5103
  apiKey: apiKey.trim(),
4169
- models: models.map((m) => ({
4170
- id: m,
4171
- name: m
4172
- }))
5104
+ models: models.map((m) => ({ id: m, name: m }))
4173
5105
  });
4174
5106
  const { getAllAvailableProviders: getAllAvailableProviders2 } = await Promise.resolve().then(() => (init_opencode_integration(), exports_opencode_integration));
4175
5107
  const providers = await getAllAvailableProviders2(false);
@@ -4194,7 +5126,7 @@ function AddCustomScreen() {
4194
5126
  else if (step === "models")
4195
5127
  setModelInput((v) => v + clean);
4196
5128
  });
4197
- useKeyboard7((key) => {
5129
+ useAppKeyboard((key) => {
4198
5130
  if (step === "done") {
4199
5131
  if (key.name === "return" || key.name === "enter")
4200
5132
  navigate("model-menu");
@@ -4249,9 +5181,8 @@ function AddCustomScreen() {
4249
5181
  setProviderId((v) => v.slice(0, -1));
4250
5182
  return;
4251
5183
  }
4252
- if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ") {
5184
+ if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ")
4253
5185
  setProviderId((v) => v + key.sequence);
4254
- }
4255
5186
  return;
4256
5187
  }
4257
5188
  if (step === "name") {
@@ -4266,9 +5197,8 @@ function AddCustomScreen() {
4266
5197
  setProviderName((v) => v.slice(0, -1));
4267
5198
  return;
4268
5199
  }
4269
- if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ") {
5200
+ if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ")
4270
5201
  setProviderName((v) => v + key.sequence);
4271
- }
4272
5202
  return;
4273
5203
  }
4274
5204
  if (step === "url") {
@@ -4289,9 +5219,8 @@ function AddCustomScreen() {
4289
5219
  setBaseUrl((v) => v.slice(0, -1));
4290
5220
  return;
4291
5221
  }
4292
- if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ") {
5222
+ if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ")
4293
5223
  setBaseUrl((v) => v + key.sequence);
4294
- }
4295
5224
  return;
4296
5225
  }
4297
5226
  if (step === "key") {
@@ -4304,9 +5233,8 @@ function AddCustomScreen() {
4304
5233
  setApiKey((v) => v.slice(0, -1));
4305
5234
  return;
4306
5235
  }
4307
- if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ") {
5236
+ if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ")
4308
5237
  setApiKey((v) => v + key.sequence);
4309
- }
4310
5238
  return;
4311
5239
  }
4312
5240
  if (step === "models") {
@@ -4328,31 +5256,30 @@ function AddCustomScreen() {
4328
5256
  setModelInput((v) => v.slice(0, -1));
4329
5257
  return;
4330
5258
  }
4331
- if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ") {
5259
+ if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ")
4332
5260
  setModelInput((v) => v + key.sequence);
4333
- }
4334
5261
  }
4335
5262
  });
4336
5263
  const curStepIdx = stepIndex(step);
4337
5264
  function ProgressBar() {
4338
- return /* @__PURE__ */ jsxDEV12("box", {
5265
+ return /* @__PURE__ */ jsxDEV16("box", {
4339
5266
  height: 1,
4340
5267
  paddingLeft: 2,
4341
5268
  paddingRight: 2,
4342
5269
  flexDirection: "row",
4343
- children: STEPS.map((s, i) => /* @__PURE__ */ jsxDEV12("box", {
5270
+ children: STEPS.map((s, i) => /* @__PURE__ */ jsxDEV16("box", {
4344
5271
  flexDirection: "row",
4345
5272
  children: [
4346
- /* @__PURE__ */ jsxDEV12("text", {
4347
- fg: i < curStepIdx ? "#9ece6a" : i === curStepIdx ? "#7dcfff" : "#292e42",
5273
+ /* @__PURE__ */ jsxDEV16("text", {
5274
+ fg: i < curStepIdx ? theme.success : i === curStepIdx ? theme.accent : theme.border,
4348
5275
  children: [
4349
5276
  STEP_NUM[i],
4350
5277
  " ",
4351
5278
  STEP_LABELS[i]
4352
5279
  ]
4353
5280
  }, undefined, true, undefined, this),
4354
- i < STEPS.length - 1 && /* @__PURE__ */ jsxDEV12("text", {
4355
- fg: "#292e42",
5281
+ i < STEPS.length - 1 && /* @__PURE__ */ jsxDEV16("text", {
5282
+ fg: theme.border,
4356
5283
  children: " "
4357
5284
  }, undefined, false, undefined, this)
4358
5285
  ]
@@ -4360,29 +5287,29 @@ function AddCustomScreen() {
4360
5287
  }, undefined, false, undefined, this);
4361
5288
  }
4362
5289
  if (step === "done") {
4363
- return /* @__PURE__ */ jsxDEV12("box", {
5290
+ return /* @__PURE__ */ jsxDEV16("box", {
4364
5291
  flexDirection: "column",
4365
5292
  flexGrow: 1,
4366
5293
  alignItems: "center",
4367
5294
  justifyContent: "center",
4368
- children: /* @__PURE__ */ jsxDEV12("box", {
5295
+ children: /* @__PURE__ */ jsxDEV16("box", {
4369
5296
  flexDirection: "column",
4370
5297
  border: true,
4371
5298
  borderStyle: "rounded",
4372
- borderColor: "#292e42",
4373
- backgroundColor: "#16161e",
5299
+ borderColor: theme.border,
5300
+ backgroundColor: theme.background,
4374
5301
  width: CARD_W,
4375
- children: /* @__PURE__ */ jsxDEV12("box", {
5302
+ children: /* @__PURE__ */ jsxDEV16("box", {
4376
5303
  flexDirection: "column",
4377
5304
  paddingLeft: 2,
4378
5305
  paddingRight: 2,
4379
5306
  paddingTop: 1,
4380
5307
  paddingBottom: 1,
4381
5308
  children: [
4382
- /* @__PURE__ */ jsxDEV12("box", {
5309
+ /* @__PURE__ */ jsxDEV16("box", {
4383
5310
  height: 1,
4384
- children: /* @__PURE__ */ jsxDEV12("text", {
4385
- fg: "#9ece6a",
5311
+ children: /* @__PURE__ */ jsxDEV16("text", {
5312
+ fg: theme.success,
4386
5313
  children: [
4387
5314
  "Custom provider added! ",
4388
5315
  savedModelCount,
@@ -4392,10 +5319,10 @@ function AddCustomScreen() {
4392
5319
  ]
4393
5320
  }, undefined, true, undefined, this)
4394
5321
  }, undefined, false, undefined, this),
4395
- /* @__PURE__ */ jsxDEV12("box", {
5322
+ /* @__PURE__ */ jsxDEV16("box", {
4396
5323
  height: 1,
4397
- children: /* @__PURE__ */ jsxDEV12("text", {
4398
- fg: "#565f89",
5324
+ children: /* @__PURE__ */ jsxDEV16("text", {
5325
+ fg: theme.dim,
4399
5326
  children: "Press [Enter] to return"
4400
5327
  }, undefined, false, undefined, this)
4401
5328
  }, undefined, false, undefined, this)
@@ -4405,107 +5332,107 @@ function AddCustomScreen() {
4405
5332
  }, undefined, false, undefined, this);
4406
5333
  }
4407
5334
  if (step === "saving") {
4408
- return /* @__PURE__ */ jsxDEV12("box", {
5335
+ return /* @__PURE__ */ jsxDEV16("box", {
4409
5336
  flexDirection: "column",
4410
5337
  flexGrow: 1,
4411
5338
  alignItems: "center",
4412
5339
  justifyContent: "center",
4413
- children: /* @__PURE__ */ jsxDEV12("box", {
5340
+ children: /* @__PURE__ */ jsxDEV16("box", {
4414
5341
  flexDirection: "column",
4415
5342
  border: true,
4416
5343
  borderStyle: "rounded",
4417
- borderColor: "#292e42",
4418
- backgroundColor: "#16161e",
5344
+ borderColor: theme.border,
5345
+ backgroundColor: theme.background,
4419
5346
  width: CARD_W,
4420
- children: /* @__PURE__ */ jsxDEV12("box", {
5347
+ children: /* @__PURE__ */ jsxDEV16("box", {
4421
5348
  paddingLeft: 2,
4422
5349
  paddingTop: 1,
4423
5350
  paddingBottom: 1,
4424
- children: /* @__PURE__ */ jsxDEV12("text", {
4425
- fg: "#ff9e64",
5351
+ children: /* @__PURE__ */ jsxDEV16("text", {
5352
+ fg: theme.warning,
4426
5353
  children: "\u2839 Saving..."
4427
5354
  }, undefined, false, undefined, this)
4428
5355
  }, undefined, false, undefined, this)
4429
5356
  }, undefined, false, undefined, this)
4430
5357
  }, undefined, false, undefined, this);
4431
5358
  }
4432
- return /* @__PURE__ */ jsxDEV12("box", {
5359
+ return /* @__PURE__ */ jsxDEV16("box", {
4433
5360
  flexDirection: "column",
4434
5361
  flexGrow: 1,
4435
5362
  alignItems: "center",
4436
5363
  justifyContent: "center",
4437
- children: /* @__PURE__ */ jsxDEV12("box", {
5364
+ children: /* @__PURE__ */ jsxDEV16("box", {
4438
5365
  flexDirection: "column",
4439
5366
  border: true,
4440
5367
  borderStyle: "rounded",
4441
- borderColor: "#292e42",
4442
- backgroundColor: "#16161e",
5368
+ borderColor: theme.border,
5369
+ backgroundColor: theme.background,
4443
5370
  width: CARD_W,
4444
5371
  children: [
4445
- /* @__PURE__ */ jsxDEV12("box", {
5372
+ /* @__PURE__ */ jsxDEV16("box", {
4446
5373
  height: 1,
4447
5374
  paddingLeft: 2,
4448
5375
  paddingTop: 1,
4449
- children: /* @__PURE__ */ jsxDEV12("text", {
4450
- fg: "#7dcfff",
5376
+ children: /* @__PURE__ */ jsxDEV16("text", {
5377
+ fg: theme.accent,
4451
5378
  children: "Add Custom Provider"
4452
5379
  }, undefined, false, undefined, this)
4453
5380
  }, undefined, false, undefined, this),
4454
- /* @__PURE__ */ jsxDEV12("box", {
5381
+ /* @__PURE__ */ jsxDEV16("box", {
4455
5382
  height: 1,
4456
- backgroundColor: "#292e42"
5383
+ backgroundColor: theme.border
4457
5384
  }, undefined, false, undefined, this),
4458
- /* @__PURE__ */ jsxDEV12("box", {
5385
+ /* @__PURE__ */ jsxDEV16("box", {
4459
5386
  paddingTop: 1,
4460
5387
  paddingBottom: 1,
4461
- children: /* @__PURE__ */ jsxDEV12(ProgressBar, {}, undefined, false, undefined, this)
5388
+ children: /* @__PURE__ */ jsxDEV16(ProgressBar, {}, undefined, false, undefined, this)
4462
5389
  }, undefined, false, undefined, this),
4463
- /* @__PURE__ */ jsxDEV12("box", {
5390
+ /* @__PURE__ */ jsxDEV16("box", {
4464
5391
  height: 1,
4465
- backgroundColor: "#292e42"
5392
+ backgroundColor: theme.border
4466
5393
  }, undefined, false, undefined, this),
4467
- /* @__PURE__ */ jsxDEV12("box", {
5394
+ /* @__PURE__ */ jsxDEV16("box", {
4468
5395
  flexDirection: "column",
4469
5396
  paddingLeft: 2,
4470
5397
  paddingRight: 2,
4471
5398
  paddingTop: 1,
4472
5399
  paddingBottom: 1,
4473
5400
  children: [
4474
- step === "type" && /* @__PURE__ */ jsxDEV12("box", {
5401
+ step === "type" && /* @__PURE__ */ jsxDEV16("box", {
4475
5402
  flexDirection: "column",
4476
- children: typeItems.map((item, i) => /* @__PURE__ */ jsxDEV12("box", {
5403
+ children: typeItems.map((item, i) => /* @__PURE__ */ jsxDEV16("box", {
4477
5404
  height: 1,
4478
5405
  width: "100%",
4479
5406
  flexDirection: "row",
4480
- backgroundColor: i === typeCursor ? "#292e42" : "transparent",
5407
+ backgroundColor: i === typeCursor ? theme.border : "transparent",
4481
5408
  children: [
4482
- /* @__PURE__ */ jsxDEV12("text", {
4483
- fg: i === typeCursor ? "#c0caf5" : "#565f89",
5409
+ /* @__PURE__ */ jsxDEV16("text", {
5410
+ fg: i === typeCursor ? theme.text : theme.dim,
4484
5411
  children: [
4485
5412
  " ",
4486
5413
  item
4487
5414
  ]
4488
5415
  }, undefined, true, undefined, this),
4489
- i === typeCursor && /* @__PURE__ */ jsxDEV12("text", {
4490
- fg: "#7dcfff",
5416
+ i === typeCursor && /* @__PURE__ */ jsxDEV16("text", {
5417
+ fg: theme.accent,
4491
5418
  children: " \u203A"
4492
5419
  }, undefined, false, undefined, this)
4493
5420
  ]
4494
5421
  }, item, true, undefined, this))
4495
5422
  }, undefined, false, undefined, this),
4496
- step === "id" && /* @__PURE__ */ jsxDEV12("box", {
5423
+ step === "id" && /* @__PURE__ */ jsxDEV16("box", {
4497
5424
  flexDirection: "column",
4498
5425
  children: [
4499
- /* @__PURE__ */ jsxDEV12("box", {
5426
+ /* @__PURE__ */ jsxDEV16("box", {
4500
5427
  height: 1,
4501
5428
  flexDirection: "row",
4502
5429
  children: [
4503
- /* @__PURE__ */ jsxDEV12("text", {
4504
- fg: "#7aa2f7",
5430
+ /* @__PURE__ */ jsxDEV16("text", {
5431
+ fg: theme.primary,
4505
5432
  children: "Provider ID: "
4506
5433
  }, undefined, false, undefined, this),
4507
- /* @__PURE__ */ jsxDEV12("text", {
4508
- fg: "#c0caf5",
5434
+ /* @__PURE__ */ jsxDEV16("text", {
5435
+ fg: theme.text,
4509
5436
  children: [
4510
5437
  providerId,
4511
5438
  "_"
@@ -4513,28 +5440,28 @@ function AddCustomScreen() {
4513
5440
  }, undefined, true, undefined, this)
4514
5441
  ]
4515
5442
  }, undefined, true, undefined, this),
4516
- /* @__PURE__ */ jsxDEV12("box", {
5443
+ /* @__PURE__ */ jsxDEV16("box", {
4517
5444
  height: 1,
4518
- children: /* @__PURE__ */ jsxDEV12("text", {
4519
- fg: "#565f89",
5445
+ children: /* @__PURE__ */ jsxDEV16("text", {
5446
+ fg: theme.dim,
4520
5447
  children: "e.g. my-openai"
4521
5448
  }, undefined, false, undefined, this)
4522
5449
  }, undefined, false, undefined, this)
4523
5450
  ]
4524
5451
  }, undefined, true, undefined, this),
4525
- step === "name" && /* @__PURE__ */ jsxDEV12("box", {
5452
+ step === "name" && /* @__PURE__ */ jsxDEV16("box", {
4526
5453
  flexDirection: "column",
4527
5454
  children: [
4528
- /* @__PURE__ */ jsxDEV12("box", {
5455
+ /* @__PURE__ */ jsxDEV16("box", {
4529
5456
  height: 1,
4530
5457
  flexDirection: "row",
4531
5458
  children: [
4532
- /* @__PURE__ */ jsxDEV12("text", {
4533
- fg: "#7aa2f7",
5459
+ /* @__PURE__ */ jsxDEV16("text", {
5460
+ fg: theme.primary,
4534
5461
  children: "Display Name: "
4535
5462
  }, undefined, false, undefined, this),
4536
- /* @__PURE__ */ jsxDEV12("text", {
4537
- fg: "#c0caf5",
5463
+ /* @__PURE__ */ jsxDEV16("text", {
5464
+ fg: theme.text,
4538
5465
  children: [
4539
5466
  providerName,
4540
5467
  "_"
@@ -4542,10 +5469,10 @@ function AddCustomScreen() {
4542
5469
  }, undefined, true, undefined, this)
4543
5470
  ]
4544
5471
  }, undefined, true, undefined, this),
4545
- /* @__PURE__ */ jsxDEV12("box", {
5472
+ /* @__PURE__ */ jsxDEV16("box", {
4546
5473
  height: 1,
4547
- children: /* @__PURE__ */ jsxDEV12("text", {
4548
- fg: "#565f89",
5474
+ children: /* @__PURE__ */ jsxDEV16("text", {
5475
+ fg: theme.dim,
4549
5476
  children: [
4550
5477
  'e.g. My OpenAI (Enter to use "',
4551
5478
  providerId,
@@ -4555,19 +5482,19 @@ function AddCustomScreen() {
4555
5482
  }, undefined, false, undefined, this)
4556
5483
  ]
4557
5484
  }, undefined, true, undefined, this),
4558
- step === "url" && /* @__PURE__ */ jsxDEV12("box", {
5485
+ step === "url" && /* @__PURE__ */ jsxDEV16("box", {
4559
5486
  flexDirection: "column",
4560
5487
  children: [
4561
- /* @__PURE__ */ jsxDEV12("box", {
5488
+ /* @__PURE__ */ jsxDEV16("box", {
4562
5489
  height: 1,
4563
5490
  flexDirection: "row",
4564
5491
  children: [
4565
- /* @__PURE__ */ jsxDEV12("text", {
4566
- fg: "#7aa2f7",
5492
+ /* @__PURE__ */ jsxDEV16("text", {
5493
+ fg: theme.primary,
4567
5494
  children: "Base URL: "
4568
5495
  }, undefined, false, undefined, this),
4569
- /* @__PURE__ */ jsxDEV12("text", {
4570
- fg: "#c0caf5",
5496
+ /* @__PURE__ */ jsxDEV16("text", {
5497
+ fg: theme.text,
4571
5498
  children: [
4572
5499
  baseUrl,
4573
5500
  "_"
@@ -4575,28 +5502,28 @@ function AddCustomScreen() {
4575
5502
  }, undefined, true, undefined, this)
4576
5503
  ]
4577
5504
  }, undefined, true, undefined, this),
4578
- /* @__PURE__ */ jsxDEV12("box", {
5505
+ /* @__PURE__ */ jsxDEV16("box", {
4579
5506
  height: 1,
4580
- children: /* @__PURE__ */ jsxDEV12("text", {
4581
- fg: "#565f89",
5507
+ children: /* @__PURE__ */ jsxDEV16("text", {
5508
+ fg: theme.dim,
4582
5509
  children: "e.g. https://api.example.com/v1"
4583
5510
  }, undefined, false, undefined, this)
4584
5511
  }, undefined, false, undefined, this)
4585
5512
  ]
4586
5513
  }, undefined, true, undefined, this),
4587
- step === "key" && /* @__PURE__ */ jsxDEV12("box", {
5514
+ step === "key" && /* @__PURE__ */ jsxDEV16("box", {
4588
5515
  flexDirection: "column",
4589
5516
  children: [
4590
- /* @__PURE__ */ jsxDEV12("box", {
5517
+ /* @__PURE__ */ jsxDEV16("box", {
4591
5518
  height: 1,
4592
5519
  flexDirection: "row",
4593
5520
  children: [
4594
- /* @__PURE__ */ jsxDEV12("text", {
4595
- fg: "#7aa2f7",
5521
+ /* @__PURE__ */ jsxDEV16("text", {
5522
+ fg: theme.primary,
4596
5523
  children: "API Key: "
4597
5524
  }, undefined, false, undefined, this),
4598
- /* @__PURE__ */ jsxDEV12("text", {
4599
- fg: "#c0caf5",
5525
+ /* @__PURE__ */ jsxDEV16("text", {
5526
+ fg: theme.text,
4600
5527
  children: [
4601
5528
  apiKey,
4602
5529
  "_"
@@ -4604,24 +5531,24 @@ function AddCustomScreen() {
4604
5531
  }, undefined, true, undefined, this)
4605
5532
  ]
4606
5533
  }, undefined, true, undefined, this),
4607
- /* @__PURE__ */ jsxDEV12("box", {
5534
+ /* @__PURE__ */ jsxDEV16("box", {
4608
5535
  height: 1,
4609
- children: /* @__PURE__ */ jsxDEV12("text", {
4610
- fg: "#565f89",
5536
+ children: /* @__PURE__ */ jsxDEV16("text", {
5537
+ fg: theme.dim,
4611
5538
  children: "sk-... (leave empty if not needed)"
4612
5539
  }, undefined, false, undefined, this)
4613
5540
  }, undefined, false, undefined, this)
4614
5541
  ]
4615
5542
  }, undefined, true, undefined, this),
4616
- step === "models" && /* @__PURE__ */ jsxDEV12("box", {
5543
+ step === "models" && /* @__PURE__ */ jsxDEV16("box", {
4617
5544
  flexDirection: "column",
4618
5545
  children: [
4619
- models.length > 0 && /* @__PURE__ */ jsxDEV12("box", {
5546
+ models.length > 0 && /* @__PURE__ */ jsxDEV16("box", {
4620
5547
  flexDirection: "column",
4621
- children: models.map((m) => /* @__PURE__ */ jsxDEV12("box", {
5548
+ children: models.map((m) => /* @__PURE__ */ jsxDEV16("box", {
4622
5549
  height: 1,
4623
- children: /* @__PURE__ */ jsxDEV12("text", {
4624
- fg: "#565f89",
5550
+ children: /* @__PURE__ */ jsxDEV16("text", {
5551
+ fg: theme.dim,
4625
5552
  children: [
4626
5553
  " \xB7 ",
4627
5554
  m
@@ -4629,16 +5556,16 @@ function AddCustomScreen() {
4629
5556
  }, undefined, true, undefined, this)
4630
5557
  }, m, false, undefined, this))
4631
5558
  }, undefined, false, undefined, this),
4632
- /* @__PURE__ */ jsxDEV12("box", {
5559
+ /* @__PURE__ */ jsxDEV16("box", {
4633
5560
  height: 1,
4634
5561
  flexDirection: "row",
4635
5562
  children: [
4636
- /* @__PURE__ */ jsxDEV12("text", {
4637
- fg: "#7aa2f7",
5563
+ /* @__PURE__ */ jsxDEV16("text", {
5564
+ fg: theme.primary,
4638
5565
  children: "Model name: "
4639
5566
  }, undefined, false, undefined, this),
4640
- /* @__PURE__ */ jsxDEV12("text", {
4641
- fg: "#c0caf5",
5567
+ /* @__PURE__ */ jsxDEV16("text", {
5568
+ fg: theme.text,
4642
5569
  children: [
4643
5570
  modelInput,
4644
5571
  "_"
@@ -4646,10 +5573,10 @@ function AddCustomScreen() {
4646
5573
  }, undefined, true, undefined, this)
4647
5574
  ]
4648
5575
  }, undefined, true, undefined, this),
4649
- models.length > 0 && /* @__PURE__ */ jsxDEV12("box", {
5576
+ models.length > 0 && /* @__PURE__ */ jsxDEV16("box", {
4650
5577
  height: 1,
4651
- children: /* @__PURE__ */ jsxDEV12("text", {
4652
- fg: "#9ece6a",
5578
+ children: /* @__PURE__ */ jsxDEV16("text", {
5579
+ fg: theme.success,
4653
5580
  children: [
4654
5581
  " ",
4655
5582
  models.length,
@@ -4659,10 +5586,10 @@ function AddCustomScreen() {
4659
5586
  ]
4660
5587
  }, undefined, true, undefined, this)
4661
5588
  }, undefined, false, undefined, this),
4662
- saveError && /* @__PURE__ */ jsxDEV12("box", {
5589
+ saveError && /* @__PURE__ */ jsxDEV16("box", {
4663
5590
  height: 1,
4664
- children: /* @__PURE__ */ jsxDEV12("text", {
4665
- fg: "#f7768e",
5591
+ children: /* @__PURE__ */ jsxDEV16("text", {
5592
+ fg: theme.error,
4666
5593
  children: [
4667
5594
  "Error: ",
4668
5595
  saveError
@@ -4671,10 +5598,10 @@ function AddCustomScreen() {
4671
5598
  }, undefined, false, undefined, this)
4672
5599
  ]
4673
5600
  }, undefined, true, undefined, this),
4674
- inputError ? /* @__PURE__ */ jsxDEV12("box", {
5601
+ inputError ? /* @__PURE__ */ jsxDEV16("box", {
4675
5602
  height: 1,
4676
- children: /* @__PURE__ */ jsxDEV12("text", {
4677
- fg: "#f7768e",
5603
+ children: /* @__PURE__ */ jsxDEV16("text", {
5604
+ fg: theme.error,
4678
5605
  children: inputError
4679
5606
  }, undefined, false, undefined, this)
4680
5607
  }, undefined, false, undefined, this) : null
@@ -4686,7 +5613,9 @@ function AddCustomScreen() {
4686
5613
  }
4687
5614
  var STEPS, STEP_LABELS, STEP_NUM;
4688
5615
  var init_AddCustomScreen = __esm(() => {
5616
+ init_useAppKeyboard();
4689
5617
  init_AppContext();
5618
+ init_ThemeContext();
4690
5619
  init_usePaste();
4691
5620
  STEPS = ["type", "id", "name", "url", "key", "models"];
4692
5621
  STEP_LABELS = ["Type", "ID", "Name", "URL", "Key", "Models"];
@@ -4694,25 +5623,26 @@ var init_AddCustomScreen = __esm(() => {
4694
5623
  });
4695
5624
 
4696
5625
  // src/tui/screens/AddModelsScreen.tsx
4697
- import { useState as useState7, useEffect as useEffect6 } from "react";
4698
- import { useKeyboard as useKeyboard8, useTerminalDimensions as useTerminalDimensions4 } from "@opentui/react";
4699
- import { jsxDEV as jsxDEV13 } from "@opentui/react/jsx-dev-runtime";
5626
+ import { useState as useState11, useEffect as useEffect8 } from "react";
5627
+ import { useTerminalDimensions as useTerminalDimensions4 } from "@opentui/react";
5628
+ import { jsxDEV as jsxDEV17 } from "@opentui/react/jsx-dev-runtime";
4700
5629
  function AddModelsScreen() {
4701
5630
  const { dispatch } = useAppContext();
4702
5631
  const navigate = useNavigate();
5632
+ const theme = useTheme();
4703
5633
  const { width } = useTerminalDimensions4();
4704
5634
  const CARD_W = Math.min(60, width - 4);
4705
- const [step, setStep] = useState7("pick");
4706
- const [providers, setProviders] = useState7([]);
4707
- const [cursor, setCursor] = useState7(0);
4708
- const [selectedProvider, setSelectedProvider] = useState7(null);
4709
- const [modelInput, setModelInput] = useState7("");
4710
- const [addedModels, setAddedModels] = useState7([]);
4711
- const [loadError, setLoadError] = useState7("");
4712
- const [saveError, setSaveError] = useState7("");
4713
- const [inputError, setInputError] = useState7("");
4714
- const [done, setDone] = useState7(false);
4715
- useEffect6(() => {
5635
+ const [step, setStep] = useState11("pick");
5636
+ const [providers, setProviders] = useState11([]);
5637
+ const [cursor, setCursor] = useState11(0);
5638
+ const [selectedProvider, setSelectedProvider] = useState11(null);
5639
+ const [modelInput, setModelInput] = useState11("");
5640
+ const [addedModels, setAddedModels] = useState11([]);
5641
+ const [loadError, setLoadError] = useState11("");
5642
+ const [saveError, setSaveError] = useState11("");
5643
+ const [inputError, setInputError] = useState11("");
5644
+ const [done, setDone] = useState11(false);
5645
+ useEffect8(() => {
4716
5646
  async function load() {
4717
5647
  try {
4718
5648
  const { getCustomProvidersFromConfig: getCustomProvidersFromConfig2 } = await Promise.resolve().then(() => (init_ai_config(), exports_ai_config));
@@ -4729,7 +5659,7 @@ function AddModelsScreen() {
4729
5659
  if (step === "add")
4730
5660
  setModelInput((v) => v + clean);
4731
5661
  });
4732
- useKeyboard8((key) => {
5662
+ useAppKeyboard((key) => {
4733
5663
  if (done) {
4734
5664
  if (key.name === "return" || key.name === "enter")
4735
5665
  navigate("model-menu");
@@ -4782,9 +5712,8 @@ function AddModelsScreen() {
4782
5712
  setModelInput((v) => v.slice(0, -1));
4783
5713
  return;
4784
5714
  }
4785
- if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ") {
5715
+ if (key.sequence && key.sequence.length === 1 && !key.ctrl && !key.meta && key.sequence >= " ")
4786
5716
  setModelInput((v) => v + key.sequence);
4787
- }
4788
5717
  }
4789
5718
  });
4790
5719
  async function addModel() {
@@ -4795,10 +5724,7 @@ function AddModelsScreen() {
4795
5724
  const name = modelInput.trim();
4796
5725
  try {
4797
5726
  const { addModelToCustomProvider: addModelToCustomProvider2 } = await Promise.resolve().then(() => (init_ai_config(), exports_ai_config));
4798
- await addModelToCustomProvider2(selectedProvider.id, {
4799
- id: name.toLowerCase().replace(/[^a-z0-9-]/g, "-"),
4800
- name
4801
- });
5727
+ await addModelToCustomProvider2(selectedProvider.id, { id: name.toLowerCase().replace(/[^a-z0-9-]/g, "-"), name });
4802
5728
  setAddedModels((ms) => [...ms, name]);
4803
5729
  setModelInput("");
4804
5730
  } catch (e) {
@@ -4812,29 +5738,29 @@ function AddModelsScreen() {
4812
5738
  setDone(true);
4813
5739
  }
4814
5740
  if (done) {
4815
- return /* @__PURE__ */ jsxDEV13("box", {
5741
+ return /* @__PURE__ */ jsxDEV17("box", {
4816
5742
  flexDirection: "column",
4817
5743
  flexGrow: 1,
4818
5744
  alignItems: "center",
4819
5745
  justifyContent: "center",
4820
- children: /* @__PURE__ */ jsxDEV13("box", {
5746
+ children: /* @__PURE__ */ jsxDEV17("box", {
4821
5747
  flexDirection: "column",
4822
5748
  border: true,
4823
5749
  borderStyle: "rounded",
4824
- borderColor: "#292e42",
4825
- backgroundColor: "#16161e",
5750
+ borderColor: theme.border,
5751
+ backgroundColor: theme.background,
4826
5752
  width: CARD_W,
4827
- children: /* @__PURE__ */ jsxDEV13("box", {
5753
+ children: /* @__PURE__ */ jsxDEV17("box", {
4828
5754
  flexDirection: "column",
4829
5755
  paddingLeft: 2,
4830
5756
  paddingRight: 2,
4831
5757
  paddingTop: 1,
4832
5758
  paddingBottom: 1,
4833
5759
  children: [
4834
- /* @__PURE__ */ jsxDEV13("box", {
5760
+ /* @__PURE__ */ jsxDEV17("box", {
4835
5761
  height: 1,
4836
- children: /* @__PURE__ */ jsxDEV13("text", {
4837
- fg: "#9ece6a",
5762
+ children: /* @__PURE__ */ jsxDEV17("text", {
5763
+ fg: theme.success,
4838
5764
  children: [
4839
5765
  "Done! Added ",
4840
5766
  addedModels.length,
@@ -4846,10 +5772,10 @@ function AddModelsScreen() {
4846
5772
  ]
4847
5773
  }, undefined, true, undefined, this)
4848
5774
  }, undefined, false, undefined, this),
4849
- /* @__PURE__ */ jsxDEV13("box", {
5775
+ /* @__PURE__ */ jsxDEV17("box", {
4850
5776
  height: 1,
4851
- children: /* @__PURE__ */ jsxDEV13("text", {
4852
- fg: "#565f89",
5777
+ children: /* @__PURE__ */ jsxDEV17("text", {
5778
+ fg: theme.dim,
4853
5779
  children: "Press [Enter] to return"
4854
5780
  }, undefined, false, undefined, this)
4855
5781
  }, undefined, false, undefined, this)
@@ -4859,70 +5785,70 @@ function AddModelsScreen() {
4859
5785
  }, undefined, false, undefined, this);
4860
5786
  }
4861
5787
  if (step === "add" && selectedProvider) {
4862
- return /* @__PURE__ */ jsxDEV13("box", {
5788
+ return /* @__PURE__ */ jsxDEV17("box", {
4863
5789
  flexDirection: "column",
4864
5790
  flexGrow: 1,
4865
5791
  alignItems: "center",
4866
5792
  justifyContent: "center",
4867
- children: /* @__PURE__ */ jsxDEV13("box", {
5793
+ children: /* @__PURE__ */ jsxDEV17("box", {
4868
5794
  flexDirection: "column",
4869
5795
  border: true,
4870
5796
  borderStyle: "rounded",
4871
- borderColor: "#292e42",
4872
- backgroundColor: "#16161e",
5797
+ borderColor: theme.border,
5798
+ backgroundColor: theme.background,
4873
5799
  width: CARD_W,
4874
5800
  children: [
4875
- /* @__PURE__ */ jsxDEV13("box", {
5801
+ /* @__PURE__ */ jsxDEV17("box", {
4876
5802
  height: 1,
4877
5803
  paddingLeft: 2,
4878
5804
  paddingTop: 1,
4879
5805
  flexDirection: "row",
4880
5806
  children: [
4881
- /* @__PURE__ */ jsxDEV13("text", {
4882
- fg: "#7dcfff",
5807
+ /* @__PURE__ */ jsxDEV17("text", {
5808
+ fg: theme.accent,
4883
5809
  children: "Add Models to: "
4884
5810
  }, undefined, false, undefined, this),
4885
- /* @__PURE__ */ jsxDEV13("text", {
4886
- fg: "#c0caf5",
5811
+ /* @__PURE__ */ jsxDEV17("text", {
5812
+ fg: theme.text,
4887
5813
  children: selectedProvider.name
4888
5814
  }, undefined, false, undefined, this)
4889
5815
  ]
4890
5816
  }, undefined, true, undefined, this),
4891
- /* @__PURE__ */ jsxDEV13("box", {
5817
+ /* @__PURE__ */ jsxDEV17("box", {
4892
5818
  height: 1,
4893
- backgroundColor: "#292e42"
5819
+ backgroundColor: theme.border
4894
5820
  }, undefined, false, undefined, this),
4895
- /* @__PURE__ */ jsxDEV13("box", {
5821
+ /* @__PURE__ */ jsxDEV17("box", {
4896
5822
  flexDirection: "column",
4897
5823
  paddingLeft: 2,
4898
5824
  paddingRight: 2,
4899
5825
  paddingTop: 1,
4900
5826
  paddingBottom: 1,
4901
5827
  children: [
4902
- (selectedProvider.models.length > 0 || addedModels.length > 0) && /* @__PURE__ */ jsxDEV13("box", {
5828
+ (selectedProvider.models.length > 0 || addedModels.length > 0) && /* @__PURE__ */ jsxDEV17("box", {
4903
5829
  flexDirection: "column",
4904
5830
  children: [
4905
- /* @__PURE__ */ jsxDEV13("box", {
5831
+ /* @__PURE__ */ jsxDEV17("box", {
4906
5832
  height: 1,
4907
- children: /* @__PURE__ */ jsxDEV13("text", {
4908
- fg: "#7aa2f7",
5833
+ children: /* @__PURE__ */ jsxDEV17("text", {
5834
+ fg: theme.primary,
4909
5835
  children: "Current models:"
4910
5836
  }, undefined, false, undefined, this)
4911
5837
  }, undefined, false, undefined, this),
4912
- selectedProvider.models.map((m) => /* @__PURE__ */ jsxDEV13("box", {
5838
+ selectedProvider.models.map((m) => /* @__PURE__ */ jsxDEV17("box", {
4913
5839
  height: 1,
4914
- children: /* @__PURE__ */ jsxDEV13("text", {
4915
- fg: "#565f89",
5840
+ children: /* @__PURE__ */ jsxDEV17("text", {
5841
+ fg: theme.dim,
4916
5842
  children: [
4917
5843
  " \xB7 ",
4918
5844
  m.name || m.id
4919
5845
  ]
4920
5846
  }, undefined, true, undefined, this)
4921
5847
  }, m.id, false, undefined, this)),
4922
- addedModels.map((m) => /* @__PURE__ */ jsxDEV13("box", {
5848
+ addedModels.map((m) => /* @__PURE__ */ jsxDEV17("box", {
4923
5849
  height: 1,
4924
- children: /* @__PURE__ */ jsxDEV13("text", {
4925
- fg: "#9ece6a",
5850
+ children: /* @__PURE__ */ jsxDEV17("text", {
5851
+ fg: theme.success,
4926
5852
  children: [
4927
5853
  " \xB7 ",
4928
5854
  m,
@@ -4932,16 +5858,16 @@ function AddModelsScreen() {
4932
5858
  }, m, false, undefined, this))
4933
5859
  ]
4934
5860
  }, undefined, true, undefined, this),
4935
- /* @__PURE__ */ jsxDEV13("box", {
5861
+ /* @__PURE__ */ jsxDEV17("box", {
4936
5862
  height: 1,
4937
5863
  flexDirection: "row",
4938
5864
  children: [
4939
- /* @__PURE__ */ jsxDEV13("text", {
4940
- fg: "#7aa2f7",
5865
+ /* @__PURE__ */ jsxDEV17("text", {
5866
+ fg: theme.primary,
4941
5867
  children: "Model name: "
4942
5868
  }, undefined, false, undefined, this),
4943
- /* @__PURE__ */ jsxDEV13("text", {
4944
- fg: "#c0caf5",
5869
+ /* @__PURE__ */ jsxDEV17("text", {
5870
+ fg: theme.text,
4945
5871
  children: [
4946
5872
  modelInput,
4947
5873
  "_"
@@ -4949,10 +5875,10 @@ function AddModelsScreen() {
4949
5875
  }, undefined, true, undefined, this)
4950
5876
  ]
4951
5877
  }, undefined, true, undefined, this),
4952
- addedModels.length > 0 && /* @__PURE__ */ jsxDEV13("box", {
5878
+ addedModels.length > 0 && /* @__PURE__ */ jsxDEV17("box", {
4953
5879
  height: 1,
4954
- children: /* @__PURE__ */ jsxDEV13("text", {
4955
- fg: "#9ece6a",
5880
+ children: /* @__PURE__ */ jsxDEV17("text", {
5881
+ fg: theme.success,
4956
5882
  children: [
4957
5883
  "Added ",
4958
5884
  addedModels.length,
@@ -4962,20 +5888,20 @@ function AddModelsScreen() {
4962
5888
  ]
4963
5889
  }, undefined, true, undefined, this)
4964
5890
  }, undefined, false, undefined, this),
4965
- saveError && /* @__PURE__ */ jsxDEV13("box", {
5891
+ saveError && /* @__PURE__ */ jsxDEV17("box", {
4966
5892
  height: 1,
4967
- children: /* @__PURE__ */ jsxDEV13("text", {
4968
- fg: "#f7768e",
5893
+ children: /* @__PURE__ */ jsxDEV17("text", {
5894
+ fg: theme.error,
4969
5895
  children: [
4970
5896
  "Error: ",
4971
5897
  saveError
4972
5898
  ]
4973
5899
  }, undefined, true, undefined, this)
4974
5900
  }, undefined, false, undefined, this),
4975
- inputError && /* @__PURE__ */ jsxDEV13("box", {
5901
+ inputError && /* @__PURE__ */ jsxDEV17("box", {
4976
5902
  height: 1,
4977
- children: /* @__PURE__ */ jsxDEV13("text", {
4978
- fg: "#f7768e",
5903
+ children: /* @__PURE__ */ jsxDEV17("text", {
5904
+ fg: theme.error,
4979
5905
  children: inputError
4980
5906
  }, undefined, false, undefined, this)
4981
5907
  }, undefined, false, undefined, this)
@@ -4985,84 +5911,84 @@ function AddModelsScreen() {
4985
5911
  }, undefined, true, undefined, this)
4986
5912
  }, undefined, false, undefined, this);
4987
5913
  }
4988
- return /* @__PURE__ */ jsxDEV13("box", {
5914
+ return /* @__PURE__ */ jsxDEV17("box", {
4989
5915
  flexDirection: "column",
4990
5916
  flexGrow: 1,
4991
5917
  alignItems: "center",
4992
5918
  justifyContent: "center",
4993
- children: /* @__PURE__ */ jsxDEV13("box", {
5919
+ children: /* @__PURE__ */ jsxDEV17("box", {
4994
5920
  flexDirection: "column",
4995
5921
  border: true,
4996
5922
  borderStyle: "rounded",
4997
- borderColor: "#292e42",
4998
- backgroundColor: "#16161e",
5923
+ borderColor: theme.border,
5924
+ backgroundColor: theme.background,
4999
5925
  width: CARD_W,
5000
5926
  children: [
5001
- /* @__PURE__ */ jsxDEV13("box", {
5927
+ /* @__PURE__ */ jsxDEV17("box", {
5002
5928
  height: 1,
5003
5929
  paddingLeft: 2,
5004
5930
  paddingTop: 1,
5005
- children: /* @__PURE__ */ jsxDEV13("text", {
5006
- fg: "#7dcfff",
5931
+ children: /* @__PURE__ */ jsxDEV17("text", {
5932
+ fg: theme.accent,
5007
5933
  children: "Add Models to Provider"
5008
5934
  }, undefined, false, undefined, this)
5009
5935
  }, undefined, false, undefined, this),
5010
- /* @__PURE__ */ jsxDEV13("box", {
5936
+ /* @__PURE__ */ jsxDEV17("box", {
5011
5937
  height: 1,
5012
- backgroundColor: "#292e42"
5938
+ backgroundColor: theme.border
5013
5939
  }, undefined, false, undefined, this),
5014
- /* @__PURE__ */ jsxDEV13("box", {
5940
+ /* @__PURE__ */ jsxDEV17("box", {
5015
5941
  flexDirection: "column",
5016
5942
  paddingLeft: 2,
5017
5943
  paddingRight: 2,
5018
5944
  paddingTop: 1,
5019
5945
  paddingBottom: 1,
5020
5946
  children: [
5021
- loadError && /* @__PURE__ */ jsxDEV13("box", {
5947
+ loadError && /* @__PURE__ */ jsxDEV17("box", {
5022
5948
  height: 1,
5023
- children: /* @__PURE__ */ jsxDEV13("text", {
5024
- fg: "#f7768e",
5949
+ children: /* @__PURE__ */ jsxDEV17("text", {
5950
+ fg: theme.error,
5025
5951
  children: [
5026
5952
  "Error: ",
5027
5953
  loadError
5028
5954
  ]
5029
5955
  }, undefined, true, undefined, this)
5030
5956
  }, undefined, false, undefined, this),
5031
- !loadError && providers.length === 0 && /* @__PURE__ */ jsxDEV13("box", {
5957
+ !loadError && providers.length === 0 && /* @__PURE__ */ jsxDEV17("box", {
5032
5958
  height: 1,
5033
- children: /* @__PURE__ */ jsxDEV13("text", {
5034
- fg: "#ff9e64",
5959
+ children: /* @__PURE__ */ jsxDEV17("text", {
5960
+ fg: theme.warning,
5035
5961
  children: "No custom providers yet. Add one first."
5036
5962
  }, undefined, false, undefined, this)
5037
5963
  }, undefined, false, undefined, this),
5038
5964
  providers.map((prov, i) => {
5039
5965
  const isActive = i === cursor;
5040
- return /* @__PURE__ */ jsxDEV13("box", {
5966
+ return /* @__PURE__ */ jsxDEV17("box", {
5041
5967
  height: 1,
5042
5968
  width: "100%",
5043
5969
  flexDirection: "row",
5044
- backgroundColor: isActive ? "#292e42" : "transparent",
5970
+ backgroundColor: isActive ? theme.border : "transparent",
5045
5971
  children: [
5046
- /* @__PURE__ */ jsxDEV13("text", {
5047
- fg: "#565f89",
5972
+ /* @__PURE__ */ jsxDEV17("text", {
5973
+ fg: theme.dim,
5048
5974
  width: 2,
5049
5975
  children: " "
5050
5976
  }, undefined, false, undefined, this),
5051
- /* @__PURE__ */ jsxDEV13("text", {
5052
- fg: isActive ? "#c0caf5" : "#565f89",
5977
+ /* @__PURE__ */ jsxDEV17("text", {
5978
+ fg: isActive ? theme.text : theme.dim,
5053
5979
  width: Math.floor((CARD_W - 8) * 0.6),
5054
5980
  children: prov.name
5055
5981
  }, undefined, false, undefined, this),
5056
- /* @__PURE__ */ jsxDEV13("text", {
5057
- fg: isActive ? "#7aa2f7" : "#292e42",
5982
+ /* @__PURE__ */ jsxDEV17("text", {
5983
+ fg: isActive ? theme.primary : theme.border,
5058
5984
  width: Math.floor((CARD_W - 8) * 0.3),
5059
5985
  children: [
5060
5986
  prov.models.length,
5061
5987
  " models"
5062
5988
  ]
5063
5989
  }, undefined, true, undefined, this),
5064
- /* @__PURE__ */ jsxDEV13("text", {
5065
- fg: "#7dcfff",
5990
+ /* @__PURE__ */ jsxDEV17("text", {
5991
+ fg: theme.accent,
5066
5992
  width: 2,
5067
5993
  children: isActive ? "\u203A" : " "
5068
5994
  }, undefined, false, undefined, this)
@@ -5076,84 +6002,87 @@ function AddModelsScreen() {
5076
6002
  }, undefined, false, undefined, this);
5077
6003
  }
5078
6004
  var init_AddModelsScreen = __esm(() => {
6005
+ init_useAppKeyboard();
5079
6006
  init_AppContext();
6007
+ init_ThemeContext();
5080
6008
  init_usePaste();
5081
6009
  });
5082
6010
 
5083
6011
  // src/tui/screens/ListProvidersScreen.tsx
5084
- import { useKeyboard as useKeyboard9 } from "@opentui/react";
5085
- import { jsxDEV as jsxDEV14 } from "@opentui/react/jsx-dev-runtime";
6012
+ import { jsxDEV as jsxDEV18 } from "@opentui/react/jsx-dev-runtime";
5086
6013
  function ListProvidersScreen() {
5087
6014
  const { state } = useAppContext();
5088
6015
  const navigate = useNavigate();
5089
- useKeyboard9((key) => {
6016
+ const theme = useTheme();
6017
+ useAppKeyboard((key) => {
5090
6018
  if (key.name === "escape" || key.name === "q") {
5091
6019
  navigate("model-menu");
5092
6020
  }
5093
6021
  });
5094
6022
  if (state.isLoadingConfig) {
5095
- return /* @__PURE__ */ jsxDEV14("box", {
6023
+ return /* @__PURE__ */ jsxDEV18("box", {
5096
6024
  flexDirection: "column",
5097
6025
  flexGrow: 1,
5098
6026
  padding: 1,
5099
- children: /* @__PURE__ */ jsxDEV14("text", {
6027
+ children: /* @__PURE__ */ jsxDEV18("text", {
6028
+ fg: theme.dim,
5100
6029
  children: "Loading providers..."
5101
6030
  }, undefined, false, undefined, this)
5102
6031
  }, undefined, false, undefined, this);
5103
6032
  }
5104
6033
  const providers = state.config?.providers ?? [];
5105
6034
  if (providers.length === 0) {
5106
- return /* @__PURE__ */ jsxDEV14("box", {
6035
+ return /* @__PURE__ */ jsxDEV18("box", {
5107
6036
  flexDirection: "column",
5108
6037
  flexGrow: 1,
5109
6038
  padding: 1,
5110
6039
  children: [
5111
- /* @__PURE__ */ jsxDEV14("text", {
5112
- fg: "#7aa2f7",
6040
+ /* @__PURE__ */ jsxDEV18("text", {
6041
+ fg: theme.primary,
5113
6042
  children: "Configured Providers"
5114
6043
  }, undefined, false, undefined, this),
5115
- /* @__PURE__ */ jsxDEV14("box", {
6044
+ /* @__PURE__ */ jsxDEV18("box", {
5116
6045
  marginTop: 1,
5117
- children: /* @__PURE__ */ jsxDEV14("text", {
5118
- fg: "#ff9e64",
6046
+ children: /* @__PURE__ */ jsxDEV18("text", {
6047
+ fg: theme.warning,
5119
6048
  children: "No providers configured yet."
5120
6049
  }, undefined, false, undefined, this)
5121
6050
  }, undefined, false, undefined, this)
5122
6051
  ]
5123
6052
  }, undefined, true, undefined, this);
5124
6053
  }
5125
- return /* @__PURE__ */ jsxDEV14("box", {
6054
+ return /* @__PURE__ */ jsxDEV18("box", {
5126
6055
  flexDirection: "column",
5127
6056
  flexGrow: 1,
5128
6057
  padding: 1,
5129
6058
  children: [
5130
- /* @__PURE__ */ jsxDEV14("text", {
5131
- fg: "#7aa2f7",
6059
+ /* @__PURE__ */ jsxDEV18("text", {
6060
+ fg: theme.primary,
5132
6061
  children: "Configured Providers"
5133
6062
  }, undefined, false, undefined, this),
5134
- /* @__PURE__ */ jsxDEV14("box", {
6063
+ /* @__PURE__ */ jsxDEV18("box", {
5135
6064
  marginTop: 1,
5136
6065
  flexGrow: 1,
5137
- children: /* @__PURE__ */ jsxDEV14("scrollbox", {
6066
+ children: /* @__PURE__ */ jsxDEV18("scrollbox", {
5138
6067
  focused: true,
5139
- children: providers.map((provider, i) => /* @__PURE__ */ jsxDEV14("box", {
6068
+ children: providers.map((provider, i) => /* @__PURE__ */ jsxDEV18("box", {
5140
6069
  flexDirection: "column",
5141
6070
  border: true,
5142
6071
  borderStyle: "rounded",
5143
- borderColor: "#292e42",
5144
- backgroundColor: "#16161e",
6072
+ borderColor: theme.border,
6073
+ backgroundColor: theme.background,
5145
6074
  marginBottom: 1,
5146
6075
  padding: 1,
5147
6076
  children: [
5148
- /* @__PURE__ */ jsxDEV14("box", {
6077
+ /* @__PURE__ */ jsxDEV18("box", {
5149
6078
  flexDirection: "row",
5150
6079
  children: [
5151
- /* @__PURE__ */ jsxDEV14("text", {
5152
- fg: "#7dcfff",
6080
+ /* @__PURE__ */ jsxDEV18("text", {
6081
+ fg: theme.accent,
5153
6082
  children: provider.name
5154
6083
  }, undefined, false, undefined, this),
5155
- /* @__PURE__ */ jsxDEV14("text", {
5156
- fg: "#565f89",
6084
+ /* @__PURE__ */ jsxDEV18("text", {
6085
+ fg: theme.dim,
5157
6086
  children: [
5158
6087
  " [",
5159
6088
  provider.type,
@@ -5162,8 +6091,8 @@ function ListProvidersScreen() {
5162
6091
  }, undefined, true, undefined, this)
5163
6092
  ]
5164
6093
  }, undefined, true, undefined, this),
5165
- provider.models.map((model, j) => /* @__PURE__ */ jsxDEV14("text", {
5166
- fg: "#565f89",
6094
+ provider.models.map((model, j) => /* @__PURE__ */ jsxDEV18("text", {
6095
+ fg: theme.dim,
5167
6096
  children: [
5168
6097
  " \xB7 ",
5169
6098
  model.name || model.id
@@ -5177,16 +6106,285 @@ function ListProvidersScreen() {
5177
6106
  }, undefined, true, undefined, this);
5178
6107
  }
5179
6108
  var init_ListProvidersScreen = __esm(() => {
6109
+ init_useAppKeyboard();
6110
+ init_AppContext();
6111
+ init_ThemeContext();
6112
+ });
6113
+
6114
+ // src/tui/screens/FAQScreen.tsx
6115
+ import { jsxDEV as jsxDEV19 } from "@opentui/react/jsx-dev-runtime";
6116
+ function FAQScreen() {
6117
+ const navigate = useNavigate();
6118
+ const theme = useTheme();
6119
+ useAppKeyboard((key) => {
6120
+ if (key.name === "escape" || key.name === "q") {
6121
+ navigate("main-menu");
6122
+ }
6123
+ });
6124
+ return /* @__PURE__ */ jsxDEV19("box", {
6125
+ flexDirection: "column",
6126
+ flexGrow: 1,
6127
+ alignItems: "center",
6128
+ padding: 1,
6129
+ children: /* @__PURE__ */ jsxDEV19("box", {
6130
+ flexDirection: "column",
6131
+ width: 70,
6132
+ children: [
6133
+ /* @__PURE__ */ jsxDEV19("box", {
6134
+ marginBottom: 1,
6135
+ children: /* @__PURE__ */ jsxDEV19("text", {
6136
+ fg: theme.primary,
6137
+ bold: true,
6138
+ children: "FAQ / Learn"
6139
+ }, undefined, false, undefined, this)
6140
+ }, undefined, false, undefined, this),
6141
+ /* @__PURE__ */ jsxDEV19("scrollbox", {
6142
+ focused: true,
6143
+ flexGrow: 1,
6144
+ children: /* @__PURE__ */ jsxDEV19("box", {
6145
+ flexDirection: "column",
6146
+ children: [
6147
+ /* @__PURE__ */ jsxDEV19("box", {
6148
+ flexDirection: "column",
6149
+ border: true,
6150
+ borderStyle: "rounded",
6151
+ borderColor: theme.border,
6152
+ padding: 1,
6153
+ marginBottom: 1,
6154
+ children: [
6155
+ /* @__PURE__ */ jsxDEV19("text", {
6156
+ fg: theme.accent,
6157
+ bold: true,
6158
+ children: "METRICS EXPLAINED"
6159
+ }, undefined, false, undefined, this),
6160
+ /* @__PURE__ */ jsxDEV19("text", {
6161
+ fg: theme.text,
6162
+ children: " "
6163
+ }, undefined, false, undefined, this),
6164
+ /* @__PURE__ */ jsxDEV19("text", {
6165
+ fg: theme.secondary,
6166
+ bold: true,
6167
+ children: "TPS (Tokens Per Second)"
6168
+ }, undefined, false, undefined, this),
6169
+ /* @__PURE__ */ jsxDEV19("text", {
6170
+ fg: theme.text,
6171
+ children: " How fast a model generates tokens after the first one."
6172
+ }, undefined, false, undefined, this),
6173
+ /* @__PURE__ */ jsxDEV19("text", {
6174
+ fg: theme.dim,
6175
+ children: " Formula: output_tokens / generation_time"
6176
+ }, undefined, false, undefined, this),
6177
+ /* @__PURE__ */ jsxDEV19("text", {
6178
+ fg: theme.success,
6179
+ children: " \u2192 Higher is better (faster streaming)"
6180
+ }, undefined, false, undefined, this),
6181
+ /* @__PURE__ */ jsxDEV19("text", {
6182
+ fg: theme.text,
6183
+ children: " "
6184
+ }, undefined, false, undefined, this),
6185
+ /* @__PURE__ */ jsxDEV19("text", {
6186
+ fg: theme.secondary,
6187
+ bold: true,
6188
+ children: "TTFT (Time To First Token)"
6189
+ }, undefined, false, undefined, this),
6190
+ /* @__PURE__ */ jsxDEV19("text", {
6191
+ fg: theme.text,
6192
+ children: " Time from request to receiving the first token."
6193
+ }, undefined, false, undefined, this),
6194
+ /* @__PURE__ */ jsxDEV19("text", {
6195
+ fg: theme.dim,
6196
+ children: " Formula: first_token_time - request_start_time"
6197
+ }, undefined, false, undefined, this),
6198
+ /* @__PURE__ */ jsxDEV19("text", {
6199
+ fg: theme.success,
6200
+ children: " \u2192 Lower is better (less waiting)"
6201
+ }, undefined, false, undefined, this),
6202
+ /* @__PURE__ */ jsxDEV19("text", {
6203
+ fg: theme.text,
6204
+ children: " "
6205
+ }, undefined, false, undefined, this),
6206
+ /* @__PURE__ */ jsxDEV19("text", {
6207
+ fg: theme.secondary,
6208
+ bold: true,
6209
+ children: "F1000 (First to 1000)"
6210
+ }, undefined, false, undefined, this),
6211
+ /* @__PURE__ */ jsxDEV19("text", {
6212
+ fg: theme.text,
6213
+ children: " Time to complete 1000 agentic requests (~300 tokens each)."
6214
+ }, undefined, false, undefined, this),
6215
+ /* @__PURE__ */ jsxDEV19("text", {
6216
+ fg: theme.dim,
6217
+ children: " Formula: 1000 \xD7 (TTFT + 300/TPS) = hours"
6218
+ }, undefined, false, undefined, this),
6219
+ /* @__PURE__ */ jsxDEV19("text", {
6220
+ fg: theme.success,
6221
+ children: " \u2192 Lower is better"
6222
+ }, undefined, false, undefined, this),
6223
+ /* @__PURE__ */ jsxDEV19("text", {
6224
+ fg: theme.text,
6225
+ children: " "
6226
+ }, undefined, false, undefined, this),
6227
+ /* @__PURE__ */ jsxDEV19("text", {
6228
+ fg: theme.text,
6229
+ children: " Why it matters: In agentic coding (Cursor, Copilot, OpenCode),"
6230
+ }, undefined, false, undefined, this),
6231
+ /* @__PURE__ */ jsxDEV19("text", {
6232
+ fg: theme.text,
6233
+ children: " models make hundreds of tool calls \u2014 TTFT adds up massively."
6234
+ }, undefined, false, undefined, this),
6235
+ /* @__PURE__ */ jsxDEV19("text", {
6236
+ fg: theme.text,
6237
+ children: " A 30 tok/s + 1s TTFT model can match a 60 tok/s + 6s TTFT model."
6238
+ }, undefined, false, undefined, this),
6239
+ /* @__PURE__ */ jsxDEV19("text", {
6240
+ fg: theme.text,
6241
+ children: " "
6242
+ }, undefined, false, undefined, this),
6243
+ /* @__PURE__ */ jsxDEV19("text", {
6244
+ fg: theme.secondary,
6245
+ bold: true,
6246
+ children: "Total Time"
6247
+ }, undefined, false, undefined, this),
6248
+ /* @__PURE__ */ jsxDEV19("text", {
6249
+ fg: theme.text,
6250
+ children: " Complete request duration from start to finish."
6251
+ }, undefined, false, undefined, this),
6252
+ /* @__PURE__ */ jsxDEV19("text", {
6253
+ fg: theme.dim,
6254
+ children: " Includes: connection, TTFT, and generation time"
6255
+ }, undefined, false, undefined, this)
6256
+ ]
6257
+ }, undefined, true, undefined, this),
6258
+ /* @__PURE__ */ jsxDEV19("box", {
6259
+ flexDirection: "column",
6260
+ border: true,
6261
+ borderStyle: "rounded",
6262
+ borderColor: theme.border,
6263
+ padding: 1,
6264
+ marginBottom: 1,
6265
+ children: [
6266
+ /* @__PURE__ */ jsxDEV19("text", {
6267
+ fg: theme.accent,
6268
+ bold: true,
6269
+ children: "LINKS"
6270
+ }, undefined, false, undefined, this),
6271
+ /* @__PURE__ */ jsxDEV19("text", {
6272
+ fg: theme.text,
6273
+ children: " "
6274
+ }, undefined, false, undefined, this),
6275
+ /* @__PURE__ */ jsxDEV19("text", {
6276
+ fg: theme.secondary,
6277
+ bold: true,
6278
+ children: "Discord Community"
6279
+ }, undefined, false, undefined, this),
6280
+ /* @__PURE__ */ jsxDEV19("text", {
6281
+ fg: theme.text,
6282
+ children: " https://discord.gg/6S7HwCxbMy"
6283
+ }, undefined, false, undefined, this),
6284
+ /* @__PURE__ */ jsxDEV19("text", {
6285
+ fg: theme.dim,
6286
+ children: " Join for help, updates, and discussions"
6287
+ }, undefined, false, undefined, this),
6288
+ /* @__PURE__ */ jsxDEV19("text", {
6289
+ fg: theme.text,
6290
+ children: " "
6291
+ }, undefined, false, undefined, this),
6292
+ /* @__PURE__ */ jsxDEV19("text", {
6293
+ fg: theme.secondary,
6294
+ bold: true,
6295
+ children: "Website & Leaderboard"
6296
+ }, undefined, false, undefined, this),
6297
+ /* @__PURE__ */ jsxDEV19("text", {
6298
+ fg: theme.text,
6299
+ children: " https://ai-speedometer.oliveowl.xyz/"
6300
+ }, undefined, false, undefined, this),
6301
+ /* @__PURE__ */ jsxDEV19("text", {
6302
+ fg: theme.dim,
6303
+ children: " Track OSS model speeds over time"
6304
+ }, undefined, false, undefined, this),
6305
+ /* @__PURE__ */ jsxDEV19("text", {
6306
+ fg: theme.text,
6307
+ children: " "
6308
+ }, undefined, false, undefined, this),
6309
+ /* @__PURE__ */ jsxDEV19("text", {
6310
+ fg: theme.secondary,
6311
+ bold: true,
6312
+ children: "GitHub"
6313
+ }, undefined, false, undefined, this),
6314
+ /* @__PURE__ */ jsxDEV19("text", {
6315
+ fg: theme.text,
6316
+ children: " https://github.com/anomaly/ai-speedometer"
6317
+ }, undefined, false, undefined, this),
6318
+ /* @__PURE__ */ jsxDEV19("text", {
6319
+ fg: theme.dim,
6320
+ children: " Source code, issues, contributions"
6321
+ }, undefined, false, undefined, this)
6322
+ ]
6323
+ }, undefined, true, undefined, this),
6324
+ /* @__PURE__ */ jsxDEV19("box", {
6325
+ flexDirection: "column",
6326
+ border: true,
6327
+ borderStyle: "rounded",
6328
+ borderColor: theme.border,
6329
+ padding: 1,
6330
+ marginBottom: 1,
6331
+ children: [
6332
+ /* @__PURE__ */ jsxDEV19("text", {
6333
+ fg: theme.accent,
6334
+ bold: true,
6335
+ children: "TIPS"
6336
+ }, undefined, false, undefined, this),
6337
+ /* @__PURE__ */ jsxDEV19("text", {
6338
+ fg: theme.text,
6339
+ children: " "
6340
+ }, undefined, false, undefined, this),
6341
+ /* @__PURE__ */ jsxDEV19("text", {
6342
+ fg: theme.text,
6343
+ children: " \u2022 Press [T] anytime to open the theme picker"
6344
+ }, undefined, false, undefined, this),
6345
+ /* @__PURE__ */ jsxDEV19("text", {
6346
+ fg: theme.text,
6347
+ children: " \u2022 Use --log flag to save raw SSE data for debugging"
6348
+ }, undefined, false, undefined, this),
6349
+ /* @__PURE__ */ jsxDEV19("text", {
6350
+ fg: theme.text,
6351
+ children: " \u2022 Run headless with ai-speedometer-headless for CI/CD"
6352
+ }, undefined, false, undefined, this),
6353
+ /* @__PURE__ */ jsxDEV19("text", {
6354
+ fg: theme.text,
6355
+ children: " \u2022 [*] in results means token count was estimated"
6356
+ }, undefined, false, undefined, this)
6357
+ ]
6358
+ }, undefined, true, undefined, this),
6359
+ /* @__PURE__ */ jsxDEV19("box", {
6360
+ flexDirection: "row",
6361
+ justifyContent: "center",
6362
+ marginTop: 1,
6363
+ children: /* @__PURE__ */ jsxDEV19("text", {
6364
+ fg: theme.dim,
6365
+ children: "Press [Q] or [Esc] to return to main menu"
6366
+ }, undefined, false, undefined, this)
6367
+ }, undefined, false, undefined, this)
6368
+ ]
6369
+ }, undefined, true, undefined, this)
6370
+ }, undefined, false, undefined, this)
6371
+ ]
6372
+ }, undefined, true, undefined, this)
6373
+ }, undefined, false, undefined, this);
6374
+ }
6375
+ var init_FAQScreen = __esm(() => {
6376
+ init_useAppKeyboard();
5180
6377
  init_AppContext();
6378
+ init_ThemeContext();
5181
6379
  });
5182
6380
 
5183
6381
  // src/tui/App.tsx
5184
- import { useKeyboard as useKeyboard10, useRenderer as useRenderer3 } from "@opentui/react";
5185
- import { jsxDEV as jsxDEV15 } from "@opentui/react/jsx-dev-runtime";
6382
+ import { useKeyboard as useKeyboard3, useRenderer as useRenderer3 } from "@opentui/react";
6383
+ import { jsxDEV as jsxDEV20 } from "@opentui/react/jsx-dev-runtime";
5186
6384
  function getHints(screen, benchResults) {
5187
6385
  switch (screen) {
5188
6386
  case "main-menu":
5189
- return ["[\u2191\u2193] navigate", "[Enter] select", "[Ctrl+C] quit"];
6387
+ return ["[\u2191\u2193] navigate", "[Enter] select", "[T] theme", "[Ctrl+C] quit"];
5190
6388
  case "model-menu":
5191
6389
  return ["[\u2191\u2193] navigate", "[Enter] select", "[Q] back"];
5192
6390
  case "model-select":
@@ -5197,6 +6395,8 @@ function getHints(screen, benchResults) {
5197
6395
  }
5198
6396
  case "list-providers":
5199
6397
  return ["[\u2191\u2193] scroll", "[Q] back"];
6398
+ case "faq":
6399
+ return ["[\u2191\u2193] scroll", "[Q] back"];
5200
6400
  case "add-verified":
5201
6401
  return ["[\u2191\u2193] navigate", "[Enter] select", "[Q] back"];
5202
6402
  case "add-custom":
@@ -5211,59 +6411,78 @@ function ActiveScreen() {
5211
6411
  const { state } = useAppContext();
5212
6412
  switch (state.screen) {
5213
6413
  case "main-menu":
5214
- return /* @__PURE__ */ jsxDEV15(MainMenuScreen, {}, undefined, false, undefined, this);
6414
+ return /* @__PURE__ */ jsxDEV20(MainMenuScreen, {}, undefined, false, undefined, this);
5215
6415
  case "model-menu":
5216
- return /* @__PURE__ */ jsxDEV15(ModelMenuScreen, {}, undefined, false, undefined, this);
6416
+ return /* @__PURE__ */ jsxDEV20(ModelMenuScreen, {}, undefined, false, undefined, this);
5217
6417
  case "model-select":
5218
- return /* @__PURE__ */ jsxDEV15(ModelSelectScreen, {}, undefined, false, undefined, this);
6418
+ return /* @__PURE__ */ jsxDEV20(ModelSelectScreen, {}, undefined, false, undefined, this);
5219
6419
  case "benchmark":
5220
- return /* @__PURE__ */ jsxDEV15(BenchmarkScreen, {}, undefined, false, undefined, this);
6420
+ return /* @__PURE__ */ jsxDEV20(BenchmarkScreen, {}, undefined, false, undefined, this);
5221
6421
  case "add-verified":
5222
- return /* @__PURE__ */ jsxDEV15(AddVerifiedScreen, {}, undefined, false, undefined, this);
6422
+ return /* @__PURE__ */ jsxDEV20(AddVerifiedScreen, {}, undefined, false, undefined, this);
5223
6423
  case "add-custom":
5224
- return /* @__PURE__ */ jsxDEV15(AddCustomScreen, {}, undefined, false, undefined, this);
6424
+ return /* @__PURE__ */ jsxDEV20(AddCustomScreen, {}, undefined, false, undefined, this);
5225
6425
  case "add-models":
5226
- return /* @__PURE__ */ jsxDEV15(AddModelsScreen, {}, undefined, false, undefined, this);
6426
+ return /* @__PURE__ */ jsxDEV20(AddModelsScreen, {}, undefined, false, undefined, this);
5227
6427
  case "list-providers":
5228
- return /* @__PURE__ */ jsxDEV15(ListProvidersScreen, {}, undefined, false, undefined, this);
6428
+ return /* @__PURE__ */ jsxDEV20(ListProvidersScreen, {}, undefined, false, undefined, this);
6429
+ case "faq":
6430
+ return /* @__PURE__ */ jsxDEV20(FAQScreen, {}, undefined, false, undefined, this);
5229
6431
  }
5230
6432
  }
5231
6433
  function Shell() {
5232
6434
  const renderer = useRenderer3();
5233
6435
  const { state } = useAppContext();
5234
- useKeyboard10((key) => {
6436
+ const theme = useTheme();
6437
+ const { modalOpen, setModalOpen } = useModal();
6438
+ useKeyboard3((key) => {
5235
6439
  if (key.ctrl && key.name === "c") {
5236
6440
  renderer.destroy();
6441
+ return;
6442
+ }
6443
+ if (!key.ctrl && !key.meta && key.sequence === "T") {
6444
+ setModalOpen(!modalOpen);
5237
6445
  }
5238
6446
  });
5239
- return /* @__PURE__ */ jsxDEV15("box", {
6447
+ return /* @__PURE__ */ jsxDEV20("box", {
5240
6448
  flexDirection: "column",
5241
6449
  height: "100%",
5242
6450
  width: "100%",
5243
- backgroundColor: "#1a1b26",
6451
+ backgroundColor: theme.background,
5244
6452
  children: [
5245
- /* @__PURE__ */ jsxDEV15(Header, {
6453
+ /* @__PURE__ */ jsxDEV20(Header, {
5246
6454
  screen: state.screen
5247
6455
  }, undefined, false, undefined, this),
5248
- /* @__PURE__ */ jsxDEV15("box", {
6456
+ /* @__PURE__ */ jsxDEV20("box", {
5249
6457
  flexGrow: 1,
5250
6458
  flexDirection: "column",
5251
- children: /* @__PURE__ */ jsxDEV15(ActiveScreen, {}, undefined, false, undefined, this)
6459
+ children: /* @__PURE__ */ jsxDEV20(ActiveScreen, {}, undefined, false, undefined, this)
5252
6460
  }, undefined, false, undefined, this),
5253
- /* @__PURE__ */ jsxDEV15(Footer, {
6461
+ /* @__PURE__ */ jsxDEV20(Footer, {
5254
6462
  hints: getHints(state.screen, state.benchResults)
6463
+ }, undefined, false, undefined, this),
6464
+ modalOpen && /* @__PURE__ */ jsxDEV20(ThemePicker, {
6465
+ onClose: () => setModalOpen(false)
5255
6466
  }, undefined, false, undefined, this)
5256
6467
  ]
5257
6468
  }, undefined, true, undefined, this);
5258
6469
  }
5259
- function App({ logMode = false }) {
5260
- return /* @__PURE__ */ jsxDEV15(AppProvider, {
5261
- logMode,
5262
- children: /* @__PURE__ */ jsxDEV15(Shell, {}, undefined, false, undefined, this)
6470
+ function App({ logMode = false, theme = "tokyonight" }) {
6471
+ return /* @__PURE__ */ jsxDEV20(ThemeProvider, {
6472
+ name: theme,
6473
+ children: /* @__PURE__ */ jsxDEV20(ModalProvider, {
6474
+ children: /* @__PURE__ */ jsxDEV20(AppProvider, {
6475
+ logMode,
6476
+ children: /* @__PURE__ */ jsxDEV20(Shell, {}, undefined, false, undefined, this)
6477
+ }, undefined, false, undefined, this)
6478
+ }, undefined, false, undefined, this)
5263
6479
  }, undefined, false, undefined, this);
5264
6480
  }
5265
6481
  var init_App = __esm(() => {
5266
6482
  init_AppContext();
6483
+ init_ThemeContext();
6484
+ init_ModalContext();
6485
+ init_ThemePicker();
5267
6486
  init_Header();
5268
6487
  init_Footer();
5269
6488
  init_MainMenuScreen();
@@ -5274,6 +6493,7 @@ var init_App = __esm(() => {
5274
6493
  init_AddCustomScreen();
5275
6494
  init_AddModelsScreen();
5276
6495
  init_ListProvidersScreen();
6496
+ init_FAQScreen();
5277
6497
  });
5278
6498
 
5279
6499
  // src/tui/index.tsx
@@ -5283,8 +6503,10 @@ __export(exports_tui, {
5283
6503
  });
5284
6504
  import { createCliRenderer } from "@opentui/core";
5285
6505
  import { createRoot } from "@opentui/react";
5286
- import { jsxDEV as jsxDEV16 } from "@opentui/react/jsx-dev-runtime";
6506
+ import { jsxDEV as jsxDEV21 } from "@opentui/react/jsx-dev-runtime";
5287
6507
  async function startTui(logMode = false) {
6508
+ const { readThemeFromConfig: readThemeFromConfig2 } = await Promise.resolve().then(() => (init_ai_config(), exports_ai_config));
6509
+ const theme = await readThemeFromConfig2();
5288
6510
  const renderer = await createCliRenderer({
5289
6511
  exitOnCtrlC: false
5290
6512
  });
@@ -5298,8 +6520,9 @@ async function startTui(logMode = false) {
5298
6520
  renderer.destroy();
5299
6521
  process.exit(0);
5300
6522
  });
5301
- createRoot(renderer).render(/* @__PURE__ */ jsxDEV16(App, {
5302
- logMode
6523
+ createRoot(renderer).render(/* @__PURE__ */ jsxDEV21(App, {
6524
+ logMode,
6525
+ theme
5303
6526
  }, undefined, false, undefined, this));
5304
6527
  }
5305
6528
  var ENABLE_BRACKETED_PASTE = "\x1B[?2004h", DISABLE_BRACKETED_PASTE = "\x1B[?2004l";