free-coding-models 0.5.6 → 0.5.9

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 (49) hide show
  1. package/README.md +14 -9
  2. package/changelog/v0.5.7.md +20 -0
  3. package/changelog/v0.5.8.md +23 -0
  4. package/package.json +1 -1
  5. package/src/core/endpoint-installer.js +3 -3
  6. package/src/core/tool-launchers.js +2 -2
  7. package/web/dist/assets/index-27IYGKp2.js +39 -0
  8. package/web/dist/assets/index-DKmmiDip.css +1 -0
  9. package/web/dist/index.html +2 -2
  10. package/web/server.js +386 -1
  11. package/web/src/App.jsx +145 -26
  12. package/web/src/components/analytics/AnalyticsView.jsx +4 -0
  13. package/web/src/components/analytics/TokenUsagePanel.jsx +105 -0
  14. package/web/src/components/analytics/TokenUsagePanel.module.css +126 -0
  15. package/web/src/components/atoms/TierBadge.module.css +3 -3
  16. package/web/src/components/dashboard/DetailPanel.jsx +29 -4
  17. package/web/src/components/dashboard/DetailPanel.module.css +26 -0
  18. package/web/src/components/dashboard/FilterBar.jsx +17 -2
  19. package/web/src/components/dashboard/FilterBar.module.css +17 -0
  20. package/web/src/components/dashboard/ModelTable.jsx +17 -5
  21. package/web/src/components/dashboard/ModelTable.module.css +14 -1
  22. package/web/src/components/help/HelpView.jsx +1 -1
  23. package/web/src/components/install/InstallEndpointsView.jsx +278 -0
  24. package/web/src/components/install/InstallEndpointsView.module.css +351 -0
  25. package/web/src/components/installed/InstalledModelsView.jsx +89 -0
  26. package/web/src/components/installed/InstalledModelsView.module.css +200 -0
  27. package/web/src/components/launch/IncompatibleFallbackModal.jsx +69 -0
  28. package/web/src/components/launch/LaunchButton.jsx +30 -0
  29. package/web/src/components/launch/LaunchButton.module.css +35 -0
  30. package/web/src/components/launch/LaunchModal.module.css +125 -0
  31. package/web/src/components/layout/Header.jsx +70 -11
  32. package/web/src/components/layout/Header.module.css +62 -2
  33. package/web/src/components/recommend/RecommendView.jsx +121 -0
  34. package/web/src/components/recommend/RecommendView.module.css +55 -0
  35. package/web/src/components/router/RouterView.jsx +286 -0
  36. package/web/src/components/router/RouterView.module.css +357 -0
  37. package/web/src/components/tools/ToolPicker.jsx +86 -0
  38. package/web/src/components/tools/ToolPicker.module.css +84 -0
  39. package/web/src/global.css +23 -0
  40. package/web/src/hooks/urlState.constants.js +3 -0
  41. package/web/src/hooks/useInstalledModels.js +42 -0
  42. package/web/src/hooks/useRecommend.js +67 -0
  43. package/web/src/hooks/useRouterDashboard.js +133 -0
  44. package/web/src/hooks/useTokenUsage.js +103 -0
  45. package/web/src/hooks/useToolMode.js +77 -0
  46. package/web/src/hooks/useUrlState.js +4 -3
  47. package/web/src/utils/m3.js +55 -0
  48. package/web/dist/assets/index-Blp9QJev.js +0 -39
  49. package/web/dist/assets/index-Cz_aCLTR.css +0 -1
@@ -0,0 +1 @@
1
+ ._wrap_3zy19_5{align-items:center;gap:4px;display:inline-flex;position:relative}._trigger_3zy19_11,._cycle_3zy19_12{border:1px solid var(--color-border);background:var(--color-surface);height:30px;color:var(--color-text);cursor:pointer;justify-content:center;align-items:center;transition:background .15s,border-color .15s,color .15s;display:inline-flex}._trigger_3zy19_11{border-radius:6px;gap:6px;padding:0 9px;font-size:12px;font-weight:700}._cycle_3zy19_12{border-radius:6px;width:30px}._trigger_3zy19_11:hover,._cycle_3zy19_12:hover{background:var(--color-bg-hover);border-color:var(--color-accent);color:var(--color-accent)}._emoji_3zy19_40{font-size:14px;line-height:1}._label_3zy19_41{white-space:nowrap}._menu_3zy19_42{border:1px solid var(--color-border);background:var(--color-bg-elevated);z-index:250;border-radius:10px;width:280px;max-height:min(520px,100vh - 90px);padding:5px;position:absolute;top:calc(100% + 7px);right:0;overflow:auto;box-shadow:0 14px 36px #00000061}._item_3zy19_56{width:100%;color:var(--color-text);cursor:pointer;text-align:left;background:0 0;border:0;border-radius:7px;align-items:center;gap:9px;padding:8px 9px;display:flex}._item_3zy19_56:hover{background:var(--color-bg-hover)}._itemActive_3zy19_70{background:var(--color-accent-dim);color:var(--color-accent)}._itemEmoji_3zy19_74{text-align:center;width:22px;font-size:16px}._itemText_3zy19_75{flex-direction:column;flex:1;gap:2px;min-width:0;display:flex}._itemText_3zy19_75 strong{font-size:12px;font-weight:800}._itemText_3zy19_75 small{color:var(--color-text-dim);font-family:var(--font-mono);font-size:10px}._activeDot_3zy19_78{color:var(--color-accent);font-size:10px}._compact_3zy19_79 ._trigger_3zy19_11{justify-content:flex-start;width:100%}._compact_3zy19_79 ._menu_3zy19_42{left:0;right:auto}@media (width<=1024px){._label_3zy19_41{display:none}._trigger_3zy19_11{padding:0 8px}}._header_3lvj2_11{z-index:100;height:var(--header-h,60px);background:var(--color-bg-card);-webkit-backdrop-filter:blur(20px)saturate(1.5);border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:center;gap:16px;width:100%;padding:0 20px;display:flex;position:sticky;top:0}._left_3lvj2_28{flex-shrink:0;align-items:center;gap:14px;display:flex}._center_3lvj2_35{flex:1;min-width:0;max-width:480px}._right_3lvj2_41{flex-shrink:0;align-items:center;gap:8px;display:flex}._logo_3lvj2_49{align-items:center;gap:6px;display:flex}._logoIcon_3lvj2_50{color:var(--color-brand);font-family:var(--font-mono);align-items:center;font-size:20px;font-weight:900;display:flex}._logoText_3lvj2_58{color:var(--color-text);align-items:center;font-size:14px;font-weight:700;display:flex}._logoTextHighlight_3lvj2_64{color:var(--color-brand)}._version_3lvj2_65{font-size:10px;font-weight:500;font-family:var(--font-mono);color:var(--color-text-muted);background:var(--color-surface);border:1px solid var(--color-border);border-radius:999px;padding:2px 6px}._nav_3lvj2_72{border-left:1px solid var(--color-border);align-items:center;gap:2px;height:36px;margin-left:8px;padding-left:12px;display:flex}._navBtn_3lvj2_82{height:30px;font-size:12px;font-weight:600;font-family:var(--font-sans);color:var(--color-text-muted);cursor:pointer;white-space:nowrap;background:0 0;border:1px solid #0000;border-radius:6px;align-items:center;gap:5px;padding:0 10px;transition:background .15s,color .15s,border-color .15s;display:inline-flex}._navBtn_3lvj2_82:hover{background:var(--color-bg-hover);color:var(--color-text)}._navBtnActive_3lvj2_103{background:var(--color-accent-dim);color:var(--color-accent);border-color:var(--color-border);font-weight:700}._navBtnActive_3lvj2_103:hover{background:var(--color-accent-dim);color:var(--color-accent)}._comingBadge_3lvj2_116{font-size:9px;font-weight:700;font-family:var(--font-mono);color:var(--color-text-dim);background:var(--color-surface);border:1px solid var(--color-border);text-transform:uppercase;letter-spacing:.3px;border-radius:3px;margin-left:2px;padding:1px 4px;line-height:1}._menuWrap_3lvj2_132{position:relative}._menuTrigger_3lvj2_133{justify-content:center;width:30px;padding:0}._menuPopover_3lvj2_138{background:var(--color-bg-elevated);border:1px solid var(--color-border);z-index:200;border-radius:8px;flex-direction:column;gap:1px;min-width:200px;padding:4px;display:flex;position:absolute;top:calc(100% + 6px);right:0;box-shadow:0 8px 24px #00000052}._menuItem_3lvj2_153{width:100%;color:var(--color-text);cursor:pointer;text-align:left;background:0 0;border:none;border-radius:5px;align-items:center;gap:8px;padding:7px 10px;font-size:12px;font-weight:500;transition:background .1s;display:flex}._menuItem_3lvj2_153:hover{background:var(--color-bg-hover)}._menuItem_3lvj2_153>span:first-of-type{flex:1}._searchBar_3lvj2_173{background:var(--color-surface);border:1px solid var(--color-border);border-radius:8px;align-items:center;gap:8px;height:34px;padding:0 12px;transition:border-color .15s,box-shadow .15s;display:flex}._searchBar_3lvj2_173:focus-within{border-color:var(--color-accent);box-shadow:0 0 0 3px var(--color-accent-glow)}._searchIcon_3lvj2_183{flex-shrink:0;font-size:14px}._searchInput_3lvj2_184{color:var(--color-text);font-size:13px;font-family:var(--font-sans);background:0 0;border:none;outline:none;flex:1;min-width:0}._searchInput_3lvj2_184::placeholder{color:var(--color-text-dim)}._iconBtn_3lvj2_192{border:1px solid var(--color-border);background:var(--color-surface);color:var(--color-text);cursor:pointer;border-radius:6px;justify-content:center;align-items:center;padding:6px 8px;font-size:16px;transition:all .15s;display:inline-flex}._iconBtn_3lvj2_192:hover{background:var(--color-bg-hover);border-color:var(--color-border-hover)}._cmdkBtn_3lvj2_202{border:1px solid var(--color-border);background:var(--color-surface);height:30px;color:var(--color-text);cursor:pointer;font-size:12px;font-weight:600;font-family:var(--font-mono);border-radius:6px;align-items:center;gap:6px;padding:0 10px;transition:all .15s;display:inline-flex}._cmdkBtn_3lvj2_202:hover{border-color:var(--color-accent);background:var(--color-bg-hover)}._cmdkLabel_3lvj2_215{letter-spacing:.5px;font-size:11px}._benchmarkBtn_3lvj2_218{border:1px solid var(--color-border);background:var(--color-surface);height:30px;color:var(--color-text);cursor:pointer;font-size:12px;font-weight:700;font-family:var(--font-mono);border-radius:6px;align-items:center;gap:6px;padding:0 12px;transition:all .15s;display:inline-flex}._benchmarkBtn_3lvj2_218:hover{color:#0f8;background:#00ff8814;border-color:#0f8}._benchmarkActive_3lvj2_228{cursor:not-allowed;color:#0f8!important;background:#00ff881f!important;border-color:#0f8!important}._benchmarkRunning_3lvj2_233{align-items:center;gap:6px;display:inline-flex}@keyframes _spin_3lvj2_235{to{transform:rotate(360deg)}}._spinner_3lvj2_235{border:2px solid #00ff884d;border-top-color:#0f8;border-radius:50%;flex-shrink:0;width:10px;height:10px;animation:.8s linear infinite _spin_3lvj2_235;display:inline-block}[data-theme=light] ._benchmarkBtn_3lvj2_218:hover{color:#008f4d;background:#008f4d0f;border-color:#008f4d}[data-theme=light] ._benchmarkActive_3lvj2_228{color:#008f4d!important;background:#008f4d1a!important;border-color:#008f4d!important}[data-theme=light] ._spinner_3lvj2_235{border-color:#008f4d #0000001a #0000001a}@media (width<=1024px){._navBtn_3lvj2_82>span:not(._comingBadge_3lvj2_116){display:none}._navBtn_3lvj2_82{padding:0 8px}._center_3lvj2_35{max-width:320px}}@media (width<=768px){._center_3lvj2_35,._logoText_3lvj2_58,._cmdkLabel_3lvj2_215,._benchmarkBtn_3lvj2_218>span:not(._benchmarkRunning_3lvj2_233),._nav_3lvj2_72{display:none}._hamburgerBtn_3lvj2_268{display:flex}}@media (width<=560px){._version_3lvj2_65{display:none}}._hamburgerBtn_3lvj2_268{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-md);width:34px;height:34px;color:var(--color-text-muted);cursor:pointer;justify-content:center;align-items:center;margin-left:8px;display:none}._hamburgerBtn_3lvj2_268:hover{color:var(--color-text);background:var(--color-bg-hover)}._mobileNav_3lvj2_290{top:var(--header-h,60px);background:var(--color-bg-elevated);border-bottom:1px solid var(--color-border);z-index:150;flex-direction:column;gap:2px;padding:8px 16px 16px;display:flex;position:absolute;left:0;right:0;box-shadow:0 8px 24px #0000004d}._mobileNavItem_3lvj2_305{color:var(--color-text-muted);border-radius:var(--radius-md);cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:10px;width:100%;padding:10px 12px;font-size:13px;font-weight:600;display:flex}._mobileNavItem_3lvj2_305:hover{background:var(--color-bg-hover);color:var(--color-text)}._mobileNavActive_3lvj2_322{color:var(--color-accent);background:var(--color-accent-dim)}._mobileNavDivider_3lvj2_327{background:var(--color-border);height:1px;margin:6px 0}._footer_1uw54_1{z-index:1;border-top:1px solid var(--color-border);color:var(--color-text-dim);justify-content:space-between;align-items:center;padding:16px 24px;font-size:12px;display:flex;position:relative}._left_1uw54_8 a,._right_1uw54_8 a{color:var(--color-text-dim);text-decoration:none}._left_1uw54_8 a:hover,._right_1uw54_8 a:hover{color:var(--color-accent)}._right_1uw54_8{gap:16px;display:flex}._filters_1kabq_9{z-index:99;background:var(--color-bg-card);border-bottom:1px solid var(--color-border);-webkit-backdrop-filter:blur(20px)saturate(1.5);flex-wrap:wrap;align-items:center;gap:14px;padding:10px 20px;display:flex;position:sticky;top:60px}._group_1kabq_19{align-items:center;gap:6px;display:flex}._filterLabel_1kabq_21{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.5px;white-space:nowrap;font-size:10px;font-weight:700}._chipRow_1kabq_28{gap:3px;display:flex}._chip_1kabq_28{font-size:11px;font-weight:600;font-family:var(--font-mono);border:1px solid var(--color-border);background:var(--color-surface);color:var(--color-text-muted);cursor:pointer;white-space:nowrap;border-radius:5px;padding:4px 8px;transition:all .15s}._chip_1kabq_28:hover{background:var(--color-bg-hover);color:var(--color-text)}._chipActive_1kabq_37{font-weight:700;background:var(--color-accent)!important;color:var(--color-bg)!important;border-color:var(--color-accent)!important}._select_1kabq_43,._providerSelect_1kabq_43{background:var(--color-surface);color:var(--color-text);border:1px solid var(--color-border);font-size:11px;font-family:var(--font-sans);cursor:pointer;border-radius:5px;outline:none;min-width:130px;padding:4px 8px}._select_1kabq_43:focus,._providerSelect_1kabq_43:focus{border-color:var(--color-accent)}._toolStatus_1kabq_52{border:1px solid var(--color-border);background:var(--color-surface);color:var(--color-text);white-space:nowrap;border-radius:5px;align-items:center;gap:6px;padding:4px 8px;font-size:11px;display:inline-flex}._toolStatus_1kabq_52 strong{font-size:11px;font-weight:800}._spacer_1kabq_70{flex:1}._resetBtn_1kabq_72{font-size:11px;font-weight:700;font-family:var(--font-mono);border:1px solid var(--color-border-hover);background:var(--color-accent-dim);color:var(--color-text);cursor:pointer;border-radius:5px;align-items:center;gap:5px;padding:4px 9px;transition:all .15s;display:inline-flex}._resetBtn_1kabq_72:hover{background:var(--color-accent);color:var(--color-bg)}._resetBadge_1kabq_85{background:var(--color-bg);min-width:16px;height:16px;color:var(--color-accent);border-radius:999px;justify-content:center;align-items:center;padding:0 4px;font-size:9px;font-weight:800;display:inline-flex}._customFilterChip_1kabq_96{font-size:11px;font-weight:600;font-family:var(--font-mono);border:1px solid var(--color-accent);background:var(--color-accent-dim);color:var(--color-accent);border-radius:5px;align-items:center;gap:6px;max-width:240px;padding:3px 4px 3px 8px;display:inline-flex}._customFilterIcon_1kabq_106{flex-shrink:0;display:inline-flex}._customFilterLabel_1kabq_107{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._customFilterClear_1kabq_112{width:18px;height:18px;color:var(--color-accent);cursor:pointer;background:0 0;border:none;border-radius:3px;flex-shrink:0;justify-content:center;align-items:center;display:inline-flex}._customFilterClear_1kabq_112:hover{background:var(--color-accent);color:var(--color-bg)}._pingRow_1kabq_125{gap:3px;display:flex}._pingBtn_1kabq_126{font-size:11px;font-weight:600;font-family:var(--font-mono);border:1px solid var(--color-border);background:var(--color-surface);color:var(--color-text-muted);cursor:pointer;white-space:nowrap;border-radius:5px;padding:4px 8px;transition:all .15s}._pingBtn_1kabq_126:hover{background:var(--color-bg-hover);color:var(--color-text);border-color:var(--color-text-muted)}._pingBtnActive_1kabq_134{font-weight:700;background:var(--color-bg-hover)!important;color:var(--ping-active-color,var(--color-accent))!important;border-color:var(--ping-active-color,var(--color-accent))!important}._nextPing_1kabq_142{font-size:11px;font-family:var(--font-mono);border:1px solid var(--color-border);background:var(--color-surface);border-radius:5px;align-items:center;gap:6px;padding:4px 8px;display:flex}._nextPingLabel_1kabq_150{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.5px;font-size:10px;font-weight:500}._nextPingTime_1kabq_154{color:var(--color-text);text-align:right;font-variant-numeric:tabular-nums;min-width:32px;font-size:13px;font-weight:700}._pingingDot_1kabq_160{background:#f46;border-radius:50%;flex-shrink:0;width:7px;height:7px;animation:.6s ease-in-out infinite _pulseDot_1kabq_1}@keyframes _pulseDot_1kabq_1{0%,to{box-shadow:0 0 0 0 var(--color-accent-glow)}50%{box-shadow:0 0 0 6px #0000}}._live_1kabq_171{color:var(--color-accent);text-transform:uppercase;letter-spacing:1px;align-items:center;gap:5px;font-size:10px;font-weight:700;display:flex}._liveDot_1kabq_176{background:var(--color-accent);border-radius:50%;width:7px;height:7px;animation:2s ease-in-out infinite _pulseDot_1kabq_1}._benchmarkBar_1kabq_182{background:#b400ff1f;border:1px solid #b400ff66;border-radius:6px;flex-shrink:0;align-items:center;gap:10px;width:100%;margin-bottom:4px;padding:6px 12px;display:flex}._benchmarkLabel_1kabq_192{color:#b400ff;font-size:11px;font-weight:700;font-family:var(--font-mono);white-space:nowrap;align-items:center;gap:5px;display:flex}._benchmarkSpinner_1kabq_198{font-size:12px;line-height:1;animation:.8s linear infinite _spinSp_1kabq_1;display:inline-block}._benchmarkCount_1kabq_203{opacity:.8;font-size:10px}._benchmarkTrack_1kabq_204{background:#ffffff1a;border-radius:3px;flex:1;width:120px;height:5px;overflow:hidden}._benchmarkFill_1kabq_210{background:linear-gradient(90deg,#b400ff,#f0f);border-radius:3px;height:100%;transition:width .5s}._benchmarkPct_1kabq_216{color:#b400ff;font-size:11px;font-weight:700;font-family:var(--font-mono);text-align:right;min-width:32px}@keyframes _spinSp_1kabq_1{0%{transform:rotate(0)}to{transform:rotate(360deg)}}._mood_f9he5_1{text-align:center;width:20px;font-size:14px;display:inline-block}._badge_5yv5w_1{text-align:center;border-radius:4px;min-width:32px;padding:2px 8px;font-family:JetBrains Mono,monospace;font-size:11px;font-weight:700;display:inline-block}._tier_splus_5yv5w_11{color:gold;background:#ffd70026;border:1px solid #ffd7004d}._tier_s_5yv5w_11{color:#ff8c00;background:#ff8c001f;border:1px solid #ff8c0040}._tier_aplus_5yv5w_13{color:#00c8ff;background:#00c8ff1a;border:1px solid #00c8ff33}._tier_a_5yv5w_13{color:#3ddc84;background:#3ddc841a;border:1px solid #3ddc8433}._tier_aminus_5yv5w_15{color:#7ecf7e;background:#7ecf7e1a;border:1px solid #7ecf7e33}._tier_bplus_5yv5w_16{color:#b8b8d8;background:#a8a8c81a;border:1px solid #a8a8c826}._tier_b_5yv5w_16{color:#a0a0b8;background:#8080981a;border:1px solid #80809826}._tier_c_5yv5w_18{color:#909098;background:#6060781a;border:1px solid #60607826}[data-theme=light] ._tier_splus_5yv5w_11{color:#7a5e00;border-color:#b0880066}[data-theme=light] ._tier_s_5yv5w_11{color:#a14a00;border-color:#c45a0066}[data-theme=light] ._tier_aplus_5yv5w_13{color:#005d8a;border-color:#0073a866}[data-theme=light] ._tier_a_5yv5w_13{color:#1f7a3e;border-color:#1f7a3e66}[data-theme=light] ._tier_aminus_5yv5w_15{color:#2f7a2f;border-color:#2f7a2f66}[data-theme=light] ._tier_bplus_5yv5w_16{color:#4a4a72;border-color:#5a5a8a66}[data-theme=light] ._tier_b_5yv5w_16{color:#556;border-color:#5566}[data-theme=light] ._tier_c_5yv5w_18{color:#5a5a6a;border-color:#6a6a7a66}._dot_1u2qu_1{vertical-align:middle;border-radius:50%;width:8px;height:8px;margin-right:6px;display:inline-block}._up_1u2qu_9{background:#0f8;box-shadow:0 0 6px #0f86}._down_1u2qu_10,._timeout_1u2qu_11{background:#f44}._pending_1u2qu_12{background:#555570;animation:1.5s ease-in-out infinite _pulse_1u2qu_1}@keyframes _pulse_1u2qu_1{0%,to{box-shadow:0 0 #76b90040}50%{box-shadow:0 0 0 6px #0000}}[data-theme=light] ._up_1u2qu_9{background:#008f4d;box-shadow:0 0 4px #008f4d59}[data-theme=light] ._down_1u2qu_10,[data-theme=light] ._timeout_1u2qu_11{background:#c8143a}[data-theme=light] ._pending_1u2qu_12{background:#889}._cell_ptyq8_1{font-family:var(--font-mono);align-items:center;gap:4px;min-width:54px;font-size:12px;font-weight:600;display:inline-flex}._fast_ptyq8_11{color:#0f8}._medium_ptyq8_12{color:#fa0}._slow_ptyq8_13{color:#f44}._none_ptyq8_14{color:var(--color-text-dim)}@keyframes _pingPulse_ptyq8_1{0%,to{opacity:1}50%{opacity:.3}}@keyframes _pingRing_ptyq8_1{0%{opacity:1;transform:rotate(0)scale(1)}70%{opacity:.6;transform:rotate(180deg)scale(.6)}to{opacity:1;transform:rotate(360deg)scale(1)}}._spinner_ptyq8_26{border:1.5px solid #00ff8840;border-top-color:#0f8;border-radius:50%;flex-shrink:0;width:10px;height:10px;animation:.8s linear infinite _pingRing_ptyq8_1;display:inline-block}[data-theme=light] ._fast_ptyq8_11{color:#008f4d}[data-theme=light] ._medium_ptyq8_12{color:#b86b00}[data-theme=light] ._slow_ptyq8_13{color:#c8143a}[data-theme=light] ._spinner_ptyq8_26{border-color:#008f4d #0000001f #0000001f}._wrapper_1t2v0_7{vertical-align:middle;flex-shrink:0;justify-content:center;align-items:center;line-height:0;display:inline-flex;position:relative}._key_1t2v0_17{color:#fa0;z-index:1;filter:drop-shadow(0 0 1px #ffaa0059);position:relative}._slash_1t2v0_24{pointer-events:none;z-index:2;margin:auto;position:absolute;inset:0}._cell_odwix_7{font-family:var(--font-mono);letter-spacing:.2px;white-space:nowrap;text-overflow:ellipsis;align-items:center;gap:5px;font-size:11px;font-weight:600;display:inline-flex;overflow:hidden}._up_odwix_19{color:#0f8}._warning_odwix_20{color:#fa0}._error_odwix_21{color:#f44}._errorBold_odwix_22{color:#f44;font-weight:800}._dim_odwix_23{color:var(--color-text-dim)}._noKey_odwix_30{color:#fa0;letter-spacing:.4px;background:#ffaa002e;border:1px solid #ffaa0073;border-radius:4px;padding:1px 7px;font-size:12px;font-weight:700}._noKeyText_odwix_40{letter-spacing:.4px;font-weight:700}[data-theme=light] ._noKey_odwix_30{color:#b86b00;background:#ffaa0040;border-color:#ffaa008c}[data-theme=light] ._up_odwix_19{color:#008f4d}[data-theme=light] ._warning_odwix_20{color:#b86b00}[data-theme=light] ._error_odwix_21,[data-theme=light] ._errorBold_odwix_22{color:#c02323}[data-theme=light] ._dim_odwix_23{color:#888}._cell_18ls4_1{align-items:center;gap:6px;display:flex}._bar_18ls4_2{background:var(--color-surface);border-radius:3px;width:48px;height:6px;overflow:hidden}._fill_18ls4_3{border-radius:3px;height:100%;transition:width .25s cubic-bezier(.16,1,.3,1)}._high_18ls4_4{background:linear-gradient(90deg,#0f8,#76b900)}._mid_18ls4_5{background:linear-gradient(90deg,#fa0,#ff8c00)}._low_18ls4_6{background:linear-gradient(90deg,#f44,#c00)}._value_18ls4_7{font-family:JetBrains Mono,monospace;font-size:12px;font-weight:600}._none_18ls4_8{color:var(--color-text-dim)}[data-theme=light] ._high_18ls4_4{background:linear-gradient(90deg,#008f4d,#4a7a00)}[data-theme=light] ._mid_18ls4_5{background:linear-gradient(90deg,#b86b00,#c45a00)}[data-theme=light] ._low_18ls4_6{background:linear-gradient(90deg,#c8143a,#900)}._badge_5z8g9_5{white-space:nowrap;border-radius:999px;align-items:center;gap:3px;padding:2px 7px;font-size:11px;font-weight:700;display:inline-flex}._emoji_5z8g9_16{font-size:12px;line-height:1}._text_5z8g9_17{line-height:1}._perfect_5z8g9_20{color:#0f8;background:#00ff881f}._normal_5z8g9_21{color:#76b900;background:#76b9001f}._slow_5z8g9_22{color:#fa0;background:#ffaa001f}._spiky_5z8g9_23{color:#f60;background:#ff66001f}._veryslow_5z8g9_24{color:#f44;background:#ff44441f}._overloaded_5z8g9_25{color:#f22;background:#ff22221f}._unstable_5z8g9_26{color:#c00;background:#cc00001f}._notactive_5z8g9_27{color:#555570;background:#5555701f}._pending_5z8g9_28{color:#444460;background:#4444601a}[data-theme=light] ._perfect_5z8g9_20{color:#008f4d;background:#008f4d1a}[data-theme=light] ._normal_5z8g9_21{color:#4a7a00;background:#4a7a001a}[data-theme=light] ._slow_5z8g9_22{color:#b86b00;background:#b86b001a}[data-theme=light] ._spiky_5z8g9_23{color:#c45000;background:#c450001a}[data-theme=light] ._veryslow_5z8g9_24{color:#c8143a;background:#c8143a1a}[data-theme=light] ._overloaded_5z8g9_25{color:#b8101f;background:#b8101f1a}[data-theme=light] ._unstable_5z8g9_26{color:#900;background:#9900001a}[data-theme=light] ._notactive_5z8g9_27{color:#5a5a72}[data-theme=light] ._pending_5z8g9_28{color:#5a5a8a}._cell_c8a3q_1{font-family:var(--font-mono);border-radius:4px;align-items:center;gap:4px;min-width:70px;padding:1px 3px;font-size:12px;font-weight:600;transition:background .2s;display:inline-flex}._fast_c8a3q_14{color:#0f8}._medium_c8a3q_15{color:#fa0}._slow_c8a3q_16{color:#f44}._dim_c8a3q_17{color:var(--color-text-dim)}._running_c8a3q_18{color:#b400ff;font-weight:700}._badge_c8a3q_19{color:#06b6d4;font-size:10px}._runningCell_c8a3q_22{background:#b400ff1f}@keyframes _benchSpin_c8a3q_1{to{transform:rotate(360deg)}}@keyframes _benchPulse_c8a3q_1{0%,to{box-shadow:0 0 #b400ff66}50%{box-shadow:0 0 0 4px #b400ff00}}._benchmarkSpinner_c8a3q_34{border:2px solid #b400ff4d;border-top-color:#b400ff;border-radius:50%;flex-shrink:0;width:12px;height:12px;animation:.6s linear infinite _benchSpin_c8a3q_1;display:inline-block}[data-theme=light] ._fast_c8a3q_14{color:#008f4d}[data-theme=light] ._medium_c8a3q_15{color:#b86b00}[data-theme=light] ._slow_c8a3q_16{color:#c8143a}[data-theme=light] ._badge_c8a3q_19{color:#0e7490}[data-theme=light] ._runningCell_c8a3q_22{background:#7d00b414}._cell_1bcec_1{font-family:var(--font-mono);border-radius:4px;align-items:center;gap:4px;min-width:40px;padding:1px 3px;font-size:12px;font-weight:600;transition:background .2s;display:inline-flex}._fast_1bcec_14{color:#0f8}._slow_1bcec_15{color:#f44}._dim_1bcec_16{color:var(--color-text-dim)}._running_1bcec_17{color:#b400ff;font-weight:700}._badge_1bcec_18{color:#06b6d4;font-size:10px}._runningCell_1bcec_21{background:#b400ff1f}@keyframes _miniSpin_1bcec_29{to{transform:rotate(360deg)}}._miniSpinner_1bcec_29{border:1.5px solid #b400ff4d;border-top-color:#b400ff;border-radius:50%;flex-shrink:0;width:10px;height:10px;animation:.6s linear infinite _miniSpin_1bcec_29;display:inline-block}[data-theme=light] ._fast_1bcec_14{color:#008f4d}[data-theme=light] ._slow_1bcec_15{color:#c8143a}[data-theme=light] ._badge_1bcec_18{color:#0e7490}[data-theme=light] ._runningCell_1bcec_21{background:#7d00b414}._row_2hylr_13{max-width:100%;max-height:var(--pl-max-h,22px);color:var(--color-text);vertical-align:middle;align-items:center;gap:6px;line-height:1;display:inline-flex;overflow:hidden}._icon_2hylr_27{height:var(--pl-icon-h,16px);flex-shrink:0;justify-content:center;align-items:center;width:auto;display:inline-flex}._icon_2hylr_27 svg{width:auto;height:100%;display:block}._textLogo_2hylr_44{height:var(--pl-text-h,12px);flex-shrink:0;justify-content:center;align-items:center;width:auto;display:inline-flex}._textLogo_2hylr_44 svg{width:auto;height:100%;display:block}._iconLegacyWordmark_2hylr_63{height:var(--pl-icon-h,14px);width:auto;color:var(--color-text);flex-shrink:0;justify-content:center;align-items:center;display:inline-flex}._iconLegacyWordmark_2hylr_63 svg{width:auto;height:100%;display:block}.scalewayLogo{color:#521094;transition:color .2s var(--ease-out,ease)}[data-theme=dark] .scalewayLogo{color:#a78bfa}._fallback_2hylr_96{color:var(--color-text);white-space:nowrap;letter-spacing:.2px;font-size:11px;font-weight:500}._button_5uv8q_2{color:#3ddc84;cursor:pointer;font-size:12px;font-weight:800;font-family:var(--font-mono);background:#3ddc841f;border:1px solid #3ddc8473;border-radius:6px;justify-content:center;align-items:center;gap:7px;padding:8px 12px;transition:transform .12s,background .12s,border-color .12s;display:inline-flex}._button_5uv8q_2:hover:not(:disabled){background:#3ddc8433;border-color:#3ddc84bf;transform:translateY(-1px)}._button_5uv8q_2:disabled{opacity:.45;cursor:not-allowed}._icon_5uv8q_24{opacity:.72;width:26px;height:24px;padding:0}._icon_5uv8q_24:hover:not(:disabled){opacity:1}[data-theme=light] ._button_5uv8q_2{color:#087d42;background:#087d4214;border-color:#087d4259}._container_53dq1_8{background:var(--color-bg-card);border-top:0;border-bottom:1px solid var(--color-border);border-left:0;border-right:0;border-radius:0;flex-direction:column;flex:1;min-height:0;margin:0;display:flex;overflow:auto}._table_53dq1_23{border-collapse:collapse;border:0;width:100%;min-width:1200px;font-size:12px}._th_53dq1_32{text-transform:uppercase;letter-spacing:.5px;color:var(--color-text-muted);background:var(--color-bg-elevated);border-bottom:1px solid var(--color-border-hover);border-right:1px solid var(--color-border);white-space:nowrap;-webkit-user-select:none;user-select:none;z-index:10;text-align:center;padding:9px 8px;font-size:10px;font-weight:700;position:sticky;top:0}._th_53dq1_32:last-child{border-right:0}._th_53dq1_32:hover{color:var(--color-accent);background:var(--color-bg-active)}._thInner_53dq1_59{justify-content:space-between;align-items:center;gap:4px;width:100%;min-width:0;display:flex}._thLabel_53dq1_67{text-overflow:ellipsis;white-space:nowrap;flex:1;align-items:center;gap:4px;min-width:0;display:inline-flex;overflow:hidden}._resizeHandle_53dq1_81{cursor:col-resize;touch-action:none;-webkit-user-select:none;user-select:none;flex-shrink:0;justify-content:center;align-items:center;width:6px;height:22px;margin-left:2px;display:inline-flex;position:relative}._resizeHandle_53dq1_81:after{content:"";width:2px;height:14px;transition:background .12s var(--ease-out,ease);background:0 0;border-radius:1px;display:block}._resizeHandle_53dq1_81:hover:after,._resizeHandleActive_53dq1_106:after{background:var(--color-accent)}._resizeHandleActive_53dq1_106{cursor:col-resize}._th_53dq1_32:has(._resizeHandleActive_53dq1_106){background:var(--color-bg-active);color:var(--color-accent)}.col-resizing{cursor:col-resize!important;-webkit-user-select:none!important;user-select:none!important}._resizeToolbar_53dq1_125{background:var(--color-bg-elevated);border-bottom:1px solid var(--color-border);color:var(--color-text-muted);z-index:11;justify-content:space-between;align-items:center;gap:8px;padding:6px 10px;font-size:11px;display:flex;position:sticky;top:0}._resizeToolbarHint_53dq1_139{letter-spacing:.2px;align-items:center;gap:4px;display:inline-flex}._resizeToolbarHint_53dq1_139 strong{color:var(--color-text);font-weight:700;font-family:var(--font-mono)}._resizeResetButton_53dq1_150{appearance:none;border:1px solid var(--color-border-hover);color:var(--color-text-muted);cursor:pointer;transition:background .12s var(--ease-out,ease), color .12s var(--ease-out,ease), border-color .12s var(--ease-out,ease);white-space:nowrap;background:0 0;border-radius:4px;padding:3px 10px;font-size:11px;font-weight:600}._resizeResetButton_53dq1_150:hover{background:var(--color-bg-active);color:var(--color-accent);border-color:var(--color-accent)}._resizeResetButton_53dq1_150:focus-visible{outline:2px solid var(--color-accent);outline-offset:1px}._th_53dq1_32:nth-child(6),._th_53dq1_32:nth-child(7),._th_53dq1_32:nth-child(11){text-align:left}._sortIcon_53dq1_179{opacity:.3;margin-left:3px;font-size:9px}._sortIconActive_53dq1_180{color:var(--color-accent);margin-left:3px;font-size:10px;font-weight:800}._td_53dq1_183{border-bottom:1px solid var(--color-border);border-right:1px solid var(--color-border);white-space:nowrap;padding:7px 8px}._td_53dq1_183:last-child{border-right:0}._td_53dq1_183:nth-child(6),._td_53dq1_183:nth-child(7),._td_53dq1_183:nth-child(11){text-align:left}._table_53dq1_23 tbody tr{cursor:pointer;transition:background .1s}._table_53dq1_23 tbody tr:hover{background:var(--color-bg-hover)}._rank1_53dq1_202 td:first-child{border-left:3px solid gold}._rank2_53dq1_203 td:first-child{border-left:3px solid silver}._rank3_53dq1_204 td:first-child{border-left:3px solid #cd7f32}._rankNum_53dq1_207{font-family:var(--font-mono);color:var(--color-text-dim);text-align:center;font-size:11px;display:block}._swe_53dq1_215{font-family:var(--font-mono);font-weight:600}._sweHigh_53dq1_216{color:gold}._sweMid_53dq1_217{color:#3ddc84}._sweLow_53dq1_218{color:var(--color-text-dim)}._ctx_53dq1_220{font-family:var(--font-mono);font-size:11px}._ping_53dq1_222{font-family:var(--font-mono);font-weight:600}._pingFast_53dq1_223{color:#0f8}._pingMedium_53dq1_224{color:#fa0}._pingSlow_53dq1_225{color:#f44}._pingNone_53dq1_226{color:var(--color-text-dim)}[data-theme=light] ._sweHigh_53dq1_216{color:#7a5e00}[data-theme=light] ._sweMid_53dq1_217{color:#1f7a3e}[data-theme=light] ._pingFast_53dq1_223{color:#008f4d}[data-theme=light] ._pingMedium_53dq1_224{color:#b86b00}[data-theme=light] ._pingSlow_53dq1_225{color:#c8143a}._uptime_53dq1_235{font-family:var(--font-mono);font-size:11px}._modelCell_53dq1_238{align-items:center;gap:6px;display:flex;overflow:hidden}._modelMeta_53dq1_239{flex:1;min-width:0}._modelHeader_53dq1_240{align-items:center;gap:5px;display:flex}._modelName_53dq1_241{white-space:nowrap;text-overflow:ellipsis;font-size:12px;font-weight:600;overflow:hidden}._modelId_53dq1_242{font-family:var(--font-mono);color:var(--color-text-muted);white-space:nowrap;text-overflow:ellipsis;font-size:9px;overflow:hidden}@keyframes _benchRowPulse_53dq1_1{0%,to{background:#b400ff0a}50%{background:#b400ff1a}}._benchRow_53dq1_253{animation:1.2s ease-in-out infinite _benchRowPulse_53dq1_1}[data-theme=light] ._container_53dq1_8,[data-theme=light] ._table_53dq1_23{border-color:#cfcfcf}[data-theme=light] ._th_53dq1_32,[data-theme=light] ._td_53dq1_183{border-color:#d8d8d8}._empty_53dq1_271{text-align:center;color:var(--color-text-muted);padding:60px 0}._favBtn_53dq1_274{width:24px;height:24px;color:var(--color-text-dim);cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;transition:color .12s,background .12s,transform .12s;display:inline-flex}._favBtn_53dq1_274:hover{color:gold;background:#ffd7001a;transform:scale(1.1)}._favBtnActive_53dq1_289{color:gold}._favBtnActive_53dq1_289:hover{color:#ffae00;background:#ffae0024}[data-theme=light] ._favBtn_53dq1_274{color:#999}[data-theme=light] ._favBtn_53dq1_274:hover{color:#b08800;background:#b088001a}[data-theme=light] ._favBtnActive_53dq1_289{color:#b08800}._aiLatencyWrap_53dq1_301{cursor:pointer;border-radius:4px;justify-content:center;align-items:center;gap:4px;padding:2px 4px;transition:background .1s;display:inline-flex;position:relative}._aiLatencyWrap_53dq1_301:hover{background:#b400ff14}._aiLatencyWrap_53dq1_301._aiLatencyRunning_53dq1_312{cursor:progress}._aiLatencyWrap_53dq1_301._aiLatencyRunning_53dq1_312:hover{background:0 0}._aiLatencyPlay_53dq1_314{opacity:0;color:#b400ff;transition:opacity .1s}._aiLatencyWrap_53dq1_301:hover ._aiLatencyPlay_53dq1_314{opacity:1}._aiLatencyRunning_53dq1_312 ._aiLatencyPlay_53dq1_314{display:none}._incompatible_53dq1_323 td{color:var(--color-text-muted)!important;background:#ff00000f!important}._incompatible_53dq1_323:hover td{background:#ff00001a!important}[data-theme=light] ._incompatible_53dq1_323 td{color:#888!important;background:#c8143a0f!important}._launchCell_53dq1_336{opacity:0;justify-content:center;transition:opacity .12s;display:flex}._table_53dq1_23 tbody tr:hover ._launchCell_53dq1_336,._incompatible_53dq1_323 ._launchCell_53dq1_336,._benchRow_53dq1_253 ._launchCell_53dq1_336{opacity:1}._panel_gztrf_1{z-index:300;background:var(--color-bg-elevated);border-left:1px solid var(--color-border);width:min(420px,90vw);box-shadow:var(--shadow-lg);transition:transform var(--transition-medium);position:fixed;top:0;bottom:0;right:0;overflow-y:auto;transform:translate(100%)}._header_gztrf_16{border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:center;padding:20px 24px;display:flex}._title_gztrf_24{margin:0;font-size:16px;font-weight:700}._closeBtn_gztrf_30{color:var(--color-text-muted);cursor:pointer;background:0 0;border:none;font-size:22px;line-height:1}._closeBtn_gztrf_30:hover{color:var(--color-text)}._body_gztrf_43{padding:24px}._stat_gztrf_47{border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:center;padding:10px 0;display:flex}._statLabel_gztrf_55{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.5px;font-size:12px;font-weight:600}._statValue_gztrf_63,._ping_gztrf_68{font-family:var(--font-mono);font-weight:600}._pingFast_gztrf_73{color:#0f8}._pingMedium_gztrf_74{color:#fa0}._pingSlow_gztrf_75{color:#f44}._pingNone_gztrf_76{color:var(--color-text-dim)}[data-theme=light] ._pingFast_gztrf_73{color:#008f4d}[data-theme=light] ._pingMedium_gztrf_74{color:#b86b00}[data-theme=light] ._pingSlow_gztrf_75{color:#c8143a}._chart_gztrf_82{background:var(--color-surface);border-radius:var(--radius-md);border:1px solid var(--color-border);margin:20px 0;padding:16px}._chartTitle_gztrf_90{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.8px;margin-bottom:12px;font-size:11px;font-weight:700}._chartEmpty_gztrf_99{color:var(--color-text-dim);text-align:center;padding:20px}._actions_gztrf_106{background:var(--color-surface);border-radius:var(--radius-md);border:1px solid var(--color-border);flex-direction:column;gap:10px;margin:16px 0;padding:12px;display:flex}._favBlock_gztrf_117{flex-direction:column;gap:8px;display:flex}._favBtn_gztrf_123{background:var(--color-bg-card);color:var(--color-text-muted);border:1px solid var(--color-border);cursor:pointer;text-align:left;border-radius:6px;align-items:center;gap:8px;padding:8px 12px;font-size:12px;font-weight:600;transition:all .15s;display:inline-flex}._favBtn_gztrf_123:hover{color:gold;background:#ffd70014;border-color:gold}._favBtnActive_gztrf_143{color:gold;background:#ffd7001f;border-color:gold}._favBtnActive_gztrf_143:hover{background:#ffd70029}[data-theme=light] ._favBtn_gztrf_123{color:#555}[data-theme=light] ._favBtn_gztrf_123:hover{color:#b08800;background:#b088000f;border-color:#b08800}[data-theme=light] ._favBtnActive_gztrf_143{color:#b08800;background:#b088001a;border-color:#b08800}._reorderRow_gztrf_155{align-items:center;gap:6px;padding:0 4px;display:flex}._reorderBtn_gztrf_161{font-size:10px;font-weight:600;font-family:var(--font-mono);background:var(--color-bg-card);color:var(--color-text-muted);border:1px solid var(--color-border);cursor:pointer;border-radius:4px;align-items:center;gap:3px;padding:4px 8px;transition:all .12s;display:inline-flex}._reorderBtn_gztrf_161:hover:not(:disabled){background:var(--color-bg-hover);color:var(--color-text);border-color:var(--color-text-muted)}._reorderBtn_gztrf_161:disabled{opacity:.4;cursor:not-allowed}._rankBadge_gztrf_185{font-size:10px;font-family:var(--font-mono);color:gold;background:#ffd7001f;border:1px solid #ffd7004d;border-radius:999px;margin-left:auto;padding:2px 6px;font-weight:700}[data-theme=light] ._rankBadge_gztrf_185{color:#b08800;background:#b088001f;border-color:#b088004d}._benchBtn_gztrf_202{font-size:12px;font-weight:700;font-family:var(--font-mono);color:#b400ff;cursor:pointer;background:#b400ff1f;border:1px solid #b400ff66;border-radius:6px;justify-content:center;align-items:center;gap:6px;padding:8px 12px;transition:all .15s;display:inline-flex}._benchBtn_gztrf_202:hover{background:#b400ff33;border-color:#b400ffb3}._compatWarning_gztrf_223{color:#ff8da3;background:#ff5a7a1a;border:1px solid #ff5a7a59;border-radius:8px;align-items:center;gap:8px;margin:12px 0;padding:10px;font-size:12px;line-height:1.35;display:flex}._compatWarning_gztrf_223 span{flex:1}._compatWarning_gztrf_223 button{background:var(--color-bg-card);color:#ff8da3;cursor:pointer;border:1px solid #ff5a7a73;border-radius:6px;padding:5px 8px;font-size:11px;font-weight:800}._compatWarning_gztrf_223 button:hover{background:#ff5a7a29}[data-theme=light] ._benchBtn_gztrf_202{color:#6a00a0;background:#8c00c80f;border-color:#8c00c84d}[data-theme=light] ._benchBtn_gztrf_202:hover{background:#8c00c81f}._overlay_1e3f5_1{z-index:1000;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background:#0009;justify-content:center;align-items:center;animation:.2s ease-out _fadeIn_1e3f5_1;display:flex;position:fixed;inset:0}._overlay_1e3f5_1[hidden]{display:none}@keyframes _fadeIn_1e3f5_1{0%{opacity:0}to{opacity:1}}._modal_1e3f5_18{background:var(--color-bg-elevated);border:1px solid var(--color-border);border-radius:var(--radius-xl);width:min(500px,90vw);max-height:80vh;box-shadow:var(--shadow-lg);animation:_modalSlideIn_1e3f5_1 .3s var(--ease-out);overflow-y:auto}@keyframes _modalSlideIn_1e3f5_1{0%{opacity:0;transform:translateY(20px)scale(.96)}to{opacity:1;transform:translateY(0)scale(1)}}._modalHeader_1e3f5_33{border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:center;padding:20px 24px;display:flex}._modalTitle_1e3f5_40{margin:0;font-size:18px;font-weight:700}._modalClose_1e3f5_45{color:var(--color-text-muted);cursor:pointer;background:0 0;border:none;padding:0;font-size:24px;line-height:1}._modalClose_1e3f5_45:hover{color:var(--color-text)}._modalBody_1e3f5_57{padding:24px}._options_1e3f5_60{flex-direction:column;gap:10px;display:flex}._option_1e3f5_60{border:1px solid var(--color-border);border-radius:var(--radius-md);background:var(--color-surface);cursor:pointer;transition:all var(--transition-fast);text-align:left;font-family:var(--font-sans);color:var(--color-text);align-items:center;gap:14px;width:100%;padding:14px 18px;display:flex}._option_1e3f5_60:hover{border-color:var(--color-accent);background:var(--color-accent-dim)}._optionIcon_1e3f5_84{flex-shrink:0;font-size:24px}._optionLabel_1e3f5_89{font-size:14px;font-weight:600;display:block}._optionDesc_1e3f5_94{color:var(--color-text-muted);margin-top:2px;font-size:11px;display:block}._page_1847y_1{padding:24px}._pageHeader_1847y_5{margin-bottom:24px}._pageTitle_1847y_9{margin:0 0 6px;font-size:24px;font-weight:800}._pageSubtitle_1847y_15{color:var(--color-text-muted);margin:0;font-size:13px;line-height:1.5}._pageSubtitle_1847y_15 code{font-family:var(--font-mono);background:var(--color-surface);border-radius:4px;padding:2px 6px;font-size:12px}._loading_1847y_30{text-align:center;color:var(--color-text-muted);padding:60px 0}._featureSection_1847y_37{background:var(--color-bg-card);border:1px solid var(--color-border);border-radius:12px;margin-bottom:28px;padding:18px 20px}._sectionHeading_1847y_44{text-transform:uppercase;letter-spacing:.6px;color:var(--color-text-muted);margin:0 0 14px;font-size:11px;font-weight:700}._featureGrid_1847y_52{flex-direction:column;gap:4px;display:flex}._featureRow_1847y_57{border:1px solid #0000;border-radius:8px;align-items:center;gap:14px;padding:10px 12px;transition:background .12s;display:flex}._featureRow_1847y_57:hover{background:var(--color-surface)}._featureLabel_1847y_67{flex:1;align-items:flex-start;gap:10px;min-width:0;display:flex}._featureLabel_1847y_67>svg{color:var(--color-text-muted);flex-shrink:0;margin-top:2px}._featureTitle_1847y_79{color:var(--color-text);font-size:13px;font-weight:600;line-height:1.4}._featureDesc_1847y_85{color:var(--color-text-muted);margin-top:2px;font-size:11px;line-height:1.5}._featureActions_1847y_91{flex-shrink:0;gap:6px;display:flex}._select_1847y_96{background:var(--color-surface);color:var(--color-text);border:1px solid var(--color-border);font-size:12px;font-family:var(--font-sans);cursor:pointer;border-radius:5px;outline:none;min-width:130px;padding:5px 8px}._select_1847y_96:focus{border-color:var(--color-accent)}._toggleSwitch_1847y_110{flex-shrink:0;width:36px;height:20px;display:inline-block;position:relative}._toggleSwitch_1847y_110 input{opacity:0;width:0;height:0}._toggleSlider_1847y_122{background:var(--color-border);cursor:pointer;border-radius:20px;transition:background .15s;position:absolute;inset:0}._toggleSlider_1847y_122:before{content:"";background:var(--color-text);border-radius:50%;width:16px;height:16px;transition:transform .15s;position:absolute;top:2px;left:2px}._toggleSwitch_1847y_110 input:checked+._toggleSlider_1847y_122{background:var(--color-accent)}._toggleSwitch_1847y_110 input:checked+._toggleSlider_1847y_122:before{transform:translate(16px)}._smallBtn_1847y_148{font-size:11px;font-weight:600;font-family:var(--font-sans);background:var(--color-surface);color:var(--color-text);border:1px solid var(--color-border);cursor:pointer;white-space:nowrap;border-radius:5px;align-items:center;gap:4px;padding:5px 10px;display:inline-flex}._smallBtn_1847y_148:hover{background:var(--color-bg-hover);border-color:var(--color-text-muted)}._smallBtn_1847y_148:disabled{opacity:.5;cursor:not-allowed}._notice_1847y_166{background:var(--color-info-dim);color:var(--color-info);border:1px solid var(--color-info);border-radius:6px;margin-top:12px;padding:8px 12px;font-size:12px;line-height:1.5}._testBadge_1847y_178{font-size:10px;font-weight:700;font-family:var(--font-mono);border-radius:5px;align-self:flex-start;align-items:center;gap:5px;width:fit-content;margin-bottom:8px;padding:4px 8px;display:inline-flex}._testBadge_1847y_178._test_ok_1847y_191{background:var(--color-success-dim);color:var(--color-success);border:1px solid var(--color-success)}._testBadge_1847y_178._test_auth_error_1847y_192{background:var(--color-danger-dim);color:var(--color-danger);border:1px solid var(--color-danger)}._testBadge_1847y_178._test_rate_limited_1847y_193,._testBadge_1847y_178._test_no_callable_model_1847y_194{background:var(--color-warning-dim);color:var(--color-warning);border:1px solid var(--color-warning)}._testBadge_1847y_178._test_fail_1847y_195{background:var(--color-danger-dim);color:var(--color-danger);border:1px solid var(--color-danger)}._testBadge_1847y_178._test_missing_key_1847y_196,._testBadge_1847y_178._test_pending_1847y_197{background:var(--color-surface);color:var(--color-text-muted);border:1px solid var(--color-border)}._testSpinner_1847y_199{border:2px solid #b400ff4d;border-top-color:#b400ff;border-radius:50%;width:10px;height:10px;animation:.8s linear infinite _spin_1847y_1;display:inline-block}@keyframes _spin_1847y_1{to{transform:rotate(360deg)}}._toolbar_1847y_210{flex-wrap:wrap;align-items:center;gap:12px;margin-bottom:20px;display:flex}._toolbarSearch_1847y_218{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-md);flex:1;align-items:center;gap:8px;min-width:200px;height:36px;padding:0 12px;display:flex}._toolbarSearch_1847y_218 svg{color:var(--color-text-dim);flex-shrink:0}._toolbarSearch_1847y_218 input{color:var(--color-text);font-size:13px;font-family:var(--font-sans);background:0 0;border:none;outline:none;flex:1}._toolbarSearch_1847y_218 input::placeholder{color:var(--color-text-dim)}._toolbarActions_1847y_250{gap:8px;display:flex}._toolbarBtn_1847y_255{border:1px solid var(--color-border);border-radius:var(--radius-sm);cursor:pointer;background:var(--color-surface);color:var(--color-text);transition:all var(--transition-fast);font-size:13px;font-weight:500;font-family:var(--font-sans);align-items:center;gap:6px;padding:6px 14px;display:inline-flex}._toolbarBtn_1847y_255:hover{background:var(--color-bg-hover);border-color:var(--color-border-hover)}._providers_1847y_276{flex-direction:column;gap:12px;display:flex}._card_1847y_282{background:var(--color-bg-card);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--color-border);border-radius:var(--radius-lg);transition:border-color var(--transition-fast);overflow:hidden}._card_1847y_282:hover{border-color:var(--color-border-hover)}._cardHeader_1847y_295{cursor:pointer;transition:background var(--transition-fast);align-items:center;gap:12px;padding:16px 20px;display:flex}._cardHeader_1847y_295:hover{background:var(--color-bg-hover)}._cardIcon_1847y_308{border-radius:var(--radius-sm);background:var(--color-accent-dim);flex-shrink:0;justify-content:center;align-items:center;width:36px;height:36px;font-size:18px;display:flex}._cardInfo_1847y_320{flex:1;min-width:0}._cardName_1847y_325{font-size:14px;font-weight:700}._cardMeta_1847y_330{color:var(--color-text-muted);margin-top:2px;font-size:11px}._cardStatus_1847y_336{border-radius:999px;flex-shrink:0;padding:3px 10px;font-size:11px;font-weight:700}._statusConfigured_1847y_344{background:var(--color-success-dim);color:var(--color-success)}._statusMissing_1847y_349{background:var(--color-warning-dim);color:var(--color-warning)}._toggleIcon_1847y_354{color:var(--color-text-dim);transition:transform var(--transition-fast);flex-shrink:0;font-size:18px}._toggleIconExpanded_1847y_361{transform:rotate(180deg)}._cardBody_1847y_365{max-height:0;transition:max-height var(--transition-medium);border-top:0 solid #0000;overflow:hidden}._cardExpanded_1847y_372 ._cardBody_1847y_365{border-top:1px solid var(--color-border);max-height:500px}._cardContent_1847y_377{padding:16px 20px}._keyGroup_1847y_381{margin-bottom:12px}._keyLabel_1847y_385{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px;font-size:11px;font-weight:600;display:block}._keyDisplay_1847y_395{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-sm);align-items:center;gap:8px;margin-bottom:8px;padding:8px 12px;display:flex}._keyDisplayValue_1847y_406{font-family:var(--font-mono);color:var(--color-text-muted);word-break:break-all;flex:1;font-size:13px}._keyDisplayActions_1847y_414{flex-shrink:0;gap:4px;display:flex}._actionBtn_1847y_420{border:1px solid var(--color-border);border-radius:var(--radius-sm);background:var(--color-surface);color:var(--color-text);cursor:pointer;transition:all var(--transition-fast);justify-content:center;align-items:center;padding:4px 8px;font-size:12px;display:inline-flex}._actionBtn_1847y_420:hover{background:var(--color-bg-hover)}._actionBtnDanger_1847y_438{background:var(--color-danger-dim);color:var(--color-danger);border-color:#f443}._actionBtnDanger_1847y_438:hover{background:#f443}._keyInputRow_1847y_448{align-items:center;gap:8px;display:flex}._keyInput_1847y_448{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-sm);font-size:13px;font-family:var(--font-mono);color:var(--color-text);transition:border-color var(--transition-fast);outline:none;flex:1;padding:8px 12px}._keyInput_1847y_448:focus{border-color:var(--color-accent)}._keyInput_1847y_448::placeholder{color:var(--color-text-dim)}._saveBtn_1847y_475{border-radius:var(--radius-sm);background:var(--color-success-dim);color:var(--color-success);cursor:pointer;font-size:13px;font-weight:600;font-family:var(--font-sans);transition:all var(--transition-fast);border:1px solid #0f83;align-items:center;gap:6px;padding:8px 14px;display:inline-flex}._saveBtn_1847y_475:hover{background:#00ff8826}._enabledRow_1847y_495{border-top:1px solid var(--color-border);justify-content:space-between;align-items:center;margin-top:12px;padding-top:12px;display:flex}._enabledLabel_1847y_504{color:var(--color-text-muted);font-size:12px;font-weight:500}._toggleSwitch_1847y_110{cursor:pointer;width:44px;height:24px;position:relative}._toggleSwitch_1847y_110 input{display:none}._toggleSlider_1847y_122{background:var(--color-surface);border:1px solid var(--color-border);transition:all var(--transition-fast);border-radius:12px;position:absolute;inset:0}._toggleSlider_1847y_122:after{content:"";background:var(--color-text-dim);width:16px;height:16px;transition:all var(--transition-fast);border-radius:50%;position:absolute;top:3px;left:3px}._toggleSwitch_1847y_110 input:checked+._toggleSlider_1847y_122{background:var(--color-accent-dim);border-color:var(--color-accent)}._toggleSwitch_1847y_110 input:checked+._toggleSlider_1847y_122:after{background:var(--color-accent);transform:translate(20px)}._card_1m2zx_1{margin-top:16px}._cardTitle_1m2zx_5{color:var(--text-secondary,#aaa);text-transform:uppercase;letter-spacing:.5px;margin:0 0 10px;font-size:13px;font-weight:600}._empty_1m2zx_14{color:var(--text-muted,#666);text-align:center;padding:20px 0;font-size:13px}._summaryGrid_1m2zx_22{grid-template-columns:1fr 1fr;gap:12px;margin-top:16px;display:grid}._summaryCard_1m2zx_29{background:var(--bg-secondary,#14141f);border:1px solid var(--border,#1e1e2e);border-radius:8px;flex-direction:column;gap:2px;padding:14px 16px;display:flex}._summaryLabel_1m2zx_39{color:var(--text-muted,#888);text-transform:uppercase;letter-spacing:.5px;font-size:11px;font-weight:600}._summaryValue_1m2zx_47{color:var(--text-primary,#e0e0e0);font-size:22px;font-weight:700}._summarySub_1m2zx_53{color:var(--text-muted,#888);font-size:11px}._chart_1m2zx_59{align-items:flex-end;gap:6px;height:100px;padding:0 4px;display:flex}._chartBar_1m2zx_67{flex-direction:column;flex:1;justify-content:flex-end;align-items:center;gap:4px;height:100%;display:flex}._chartFill_1m2zx_77{background:linear-gradient(#00c864 0%,#00c8644d 100%);border-radius:3px 3px 0 0;width:100%;min-height:2px;transition:height .3s}._chartLabel_1m2zx_85{color:var(--text-muted,#888);text-transform:uppercase;font-size:10px}._topList_1m2zx_92{flex-direction:column;gap:4px;display:flex}._topRow_1m2zx_98{align-items:center;gap:8px;padding:4px 0;font-size:12px;display:flex}._topKey_1m2zx_106{color:var(--text-primary,#e0e0e0);text-overflow:ellipsis;white-space:nowrap;flex:1;font-family:SF Mono,monospace;overflow:hidden}._topVal_1m2zx_115{color:var(--text-muted,#888);text-align:right;min-width:80px}._topReq_1m2zx_121{color:var(--text-muted,#666);text-align:right;min-width:50px;font-size:11px}._page_1n8f8_1{padding:24px}._pageHeader_1n8f8_5{margin-bottom:24px}._pageTitle_1n8f8_9{margin:0 0 6px;font-size:24px;font-weight:800}._pageSubtitle_1n8f8_15{color:var(--color-text-muted);margin:0;font-size:13px}._grid_1n8f8_21{grid-template-columns:repeat(2,1fr);gap:16px;display:grid}._card_1n8f8_27{background:var(--color-bg-card);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:20px;overflow:hidden}._cardWide_1n8f8_36{grid-column:span 2}._cardTitle_1n8f8_40{margin:0 0 16px;font-size:14px;font-weight:700}._empty_1n8f8_49{color:var(--color-text-dim);text-align:center;padding:20px 0}._healthItem_1n8f8_55{border-bottom:1px solid var(--color-border);align-items:center;gap:12px;padding:8px 0;display:flex}._healthItem_1n8f8_55:last-child{border-bottom:none}._healthName_1n8f8_67{flex-shrink:0;width:120px;font-size:12px;font-weight:600}._healthBar_1n8f8_74{background:var(--color-surface);border-radius:4px;flex:1;height:8px;overflow:hidden}._healthFill_1n8f8_82{background:linear-gradient(90deg, var(--color-accent), var(--color-success));height:100%;transition:width var(--transition-medium);border-radius:4px}._healthPct_1n8f8_89{text-align:right;width:40px;font-family:var(--font-mono);font-size:12px;font-weight:600}._pctFast_1n8f8_97{color:#0f8}._pctMedium_1n8f8_98{color:#fa0}._pctSlow_1n8f8_99{color:#f44}[data-theme=light] ._pctFast_1n8f8_97{color:#008f4d}[data-theme=light] ._pctMedium_1n8f8_98{color:#b86b00}[data-theme=light] ._pctSlow_1n8f8_99{color:#c8143a}._leaderItem_1n8f8_105{border-bottom:1px solid var(--color-border);align-items:center;gap:10px;padding:8px 0;display:flex}._leaderItem_1n8f8_105:last-child{border-bottom:none}._leaderRank_1n8f8_117{background:var(--color-surface);width:28px;height:28px;color:var(--color-text-dim);border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;font-size:12px;font-weight:700;display:flex}._rank1_1n8f8_131{color:gold;background:#ffd70026}._rank2_1n8f8_132{color:silver;background:#c0c0c026}._rank3_1n8f8_133{color:#cd7f32;background:#cd7f3226}._leaderName_1n8f8_135{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:12px;font-weight:600;overflow:hidden}._leaderLatency_1n8f8_145{font-family:var(--font-mono);color:var(--color-success);flex-shrink:0;font-size:12px;font-weight:600}._tierItem_1n8f8_153{align-items:center;gap:10px;padding:6px 0;display:flex}._tierBadge_1n8f8_160{flex-shrink:0;width:40px}._tierBar_1n8f8_165{background:var(--color-surface);border-radius:5px;flex:1;height:10px;overflow:hidden}._tierFill_1n8f8_173{height:100%;transition:width var(--transition-medium);border-radius:5px}._tierCount_1n8f8_179{text-align:right;width:30px;font-family:var(--font-mono);color:var(--color-text-muted);font-size:12px}@media (width<=1024px){._grid_1n8f8_21{grid-template-columns:1fr}._cardWide_1n8f8_36{grid-column:span 1}}._backdrop_162pr_6{-webkit-backdrop-filter:blur(4px);z-index:500;background:#0000008c;justify-content:center;align-items:flex-start;padding-top:12vh;display:flex;position:fixed;inset:0}._modal_162pr_19{background:var(--color-bg-elevated);border:1px solid var(--color-border-hover);border-radius:14px;flex-direction:column;width:min(560px,92vw);max-height:70vh;display:flex;overflow:hidden;box-shadow:0 24px 64px #00000080}._searchRow_162pr_31{border-bottom:1px solid var(--color-border);align-items:center;gap:10px;padding:14px 16px;display:flex}._searchIcon_162pr_38{color:var(--color-text-dim);flex-shrink:0}._input_162pr_39{color:var(--color-text);font-size:15px;font-family:var(--font-sans);background:0 0;border:none;outline:none;flex:1}._input_162pr_39::placeholder{color:var(--color-text-dim)}._kbd_162pr_49{font-size:10px;font-family:var(--font-mono);color:var(--color-text-dim);background:var(--color-surface);border:1px solid var(--color-border);border-radius:4px;align-items:center;gap:2px;padding:2px 6px;display:inline-flex}._list_162pr_62{flex:1;margin:0;padding:6px;list-style:none;overflow-y:auto}._item_162pr_70{cursor:pointer;color:var(--color-text);-webkit-user-select:none;user-select:none;border-radius:7px;align-items:center;gap:10px;padding:9px 12px;font-size:13px;transition:background 80ms;display:flex}._itemActive_162pr_82{background:var(--color-accent-dim)}._itemDisabled_162pr_83{cursor:not-allowed;opacity:.5}._itemDisabled_162pr_83:hover{background:0 0}._itemIcon_162pr_88{color:var(--color-text-muted);flex-shrink:0}._itemLabel_162pr_89{flex:1}._itemEnter_162pr_90{color:var(--color-text-dim);font-size:11px;font-family:var(--font-mono)}._empty_162pr_96{text-align:center;color:var(--color-text-dim);padding:20px;font-size:13px}._footer_162pr_103{border-top:1px solid var(--color-border);color:var(--color-text-dim);background:var(--color-bg-card);gap:16px;padding:8px 16px;font-size:11px;display:flex}._footer_162pr_103 kbd{font-family:var(--font-mono);background:var(--color-surface);border:1px solid var(--color-border);border-radius:3px;margin-right:3px;padding:1px 5px;font-size:10px;display:inline-block}._backdrop_1y1s7_6{-webkit-backdrop-filter:blur(4px);z-index:500;background:#0000008c;justify-content:center;align-items:center;padding:5vh 4vw;display:flex;position:fixed;inset:0}._modal_1y1s7_19{background:var(--color-bg-elevated);border:1px solid var(--color-border-hover);border-radius:14px;flex-direction:column;width:min(820px,95vw);max-height:90vh;display:flex;overflow:hidden;box-shadow:0 24px 64px #00000080}._header_1y1s7_31{border-bottom:1px solid var(--color-border);padding:20px 24px 16px}._titleRow_1y1s7_36{justify-content:space-between;align-items:center;gap:12px;display:flex}._title_1y1s7_36{color:var(--color-text);margin:0;font-size:17px;font-weight:700}._closeBtn_1y1s7_50{color:var(--color-text-muted);cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;padding:4px;display:inline-flex}._closeBtn_1y1s7_50:hover{color:var(--color-text);background:var(--color-bg-hover)}._searchBar_1y1s7_63{background:var(--color-surface);border:1px solid var(--color-border);border-radius:8px;align-items:center;gap:8px;height:34px;margin-top:12px;padding:0 12px;display:flex}._searchBar_1y1s7_63:focus-within{border-color:var(--color-accent);box-shadow:0 0 0 3px var(--color-accent-glow)}._searchIcon_1y1s7_78{color:var(--color-text-dim)}._searchInput_1y1s7_79{color:var(--color-text);font-size:13px;font-family:var(--font-sans);background:0 0;border:none;outline:none;flex:1}._searchInput_1y1s7_79::placeholder{color:var(--color-text-dim)}._note_1y1s7_90{color:var(--color-text-muted);margin:10px 0 0;font-size:11px;line-height:1.5}._note_1y1s7_90 kbd{font-family:var(--font-mono);background:var(--color-surface);border:1px solid var(--color-border);border-radius:3px;padding:1px 5px;font-size:10px;display:inline-block}._body_1y1s7_106{flex:1;padding:18px 24px 24px;overflow-y:auto}._section_1y1s7_112{margin-bottom:18px}._sectionTitle_1y1s7_113{text-transform:uppercase;letter-spacing:.6px;color:var(--color-text-muted);margin:0 0 8px;font-size:12px;font-weight:700}._itemList_1y1s7_122{flex-direction:column;gap:4px;margin:0;padding:0;list-style:none;display:flex}._item_1y1s7_122{background:var(--color-surface);border:1px solid var(--color-border);border-radius:6px;grid-template-columns:minmax(160px,.4fr) 1fr;align-items:baseline;gap:12px;padding:6px 10px;font-size:12px;display:grid}._itemKey_1y1s7_141{color:var(--color-text);font-weight:600;font-family:var(--font-mono);font-size:11px}._itemDesc_1y1s7_147{color:var(--color-text-muted);line-height:1.5}._empty_1y1s7_152{text-align:center;color:var(--color-text-dim);padding:40px 20px;font-size:13px}._backdrop_5ik46_6{-webkit-backdrop-filter:blur(4px);z-index:500;background:#0000008c;justify-content:center;align-items:center;padding:5vh 4vw;display:flex;position:fixed;inset:0}._modal_5ik46_19{background:var(--color-bg-elevated);border:1px solid var(--color-border-hover);border-radius:14px;flex-direction:column;width:min(720px,95vw);max-height:88vh;display:flex;overflow:hidden;box-shadow:0 24px 64px #00000080}._header_5ik46_31{border-bottom:1px solid var(--color-border);padding:16px 20px}._titleRow_5ik46_36{align-items:center;gap:12px;display:flex}._title_5ik46_36{color:var(--color-text);flex:1;min-width:0;margin:0;font-size:16px;font-weight:700}._backBtn_5ik46_51{background:var(--color-surface);color:var(--color-text);border:1px solid var(--color-border);cursor:pointer;font-size:11px;font-weight:600;font-family:var(--font-sans);white-space:nowrap;border-radius:6px;align-items:center;gap:4px;padding:4px 10px;display:inline-flex}._backBtn_5ik46_51:hover{background:var(--color-bg-hover);border-color:var(--color-text-muted)}._closeBtn_5ik46_68{color:var(--color-text-muted);cursor:pointer;background:0 0;border:none;border-radius:4px;flex-shrink:0;justify-content:center;align-items:center;padding:4px;display:inline-flex}._closeBtn_5ik46_68:hover{color:var(--color-text);background:var(--color-bg-hover)}._body_5ik46_82{flex:1;padding:16px 20px 20px;overflow-y:auto}._indexHint_5ik46_89{color:var(--color-text-muted);margin:0 0 12px;font-size:11px}._versionList_5ik46_95{flex-direction:column;gap:4px;margin:0;padding:0;list-style:none;display:flex}._versionBtn_5ik46_103{background:var(--color-surface);border:1px solid var(--color-border);cursor:pointer;text-align:left;width:100%;font-family:var(--font-sans);border-radius:6px;justify-content:space-between;align-items:center;gap:12px;padding:8px 12px;transition:all .1s;display:flex}._versionBtn_5ik46_103:hover{background:var(--color-bg-hover);border-color:var(--color-text-muted)}._versionLabel_5ik46_119{font-family:var(--font-mono);color:var(--color-text);font-size:13px;font-weight:700}._versionSummary_5ik46_125{color:var(--color-text-muted);font-size:11px}._details_5ik46_130{flex-direction:column;gap:14px;display:flex}._sectionTitle_5ik46_132{text-transform:uppercase;letter-spacing:.6px;color:var(--color-text-muted);margin:0 0 6px;font-size:12px;font-weight:700}._itemList_5ik46_140{flex-direction:column;gap:4px;margin:0;padding-left:20px;list-style:outside;display:flex}._item_5ik46_140{color:var(--color-text);word-break:break-word;font-size:12px;line-height:1.55}._empty_5ik46_155{text-align:center;color:var(--color-text-dim);padding:40px 20px;font-size:13px}._wrap_10lrt_6{display:inline-flex;position:relative}._chip_10lrt_11{height:28px;font-size:11px;font-weight:700;font-family:var(--font-mono);background:var(--color-success-dim);color:var(--color-success);border:1px solid var(--color-success);cursor:pointer;font-family:var(--font-mono);white-space:nowrap;border-radius:6px;align-items:center;gap:5px;padding:0 10px;transition:all .15s;display:inline-flex}._chip_10lrt_11:hover{background:var(--color-success);color:var(--color-bg)}._checking_10lrt_34{opacity:.5;justify-content:center;align-items:center;width:22px;height:22px;display:inline-flex}._dot_10lrt_42{background:var(--color-text-muted);border-radius:50%;width:6px;height:6px;animation:1.5s ease-in-out infinite _pulse_10lrt_1}@keyframes _pulse_10lrt_1{0%,to{opacity:.3}50%{opacity:1}}._popover_10lrt_54{background:var(--color-bg-elevated);border:1px solid var(--color-border-hover);z-index:200;border-radius:10px;width:320px;position:absolute;top:calc(100% + 6px);right:0;overflow:hidden;box-shadow:0 12px 32px #0006}._popoverHeader_10lrt_67{border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:center;padding:10px 12px;display:flex}._popoverTitle_10lrt_74{color:var(--color-success);align-items:center;gap:6px;font-size:12px;font-weight:700;display:inline-flex}._popoverClose_10lrt_82{color:var(--color-text-muted);cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;padding:2px;display:inline-flex}._popoverClose_10lrt_82:hover{color:var(--color-text);background:var(--color-bg-hover)}._popoverBody_10lrt_95{color:var(--color-text);margin:0;padding:10px 12px;font-size:12px;line-height:1.5}._popoverBody_10lrt_95 strong{color:var(--color-success);font-family:var(--font-mono)}._popoverActions_10lrt_107{gap:6px;padding:8px 12px 12px;display:flex}._primaryAction_10lrt_113,._secondaryAction_10lrt_114{cursor:pointer;height:32px;font-size:11px;font-weight:600;font-family:var(--font-sans);border-radius:6px;flex:1;justify-content:center;align-items:center;gap:5px;padding:0 10px;transition:all .15s;display:inline-flex}._primaryAction_10lrt_113{background:var(--color-success);color:var(--color-bg);border:1px solid var(--color-success)}._primaryAction_10lrt_113:hover{background:var(--color-success);filter:brightness(.9)}._secondaryAction_10lrt_114{background:var(--color-surface);color:var(--color-text);border:1px solid var(--color-border)}._secondaryAction_10lrt_114:hover{background:var(--color-bg-hover);border-color:var(--color-text-muted)}._backdrop_7j81h_2{z-index:480;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background:#000000a3;justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;inset:0}._modal_7j81h_13{border:1px solid var(--color-border);background:var(--color-bg-elevated);width:min(980px,96vw);max-height:min(820px,94vh);color:var(--color-text);border-radius:16px;overflow:auto;box-shadow:0 20px 60px #0000007a}._header_7j81h_23,._footer_7j81h_24{border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:center;gap:14px;padding:20px 24px;display:flex}._footer_7j81h_24{border-top:1px solid var(--color-border);border-bottom:0;justify-content:flex-end}._header_7j81h_23 h2{align-items:center;gap:9px;margin:4px 0;font-size:21px;display:flex}._eyebrow_7j81h_27{color:var(--color-accent);text-transform:uppercase;letter-spacing:1px;margin:0;font-size:11px;font-weight:900}._summary_7j81h_28,._muted_7j81h_29{color:var(--color-text-muted);margin:0}._close_7j81h_30,._secondary_7j81h_31{border:1px solid var(--color-border);background:var(--color-surface);color:var(--color-text);cursor:pointer;border-radius:8px;align-items:center;gap:6px;display:inline-flex}._close_7j81h_30{justify-content:center;width:32px;height:32px}._secondary_7j81h_31{padding:8px 12px;font-weight:800}._secondary_7j81h_31:disabled{opacity:.45;cursor:not-allowed}._body_7j81h_35{padding:26px 28px}._steps_7j81h_36{color:var(--color-accent);font-family:var(--font-mono);margin-bottom:10px;font-size:12px;font-weight:800}._body_7j81h_35 h3{margin:0 0 18px;font-size:20px}._options_7j81h_38{grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;display:grid}._option_7j81h_38{border:1px solid var(--color-border);background:var(--color-surface);min-height:120px;color:var(--color-text);cursor:pointer;text-align:left;border-radius:14px;padding:18px;transition:transform .12s,border-color .12s,background .12s}._option_7j81h_38:hover{border-color:var(--color-accent);background:var(--color-bg-hover);transform:translateY(-2px)}._option_7j81h_38 strong{margin-bottom:8px;font-size:16px;display:block}._option_7j81h_38 span{color:var(--color-text-dim);font-family:var(--font-mono);font-size:11px}._progress_7j81h_43{border:1px solid var(--color-border);background:var(--color-surface);border-radius:999px;height:14px;overflow:hidden}._progress_7j81h_43 span{background:linear-gradient(90deg, var(--color-accent), #b400ff);height:100%;transition:width .2s;display:block}._percent_7j81h_45{font-family:var(--font-mono);color:var(--color-accent);font-weight:900}._results_7j81h_46{flex-direction:column;gap:12px;display:flex}._resultCard_7j81h_47{border:1px solid var(--color-border);background:var(--color-surface);border-radius:14px;grid-template-columns:38px 1fr 60px auto;align-items:center;gap:14px;padding:14px;display:grid}._medal_7j81h_48{font-size:26px}._resultMain_7j81h_49{flex-direction:column;gap:3px;min-width:0;display:flex}._resultMain_7j81h_49 strong{font-size:15px}._resultMain_7j81h_49 span{color:var(--color-text-muted);font-size:12px}._resultMain_7j81h_49 p{color:var(--color-text-dim);margin:5px 0 0;font-size:12px}._score_7j81h_53{font-family:var(--font-mono);color:var(--color-accent);text-align:center;font-size:24px;font-weight:900}._error_7j81h_54{color:#ff5a7a;margin:0 24px 16px;font-weight:800}@media (width<=760px){._options_7j81h_38{grid-template-columns:1fr}._resultCard_7j81h_47{grid-template-columns:32px 1fr}._score_7j81h_53{text-align:left}}._backdrop_8r8li_2{z-index:500;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);background:#0000009e;justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;inset:0}._modal_8r8li_13,._modalWide_8r8li_14{border:1px solid var(--color-border);background:var(--color-bg-elevated);width:min(560px,96vw);max-height:min(760px,92vh);color:var(--color-text);border-radius:14px;overflow:auto;box-shadow:0 18px 48px #00000073}._modalWide_8r8li_14{width:min(920px,96vw)}._header_8r8li_25{border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:flex-start;gap:18px;padding:20px 22px;display:flex}._header_8r8li_25 h2{align-items:center;gap:8px;margin:4px 0 0;font-size:18px;display:flex}._eyebrow_8r8li_40{color:var(--color-accent);text-transform:uppercase;letter-spacing:.9px;margin:0;font-size:11px;font-weight:900}._close_8r8li_48{border:1px solid var(--color-border);background:var(--color-surface);width:30px;height:30px;color:var(--color-text-muted);cursor:pointer;border-radius:7px;justify-content:center;align-items:center;display:inline-flex}._close_8r8li_48:hover{color:var(--color-text);background:var(--color-bg-hover)}._body_8r8li_61{flex-direction:column;gap:12px;padding:20px 22px;display:flex}._command_8r8li_62{border:1px solid var(--color-border);background:var(--color-surface);color:var(--color-accent);white-space:pre-wrap;word-break:break-word;border-radius:8px;padding:12px;display:block}._note_8r8li_72,._muted_8r8li_73{color:var(--color-text-muted);font-size:13px;line-height:1.45}._docs_8r8li_74{color:var(--color-accent);align-items:center;gap:5px;font-weight:700;text-decoration:none;display:inline-flex}._error_8r8li_75{color:#ff5a7a;font-weight:700}._footer_8r8li_76{border-top:1px solid var(--color-border);justify-content:flex-end;gap:10px;padding:16px 22px 20px;display:flex}._primary_8r8li_83,._secondary_8r8li_84,._option_8r8li_85{border:1px solid var(--color-border);cursor:pointer;border-radius:8px;font-weight:800}._primary_8r8li_83{background:var(--color-accent);color:var(--color-bg);border-color:var(--color-accent);padding:9px 14px}._primary_8r8li_83:disabled{opacity:.55;cursor:not-allowed}._secondary_8r8li_84{background:var(--color-surface);color:var(--color-text);padding:9px 14px}._grid_8r8li_103{grid-template-columns:1fr 1fr;gap:14px;padding:18px;display:grid}._card_8r8li_104{border:1px solid var(--color-border);background:var(--color-surface);border-radius:12px;padding:16px}._card_8r8li_104 h3{align-items:center;gap:7px;margin:0 0 6px;font-size:14px;display:flex}._stack_8r8li_111{flex-direction:column;gap:8px;margin-top:12px;display:flex}._option_8r8li_85{background:var(--color-bg-card);width:100%;color:var(--color-text);text-align:left;grid-template-columns:auto 1fr auto;align-items:center;gap:10px;padding:10px;display:grid}._option_8r8li_85:hover{border-color:var(--color-accent);background:var(--color-bg-hover)}._option_8r8li_85 small{color:var(--color-text-dim);font-family:var(--font-mono);font-size:10px}@media (width<=720px){._grid_8r8li_103{grid-template-columns:1fr}}._overlay_1hrn9_1{z-index:200;background:#0009;justify-content:center;align-items:center;animation:.15s _fadeIn_1hrn9_1;display:flex;position:fixed;inset:0}._modal_1hrn9_12{background:var(--bg-primary,#0f0f17);border:1px solid var(--border,#1e1e2e);border-radius:12px;flex-direction:column;width:720px;max-width:95vw;max-height:85vh;display:flex;box-shadow:0 8px 32px #00000080}._header_1hrn9_24{border-bottom:1px solid var(--border,#1e1e2e);justify-content:space-between;align-items:center;padding:16px 20px;display:flex}._title_1hrn9_32{color:var(--text-primary,#e0e0e0);align-items:center;gap:8px;margin:0;font-size:16px;font-weight:600;display:flex}._closeBtn_1hrn9_42{color:var(--text-muted,#888);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:4px 8px;font-size:18px}._closeBtn_1hrn9_42:hover{background:var(--bg-hover,#1a1a2e);color:var(--text-primary,#e0e0e0)}._body_1hrn9_53{flex:1;padding:20px;overflow-y:auto}._heroCard_1hrn9_60{border-radius:10px;justify-content:space-between;align-items:center;margin-bottom:16px;padding:16px;display:flex}._heroRunning_1hrn9_69{background:linear-gradient(135deg,#00c86414,#00c86405);border:1px solid #00c86433}._heroStopped_1hrn9_74{background:var(--bg-secondary,#14141f);border:1px solid var(--border,#1e1e2e)}._heroLeft_1hrn9_79{flex-direction:column;gap:4px;display:flex}._heroStatus_1hrn9_85{align-items:center;gap:8px;display:flex}._statusDot_1hrn9_91{border-radius:50%;width:10px;height:10px;display:inline-block}._dotGreen_1hrn9_98{background:#00c864;box-shadow:0 0 6px #00c86466}._dotGray_1hrn9_103{background:#555}._heroLabel_1hrn9_107{color:var(--text-primary,#e0e0e0);font-size:15px;font-weight:600}._heroMeta_1hrn9_113{color:var(--text-muted,#888);align-items:center;gap:6px;font-size:12px;display:flex}._heroActions_1hrn9_121{align-items:center;gap:8px;display:flex}._startBtn_1hrn9_127{color:#000;cursor:pointer;background:#00c864;border:none;border-radius:8px;align-items:center;gap:6px;padding:8px 16px;font-size:13px;font-weight:600;display:flex}._startBtn_1hrn9_127:hover{background:#00d874}._startBtn_1hrn9_127:disabled{opacity:.5;cursor:not-allowed}._stopBtn_1hrn9_143{color:#fff;cursor:pointer;background:#dc3545;border:none;border-radius:8px;align-items:center;gap:6px;padding:8px 16px;font-size:13px;font-weight:600;display:flex}._stopBtn_1hrn9_143:hover{background:#e04555}._stopBtn_1hrn9_143:disabled{opacity:.5;cursor:not-allowed}._refreshBtn_1hrn9_159{background:var(--bg-secondary,#14141f);border:1px solid var(--border,#1e1e2e);width:32px;height:32px;color:var(--text-muted,#888);cursor:pointer;border-radius:8px;justify-content:center;align-items:center;display:flex}._refreshBtn_1hrn9_159:hover{color:var(--text-primary,#e0e0e0);background:var(--bg-hover,#1a1a2e)}._quickSetup_1hrn9_174{margin-bottom:16px}._sectionTitle_1hrn9_178{color:var(--text-secondary,#aaa);text-transform:uppercase;letter-spacing:.5px;align-items:center;gap:6px;margin:0 0 8px;font-size:13px;font-weight:600;display:flex}._quickRows_1hrn9_190{background:var(--bg-secondary,#14141f);border:1px solid var(--border,#1e1e2e);border-radius:8px;flex-direction:column;gap:6px;padding:10px 12px;display:flex}._quickRow_1hrn9_190{align-items:center;gap:8px;display:flex}._quickLabel_1hrn9_206{color:var(--text-muted,#888);text-transform:uppercase;min-width:60px;font-size:11px;font-weight:600}._quickValue_1hrn9_214{color:var(--text-primary,#e0e0e0);background:var(--bg-primary,#0f0f17);border-radius:4px;flex:1;padding:4px 8px;font-family:SF Mono,monospace;font-size:13px}._copyBtn_1hrn9_224{color:var(--text-muted,#888);cursor:pointer;background:0 0;border:none;border-radius:4px;padding:4px}._copyBtn_1hrn9_224:hover{color:var(--text-primary,#e0e0e0);background:var(--bg-hover,#1a1a2e)}._section_1hrn9_178{margin-bottom:16px}._probeModes_1hrn9_239{gap:8px;display:flex}._probeBtn_1hrn9_244{border:1px solid var(--border,#1e1e2e);background:var(--bg-secondary,#14141f);color:var(--text-secondary,#aaa);cursor:pointer;text-transform:capitalize;border-radius:6px;padding:6px 14px;font-size:12px}._probeBtn_1hrn9_244:hover{border-color:var(--text-muted,#888)}._probeActive_1hrn9_256{color:#00c864;background:#00c8641a;border-color:#00c8644d;font-weight:600}._modelList_1hrn9_264{flex-direction:column;gap:4px;display:flex}._modelRow_1hrn9_270{background:var(--bg-secondary,#14141f);border-radius:6px;align-items:center;gap:8px;padding:6px 10px;font-size:12px;display:flex}._modelPriority_1hrn9_280{color:var(--text-muted,#888);min-width:22px;font-weight:600}._modelName_1hrn9_286{color:var(--text-primary,#e0e0e0);text-overflow:ellipsis;white-space:nowrap;flex:1;font-family:SF Mono,monospace;overflow:hidden}._modelScore_1hrn9_295{color:var(--text-muted,#888);text-align:right;min-width:40px}._modelLatency_1hrn9_301{color:var(--text-muted,#888);text-align:right;min-width:50px}._circuitBadge_1hrn9_307{text-transform:uppercase;letter-spacing:.5px;text-align:center;border-radius:4px;min-width:70px;padding:2px 6px;font-size:10px;font-weight:700}._circuitClosed_1hrn9_318{color:#00c864;background:#00c86426}._circuitOpen_1hrn9_319{color:#dc3545;background:#dc354526}._circuitHalfOpen_1hrn9_320{color:#ffc107;background:#ffc10726}._circuitAuth_1hrn9_321{color:#ff8c00;background:#ff8c0026}._circuitUnknown_1hrn9_322{color:#888;background:#80808026}._logList_1hrn9_325{flex-direction:column;gap:2px;display:flex}._logRow_1hrn9_331{align-items:center;gap:8px;padding:4px 8px;font-family:SF Mono,monospace;font-size:11px;display:flex}._logOk_1hrn9_340{color:#00c864;min-width:28px}._logErr_1hrn9_341{color:#dc3545;min-width:28px}._logModel_1hrn9_342{color:var(--text-secondary,#aaa);text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}._logLatency_1hrn9_343{color:var(--text-muted,#888);text-align:right;min-width:50px}._logTokens_1hrn9_344{color:var(--text-muted,#888);text-align:right;min-width:60px}._logFailover_1hrn9_345{color:#ffc107;text-transform:uppercase;background:#ffc10726;border-radius:3px;padding:1px 4px;font-size:9px}@keyframes _fadeIn_1hrn9_1{0%{opacity:0}to{opacity:1}}._overlay_1ocey_1{z-index:200;background:#0009;justify-content:center;align-items:center;animation:.15s _fadeIn_1ocey_1;display:flex;position:fixed;inset:0}._modal_1ocey_12{background:var(--bg-primary,#0f0f17);border:1px solid var(--border,#1e1e2e);border-radius:12px;flex-direction:column;width:640px;max-width:95vw;max-height:85vh;display:flex;box-shadow:0 8px 32px #00000080}._header_1ocey_24{border-bottom:1px solid var(--border,#1e1e2e);justify-content:space-between;align-items:center;padding:16px 20px;display:flex}._title_1ocey_32{color:var(--text-primary,#e0e0e0);align-items:center;gap:8px;margin:0;font-size:16px;font-weight:600;display:flex}._count_1ocey_42{background:var(--bg-secondary,#14141f);border:1px solid var(--border,#1e1e2e);color:var(--text-muted,#888);border-radius:10px;padding:2px 8px;font-size:12px}._headerActions_1ocey_51{align-items:center;gap:6px;display:flex}._refreshBtn_1ocey_57{background:var(--bg-secondary,#14141f);border:1px solid var(--border,#1e1e2e);width:28px;height:28px;color:var(--text-muted,#888);cursor:pointer;border-radius:6px;justify-content:center;align-items:center;display:flex}._refreshBtn_1ocey_57:hover{color:var(--text-primary,#e0e0e0)}._closeBtn_1ocey_71{color:var(--text-muted,#888);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:4px 8px;font-size:18px}._closeBtn_1ocey_71:hover{background:var(--bg-hover,#1a1a2e);color:var(--text-primary,#e0e0e0)}._body_1ocey_82{flex:1;padding:16px 20px;overflow-y:auto}._empty_1ocey_88{color:var(--text-muted,#666);text-align:center;padding:30px 0;font-size:13px;line-height:1.6}._hint_1ocey_96{color:var(--text-muted,#555);font-size:12px}._toolGroup_1ocey_102{margin-bottom:16px}._toolHeader_1ocey_106{align-items:center;gap:8px;margin-bottom:6px;display:flex}._toolEmoji_1ocey_113{font-size:16px}._toolLabel_1ocey_117{color:var(--text-primary,#e0e0e0);font-size:14px;font-weight:600}._toolCount_1ocey_123{color:var(--text-muted,#888);font-size:11px}._toolMissing_1ocey_128{color:#ff8c00;text-transform:uppercase;letter-spacing:.3px;background:#ff8c0026;border-radius:4px;padding:2px 6px;font-size:10px}._modelList_1ocey_139{flex-direction:column;gap:3px;padding-left:24px;display:flex}._modelRow_1ocey_146{background:var(--bg-secondary,#14141f);border-radius:6px;align-items:center;gap:8px;padding:6px 8px;font-size:12px;display:flex}._modelRow_1ocey_146:hover{background:var(--bg-hover,#1a1a2e)}._modelIcon_1ocey_157{font-size:12px}._modelName_1ocey_161{color:var(--text-primary,#e0e0e0);min-width:120px}._modelTier_1ocey_166{color:#00c8ff;background:#00c8ff1a;border-radius:3px;padding:1px 5px;font-size:10px;font-weight:700}._modelId_1ocey_175{color:var(--text-muted,#888);text-overflow:ellipsis;white-space:nowrap;flex:1;font-family:SF Mono,monospace;font-size:11px;overflow:hidden}._disableBtn_1ocey_185{color:var(--text-muted,#666);cursor:pointer;background:0 0;border:none;border-radius:4px;align-items:center;padding:4px;display:flex}._disableBtn_1ocey_185:hover{color:#dc3545;background:#dc35451a}@keyframes _fadeIn_1ocey_1{0%{opacity:0}to{opacity:1}}._overlay_1jn5t_1{z-index:200;background:#0009;justify-content:center;align-items:center;animation:.15s _fadeIn_1jn5t_1;display:flex;position:fixed;inset:0}._modal_1jn5t_12{background:var(--bg-primary,#0f0f17);border:1px solid var(--border,#1e1e2e);border-radius:12px;flex-direction:column;width:680px;max-width:95vw;max-height:85vh;display:flex;box-shadow:0 8px 32px #00000080}._header_1jn5t_24{border-bottom:1px solid var(--border,#1e1e2e);justify-content:space-between;align-items:center;padding:16px 20px;display:flex}._title_1jn5t_32{color:var(--text-primary,#e0e0e0);align-items:center;gap:8px;margin:0;font-size:16px;font-weight:600;display:flex}._closeBtn_1jn5t_42{color:var(--text-muted,#888);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:4px 8px;font-size:18px}._closeBtn_1jn5t_42:hover{background:var(--bg-hover,#1a1a2e);color:var(--text-primary,#e0e0e0)}._steps_1jn5t_54{border-bottom:1px solid var(--border,#1e1e2e);justify-content:center;align-items:center;gap:24px;padding:14px 20px;display:flex}._step_1jn5t_54{color:var(--text-muted,#555);align-items:center;gap:6px;font-size:12px;display:flex}._stepActive_1jn5t_71{color:var(--text-primary,#e0e0e0);font-weight:600}._stepDone_1jn5t_76{color:#00c864}._stepNum_1jn5t_80{background:var(--bg-secondary,#14141f);border:1px solid var(--border,#1e1e2e);border-radius:50%;justify-content:center;align-items:center;width:22px;height:22px;font-size:11px;font-weight:700;display:flex}._stepActive_1jn5t_71 ._stepNum_1jn5t_80{color:#00c864;background:#00c86426;border-color:#00c8644d}._stepDone_1jn5t_76 ._stepNum_1jn5t_80{color:#00c864;background:#00c86426;border-color:#00c864}._stepLabel_1jn5t_105{text-transform:uppercase;letter-spacing:.3px}._body_1jn5t_111{flex:1;min-height:300px;padding:20px;overflow-y:auto}._stepDesc_1jn5t_120{color:var(--text-secondary,#aaa);margin:0 0 16px;font-size:14px}._loading_1jn5t_126,._empty_1jn5t_126{color:var(--text-muted,#666);text-align:center;padding:30px 0;font-size:13px}._grid_1jn5t_134{grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:8px;display:grid}._pickCard_1jn5t_140{background:var(--bg-secondary,#14141f);border:1px solid var(--border,#1e1e2e);cursor:pointer;color:var(--text-secondary,#aaa);border-radius:8px;flex-direction:column;align-items:center;gap:4px;padding:14px 10px;font-size:13px;transition:all .15s;display:flex}._pickCard_1jn5t_140:hover{border-color:var(--text-muted,#666);color:var(--text-primary,#e0e0e0)}._pickActive_1jn5t_156{color:#00c864;background:#00c86414;border-color:#00c864}._pickEmoji_1jn5t_162{font-size:20px}._pickLabel_1jn5t_166{font-size:12px;font-weight:600}._pickMeta_1jn5t_171{color:var(--text-muted,#888);font-size:10px}._scopeToggle_1jn5t_177{gap:8px;margin-bottom:12px;display:flex}._scopeBtn_1jn5t_183{border:1px solid var(--border,#1e1e2e);background:var(--bg-secondary,#14141f);color:var(--text-secondary,#aaa);cursor:pointer;border-radius:6px;padding:6px 14px;font-size:12px}._scopeBtn_1jn5t_183:hover{border-color:var(--text-muted,#888)}._scopeActive_1jn5t_194{color:#00c864;background:#00c8641a;border-color:#00c8644d;font-weight:600}._modelGrid_1jn5t_202{grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:6px;max-height:240px;display:grid;overflow-y:auto}._modelCard_1jn5t_210{background:var(--bg-secondary,#14141f);border:1px solid var(--border,#1e1e2e);cursor:pointer;color:var(--text-secondary,#aaa);border-radius:6px;justify-content:space-between;align-items:center;padding:8px 10px;font-size:12px;display:flex}._modelCard_1jn5t_210:hover{border-color:var(--text-muted,#666)}._modelSelected_1jn5t_224{color:#00c864;background:#00c86414;border-color:#00c864}._modelName_1jn5t_230{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._modelTier_1jn5t_236{color:#00c8ff;background:#00c8ff1a;border-radius:3px;flex-shrink:0;margin-left:6px;padding:1px 4px;font-size:10px;font-weight:700}._allNotice_1jn5t_247{color:var(--text-muted,#888);text-align:center;padding:30px 0;font-size:13px}._installingState_1jn5t_255{color:var(--text-secondary,#aaa);flex-direction:column;justify-content:center;align-items:center;gap:12px;padding:40px 0;display:flex}._spinner_1jn5t_265{animation:1s linear infinite _spin_1jn5t_265}._doneState_1jn5t_269{text-align:center;flex-direction:column;align-items:center;gap:8px;padding:30px 0;display:flex}._doneState_1jn5t_269 h3{color:#00c864;margin:0;font-size:18px}._doneState_1jn5t_269 p{color:var(--text-secondary,#aaa);margin:0;font-size:13px}._installPath_1jn5t_280{color:var(--text-muted,#888);background:var(--bg-secondary,#14141f);text-overflow:ellipsis;border-radius:4px;max-width:100%;padding:4px 10px;font-size:11px;overflow:hidden}._footer_1jn5t_292{border-top:1px solid var(--border,#1e1e2e);justify-content:space-between;padding:14px 20px;display:flex}._backBtn_1jn5t_299{background:var(--bg-secondary,#14141f);border:1px solid var(--border,#1e1e2e);color:var(--text-secondary,#aaa);cursor:pointer;border-radius:8px;align-items:center;gap:4px;padding:8px 14px;font-size:13px;display:flex}._backBtn_1jn5t_299:hover{color:var(--text-primary,#e0e0e0)}._nextBtn_1jn5t_313{color:#000;cursor:pointer;background:#00c864;border:none;border-radius:8px;align-items:center;gap:4px;margin-left:auto;padding:8px 18px;font-size:13px;font-weight:600;display:flex}._nextBtn_1jn5t_313:hover{background:#00d874}._nextBtn_1jn5t_313:disabled{opacity:.4;cursor:not-allowed}._doneBtn_1jn5t_330{color:#000;cursor:pointer;background:#00c864;border:none;border-radius:8px;margin-left:auto;padding:8px 24px;font-size:13px;font-weight:600}._doneBtn_1jn5t_330:hover{background:#00d874}@keyframes _fadeIn_1jn5t_1{0%{opacity:0}to{opacity:1}}@keyframes _spin_1jn5t_265{0%{transform:rotate(0)}to{transform:rotate(360deg)}}._container_18l8h_1{z-index:10000;pointer-events:none;flex-direction:column;gap:8px;display:flex;position:fixed;top:20px;right:20px}._toast_73ezc_1{pointer-events:auto;border-radius:var(--radius-md,10px);background:var(--color-bg-elevated);border:1px solid var(--color-border);box-shadow:var(--shadow-lg);align-items:center;gap:10px;min-width:280px;max-width:420px;padding:12px 18px;font-size:13px;font-weight:500;animation:.3s cubic-bezier(.16,1,.3,1) _slideIn_73ezc_1;display:flex}._success_73ezc_17{border-left:4px solid #0f8}._error_73ezc_18{border-left:4px solid #f44}._warning_73ezc_19{border-left:4px solid #fa0}._info_73ezc_20{border-left:4px solid #06b6d4}[data-theme=light] ._success_73ezc_17{border-left-color:#008f4d}[data-theme=light] ._error_73ezc_18{border-left-color:#c8143a}[data-theme=light] ._warning_73ezc_19{border-left-color:#b86b00}[data-theme=light] ._info_73ezc_20{border-left-color:#0e7490}._icon_73ezc_27{flex-shrink:0;font-size:18px}._message_73ezc_28{flex:1}._close_73ezc_29{color:var(--color-text-dim);cursor:pointer;background:0 0;border:none;padding:0;font-size:16px;line-height:1}._exiting_73ezc_38{animation:.3s cubic-bezier(.16,1,.3,1) forwards _slideOut_73ezc_1}@keyframes _slideIn_73ezc_1{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}@keyframes _slideOut_73ezc_1{0%{opacity:1;transform:translate(0)}to{opacity:0;transform:translate(100%)}}:root{--color-brand:#76b900;--color-bg:#000;--color-bg-elevated:#0a0a0a;--color-bg-card:#0a0a0a;--color-bg-hover:#161616;--color-bg-active:#222;--color-surface:#111;--color-border:#262626;--color-border-hover:#404040;--color-text:#fff;--color-text-muted:#888;--color-text-dim:#444;--color-accent:#fff;--color-accent-hover:#eaeaea;--color-accent-glow:#ffffff1a;--color-accent-dim:#ffffff0d;--color-danger:#f44;--color-danger-dim:#ff44441a;--color-warning:#fa0;--color-warning-dim:#ffaa001a;--color-success:#0f8;--color-success-dim:#00ff881a;--color-info:#06b6d4;--color-info-dim:#06b6d41a;--tier-splus:gold;--tier-s:#ff8c00;--tier-aplus:#00c8ff;--tier-a:#3ddc84;--tier-aminus:#7ecf7e;--tier-bplus:#a8a8c8;--tier-b:#808098;--tier-c:#606078;--verdict-perfect:#0f8;--verdict-normal:#76b900;--verdict-slow:#fa0;--verdict-spiky:#f60;--verdict-veryslow:#f44;--verdict-overloaded:#f22;--verdict-unstable:#c00;--verdict-notactive:#555570;--verdict-pending:#444460;--font-sans:"Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-mono:"JetBrains Mono", "Fira Code", "Cascadia Code", monospace;--header-h:60px;--radius-sm:4px;--radius-md:6px;--radius-lg:8px;--radius-xl:8px;--shadow-sm:none;--shadow-md:none;--shadow-lg:none;--shadow-glow:none;--ease-out:cubic-bezier(.16, 1, .3, 1);--transition-fast:.15s var(--ease-out);--transition-medium:.25s var(--ease-out);--transition-slow:.4s var(--ease-out)}[data-theme=light]{--color-bg:#fff;--color-bg-elevated:#fff;--color-bg-card:#fff;--color-bg-hover:#fafafa;--color-bg-active:#f0f0f0;--color-surface:#fafafa;--color-border:#eaeaea;--color-border-hover:#d5d5d5;--color-text:#000;--color-text-muted:#666;--color-text-dim:#999;--color-accent:#000;--color-accent-hover:#333;--color-accent-glow:#0000000d;--color-accent-dim:#00000005;--color-success:#008f4d;--color-warning:#b86b00;--color-danger:#c8143a;--color-info:#0e7490;--color-danger-dim:#c8143a14;--color-warning-dim:#b86b0014;--color-success-dim:#008f4d14;--color-info-dim:#0e749014;--tier-splus:#b08800;--tier-s:#c45a00;--tier-aplus:#0073a8;--tier-a:#1f7a3e;--tier-aminus:#2f7a2f;--tier-bplus:#5a5a8a;--tier-b:#556;--tier-c:#6a6a7a;--verdict-perfect:#008f4d;--verdict-normal:#4a7a00;--verdict-slow:#b86b00;--verdict-spiky:#c45000;--verdict-veryslow:#c8143a;--verdict-overloaded:#b8101f;--verdict-unstable:#900;--verdict-notactive:#6a6a7a;--verdict-pending:#6a6a8a;--shadow-sm:none;--shadow-md:none;--shadow-lg:none}*,:before,:after{box-sizing:border-box;margin:0;padding:0}:focus-visible{outline:2px solid var(--color-accent);outline-offset:2px;border-radius:var(--radius-sm)}:focus:not(:focus-visible){outline:none}input:focus-visible,select:focus-visible,textarea:focus-visible{outline:2px solid var(--color-accent);outline-offset:1px}html{scroll-behavior:smooth;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:14px}body{font-family:var(--font-sans);background:var(--color-bg);color:var(--color-text);flex-direction:column;min-height:100vh;display:flex;position:relative;overflow-x:hidden}a{color:var(--color-accent);text-decoration:none}a:hover{color:var(--color-accent-hover)}code{font-family:var(--font-mono);background:var(--color-surface);border-radius:4px;padding:2px 6px;font-size:12px}.bg-grid,.bg-glow{display:none}[data-theme=light] .bg-glow{opacity:.12}[data-theme=light] .bg-grid{background-image:linear-gradient(#0000000a 1px,#0000 1px),linear-gradient(90deg,#0000000a 1px,#0000 1px)}.app-shell{z-index:1;flex-direction:column;flex:1;width:100%;min-height:100vh;display:flex;position:relative}.update-warning-banner{top:var(--header-h,60px);z-index:90;background:var(--color-danger);color:#fff;letter-spacing:.01em;text-align:center;border-bottom:1px solid #ffffff38;padding:10px 18px;font-size:13px;font-weight:800;position:sticky;box-shadow:0 8px 24px #00000038}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:var(--color-bg)}::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:4px}::-webkit-scrollbar-thumb:hover{background:var(--color-text-dim)}::-webkit-scrollbar-corner{background:var(--color-bg)}.app-content{z-index:1;min-height:calc(100vh - var(--header-h));flex-direction:column;flex:1;display:flex;position:relative}.view{flex-direction:column;flex:1;min-height:0;display:flex}
@@ -48,8 +48,8 @@
48
48
  <link rel="preconnect" href="https://fonts.googleapis.com">
49
49
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
50
50
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
51
- <script type="module" crossorigin src="/assets/index-Blp9QJev.js"></script>
52
- <link rel="stylesheet" crossorigin href="/assets/index-Cz_aCLTR.css">
51
+ <script type="module" crossorigin src="/assets/index-27IYGKp2.js"></script>
52
+ <link rel="stylesheet" crossorigin href="/assets/index-DKmmiDip.css">
53
53
  </head>
54
54
  <body>
55
55
  <div id="root"></div>
package/web/server.js CHANGED
@@ -46,6 +46,17 @@ import {
46
46
  getStabilityScore,
47
47
  } from '../src/core/utils.js'
48
48
  import { benchmarkModel, BENCHMARK_TIMEOUT_MS } from '../src/core/benchmark.js'
49
+ import { getInstallTargetModes, installProviderEndpoints, getConfiguredInstallableProviders, getProviderCatalogModels } from '../src/core/endpoint-installer.js'
50
+ import { isModelCompatibleWithTool } from '../src/core/tool-metadata.js'
51
+ import { sendUsageTelemetry } from '../src/core/telemetry.js'
52
+ import { getRouterDaemonStatus, startRouterDaemonBackground, stopRouterDaemon, ROUTER_TOKENS_PATH } from '../src/core/router-daemon.js'
53
+ import { scanAllToolConfigs, softDeleteModel } from '../src/core/installed-models-manager.js'
54
+ import {
55
+ TASK_TYPES,
56
+ PRIORITY_TYPES,
57
+ CONTEXT_BUDGETS,
58
+ getTopRecommendations,
59
+ } from '../src/core/utils.js'
49
60
  import {
50
61
  PING_MODE_INTERVALS,
51
62
  PING_MODE_CYCLE,
@@ -511,6 +522,108 @@ function runWithConcurrency(tasks, concurrency) {
511
522
  })
512
523
  }
513
524
 
525
+ const TOOL_MODE_ORDER = getInstallTargetModes()
526
+ const TOOL_MODES = new Set(TOOL_MODE_ORDER)
527
+ const DAEMON_PROXY_TIMEOUT_MS = 5000
528
+
529
+ // ─── Router daemon proxy helper ────────────────────────────────────────────
530
+ async function proxyToDaemon(path, options = {}) {
531
+ const port = await readDaemonPort()
532
+ if (!port) return null
533
+ try {
534
+ const url = `http://127.0.0.1:${port}${path}`
535
+ const resp = await fetch(url, { ...options, signal: AbortSignal.timeout(DAEMON_PROXY_TIMEOUT_MS) })
536
+ return { ok: resp.ok, status: resp.status, data: await resp.json().catch(() => null) }
537
+ } catch { return null }
538
+ }
539
+
540
+ function readTokenFile() {
541
+ try {
542
+ if (!existsSync(ROUTER_TOKENS_PATH)) return null
543
+ return JSON.parse(readFileSync(ROUTER_TOKENS_PATH, 'utf8'))
544
+ } catch { return null }
545
+ }
546
+
547
+ function normalizeToolMode(mode) {
548
+ return typeof mode === 'string' && TOOL_MODES.has(mode) ? mode : 'opencode'
549
+ }
550
+
551
+ function getPreferredToolMode() {
552
+ return normalizeToolMode(config.settings?.preferredToolMode)
553
+ }
554
+
555
+ function persistPreferredToolMode(mode) {
556
+ const normalized = normalizeToolMode(mode)
557
+ if (!config.settings || typeof config.settings !== 'object') config.settings = {}
558
+ config.settings.preferredToolMode = normalized
559
+ const saveResult = saveConfig(config)
560
+ return { mode: normalized, saveResult }
561
+ }
562
+
563
+ function getEndpointModel(providerKey, modelId) {
564
+ const result = getResult(providerKey, modelId)
565
+ if (!result) return null
566
+ return {
567
+ providerKey: result.providerKey,
568
+ modelId: result.modelId,
569
+ label: result.label,
570
+ tier: result.tier,
571
+ sweScore: result.sweScore,
572
+ ctx: result.ctx,
573
+ status: result.status,
574
+ }
575
+ }
576
+
577
+ async function readDaemonPort() {
578
+ try {
579
+ const raw = readFileSync(`${process.env.HOME}/.free-coding-models-daemon.port`, 'utf8').trim()
580
+ if (/^\d+$/.test(raw)) return Number(raw)
581
+ } catch {}
582
+ return null
583
+ }
584
+
585
+ async function syncFavoritesToRouter(selected) {
586
+ if (config?.router?.enabled !== true) return
587
+ const selKey = `${selected.providerKey}/${selected.modelId}`
588
+ const favorites = Array.isArray(config.favorites) ? config.favorites : []
589
+ const chain = [selKey, ...favorites.filter((entry) => entry !== selKey)]
590
+ const models = chain.map((entry, index) => {
591
+ const slashIdx = entry.indexOf('/')
592
+ const provider = slashIdx >= 0 ? entry.slice(0, slashIdx) : '?'
593
+ const model = slashIdx >= 0 ? entry.slice(slashIdx + 1) : entry
594
+ return { provider, model, priority: index + 1 }
595
+ })
596
+ try {
597
+ const port = await readDaemonPort()
598
+ if (!port) return
599
+ const baseUrl = `http://127.0.0.1:${port}`
600
+ const setPayload = { name: 'fast-coding', models, created: new Date().toISOString() }
601
+ await fetch(`${baseUrl}/sets/fast-coding`, {
602
+ method: 'PUT',
603
+ headers: { 'Content-Type': 'application/json' },
604
+ body: JSON.stringify(setPayload),
605
+ })
606
+ await fetch(`${baseUrl}/sets/fast-coding/activate`, { method: 'POST' })
607
+ } catch {}
608
+ }
609
+
610
+ async function installEndpointForMode(mode, model) {
611
+ return installProviderEndpoints(config, model.providerKey, mode, {
612
+ scope: 'selected',
613
+ modelIds: [model.modelId],
614
+ })
615
+ }
616
+
617
+ function buildRecommendReason(result, answers) {
618
+ const bits = []
619
+ if (result.tier) bits.push(`${result.tier} tier`)
620
+ if (result.sweScore && result.sweScore !== '—') bits.push(`${result.sweScore} SWE`)
621
+ if (result.ctx) bits.push(`${result.ctx} context`)
622
+ if (result.status === 'up') bits.push('currently up')
623
+ const priority = PRIORITY_TYPES[answers.priority]?.label || 'balanced'
624
+ return `${bits.join(' · ') || 'Strong catalog fit'} for ${priority.toLowerCase()} priority.`
625
+ }
626
+
514
627
  async function handleRequest(req, res) {
515
628
  res.setHeader('X-FCM-Server', SERVER_SIGNATURE)
516
629
  res.setHeader('Access-Control-Allow-Origin', '*')
@@ -628,6 +741,110 @@ async function handleRequest(req, res) {
628
741
  sendJson(res, 200, getConfigPayload())
629
742
  return
630
743
 
744
+ // ── M3: shared tool mode — same preferredToolMode setting as the TUI Z cycle ──
745
+ case '/api/tool-mode': {
746
+ if (req.method === 'GET') {
747
+ sendJson(res, 200, { mode: getPreferredToolMode(), tools: TOOL_MODE_ORDER })
748
+ return
749
+ }
750
+ if (req.method !== 'POST') { res.writeHead(405); res.end('Method Not Allowed'); return }
751
+ const body = await readJsonBody(req)
752
+ if (!TOOL_MODES.has(body?.mode)) { sendJson(res, 422, { error: 'Invalid tool mode' }); return }
753
+ const { mode, saveResult } = persistPreferredToolMode(body.mode)
754
+ if (!saveResult.success) { sendJson(res, 500, { error: saveResult.error || 'Failed to save tool mode' }); return }
755
+ noteUserActivity()
756
+ sendJson(res, 200, { mode })
757
+ return
758
+ }
759
+
760
+ // ── M3: install selected model endpoint into a tool config, no process spawn ──
761
+ case '/api/install-endpoint':
762
+ case '/api/launch': {
763
+ if (req.method !== 'POST') { res.writeHead(405); res.end('Method Not Allowed'); return }
764
+ const body = await readJsonBody(req)
765
+ const mode = normalizeToolMode(body?.toolMode || body?.mode || getPreferredToolMode())
766
+ const model = getEndpointModel(body?.providerKey, body?.modelId)
767
+ if (!model) { sendJson(res, 404, { error: 'Model not found' }); return }
768
+ if (!isModelCompatibleWithTool(model.providerKey, mode)) {
769
+ sendJson(res, 422, { error: 'Model is incompatible with selected tool', code: 'incompatible_model', mode, model })
770
+ return
771
+ }
772
+
773
+ const { saveResult } = persistPreferredToolMode(mode)
774
+ if (!saveResult.success) { sendJson(res, 500, { error: saveResult.error || 'Failed to persist tool mode' }); return }
775
+ noteUserActivity()
776
+ try {
777
+ const installResult = await installEndpointForMode(mode, model)
778
+ void syncFavoritesToRouter(model)
779
+ void sendUsageTelemetry(config, { noTelemetry: false }, {
780
+ event: 'app_action',
781
+ mode,
782
+ properties: {
783
+ source: 'web',
784
+ action_type: 'install_endpoint',
785
+ tool_mode: mode,
786
+ provider: model.providerKey,
787
+ model_id: model.modelId,
788
+ model_label: model.label,
789
+ model_tier: model.tier,
790
+ },
791
+ })
792
+ sendJson(res, 200, { configured: true, mode, model, installResult })
793
+ } catch (err) {
794
+ sendJson(res, 422, {
795
+ error: err?.message || 'Failed to install endpoint',
796
+ code: 'endpoint_install_failed',
797
+ mode,
798
+ model,
799
+ })
800
+ }
801
+ return
802
+ }
803
+
804
+ // ── M3: Smart Recommend — wraps the same core scoring engine as the TUI ──
805
+ case '/api/recommend': {
806
+ if (req.method !== 'POST') { res.writeHead(405); res.end('Method Not Allowed'); return }
807
+ const body = await readJsonBody(req)
808
+ const answers = body?.answers || {}
809
+ const taskType = answers.taskType
810
+ const priority = answers.priority
811
+ const contextBudget = answers.contextBudget
812
+ if (!TASK_TYPES[taskType] || !PRIORITY_TYPES[priority] || !CONTEXT_BUDGETS[contextBudget]) {
813
+ sendJson(res, 422, { error: 'Invalid recommendation answers' })
814
+ return
815
+ }
816
+ const top3 = getTopRecommendations(results, taskType, priority, contextBudget, 3)
817
+ .map(({ result, score }) => ({
818
+ result: serializeModel(result),
819
+ score,
820
+ reason: buildRecommendReason(result, answers),
821
+ }))
822
+ void sendUsageTelemetry(config, { noTelemetry: false }, {
823
+ event: 'app_action',
824
+ mode: getPreferredToolMode(),
825
+ properties: { source: 'web', action_type: 'smart_recommend', taskType, priority, contextBudget },
826
+ })
827
+ sendJson(res, 200, { top3, answers: { taskType, priority, contextBudget } })
828
+ return
829
+ }
830
+
831
+ // ── M3: web telemetry mirror — never blocks UX and never exposes secrets ──
832
+ case '/api/telemetry/event': {
833
+ if (req.method !== 'POST') { res.writeHead(405); res.end('Method Not Allowed'); return }
834
+ const body = await readJsonBody(req)
835
+ const event = typeof body?.event === 'string' && body.event.trim() ? body.event.trim() : 'app_action'
836
+ const properties = body?.properties && typeof body.properties === 'object' && !Array.isArray(body.properties)
837
+ ? body.properties
838
+ : {}
839
+ void sendUsageTelemetry(config, { noTelemetry: false }, {
840
+ event,
841
+ mode: getPreferredToolMode(),
842
+ properties: { ...properties, source: 'web' },
843
+ })
844
+ sendJson(res, 200, { ok: true })
845
+ return
846
+ }
847
+
631
848
  case '/api/events':
632
849
  res.writeHead(200, {
633
850
  'Content-Type': 'text/event-stream',
@@ -900,7 +1117,175 @@ async function handleRequest(req, res) {
900
1117
  return
901
1118
  }
902
1119
 
903
- default:
1120
+ // ── M4: Router dashboard endpoints ────────────────────────────────────
1121
+ case '/api/router/status': {
1122
+ try {
1123
+ const status = await getRouterDaemonStatus()
1124
+ sendJson(res, 200, status)
1125
+ } catch (err) {
1126
+ sendJson(res, 200, { ok: false, running: false, error: err.message })
1127
+ }
1128
+ return
1129
+ }
1130
+
1131
+ case '/api/router/stats': {
1132
+ const proxy = await proxyToDaemon('/stats')
1133
+ if (proxy?.ok) { sendJson(res, 200, proxy.data); return }
1134
+ sendJson(res, 200, { ok: false, running: false, error: 'Daemon not reachable' })
1135
+ return
1136
+ }
1137
+
1138
+ case '/api/router/tokens': {
1139
+ // 📖 Try daemon first (live data), fall back to reading the token file
1140
+ const proxy = await proxyToDaemon('/stats/tokens')
1141
+ if (proxy?.ok) { sendJson(res, 200, proxy.data); return }
1142
+ const fileData = readTokenFile()
1143
+ if (fileData) { sendJson(res, 200, fileData); return }
1144
+ sendJson(res, 200, { daily: {}, all_time: { total_tokens: 0, prompt_tokens: 0, completion_tokens: 0, requests: 0 } })
1145
+ return
1146
+ }
1147
+
1148
+ case '/api/router/start': {
1149
+ if (req.method !== 'POST') { res.writeHead(405); res.end('Method Not Allowed'); return }
1150
+ try {
1151
+ const result = await startRouterDaemonBackground()
1152
+ noteUserActivity()
1153
+ sendJson(res, 200, result)
1154
+ } catch (err) {
1155
+ sendJson(res, 500, { ok: false, error: err.message })
1156
+ }
1157
+ return
1158
+ }
1159
+
1160
+ case '/api/router/stop': {
1161
+ if (req.method !== 'POST') { res.writeHead(405); res.end('Method Not Allowed'); return }
1162
+ try {
1163
+ const result = await stopRouterDaemon()
1164
+ sendJson(res, 200, result)
1165
+ } catch (err) {
1166
+ sendJson(res, 500, { ok: false, error: err.message })
1167
+ }
1168
+ return
1169
+ }
1170
+
1171
+ case '/api/router/sets': {
1172
+ // 📖 Proxy set operations to the daemon
1173
+ if (req.method === 'GET') {
1174
+ const proxy = await proxyToDaemon('/sets')
1175
+ if (proxy?.ok) { sendJson(res, 200, proxy.data); return }
1176
+ // 📖 Fallback: read sets from config directly
1177
+ const routerConfig = config.router || {}
1178
+ sendJson(res, 200, { activeSet: routerConfig.activeSet || 'fast-coding', sets: routerConfig.sets || {} })
1179
+ return
1180
+ }
1181
+ if (req.method === 'POST') {
1182
+ const proxy = await proxyToDaemon('/sets', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(await readJsonBody(req)) })
1183
+ if (proxy?.ok) { sendJson(res, 200, proxy.data); return }
1184
+ if (proxy?.status === 201) { sendJson(res, 201, proxy.data); return }
1185
+ sendJson(res, proxy?.status || 502, proxy?.data || { error: 'Daemon not reachable' })
1186
+ return
1187
+ }
1188
+ res.writeHead(405); res.end('Method Not Allowed')
1189
+ return
1190
+ }
1191
+
1192
+ case '/api/router/probe-mode': {
1193
+ if (req.method !== 'POST') { res.writeHead(405); res.end('Method Not Allowed'); return }
1194
+ const body = await readJsonBody(req)
1195
+ const proxy = await proxyToDaemon('/daemon/probe-mode', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) })
1196
+ if (proxy?.ok) { sendJson(res, 200, proxy.data); return }
1197
+ sendJson(res, proxy?.status || 502, proxy?.data || { error: 'Daemon not reachable' })
1198
+ return
1199
+ }
1200
+
1201
+ case '/api/router/quick-setup': {
1202
+ // 📖 Return router connection info for quick clipboard copy
1203
+ const port = await readDaemonPort()
1204
+ const routerConfig = config.router || {}
1205
+ const activeSetName = routerConfig.activeSet || 'fast-coding'
1206
+ const baseUrl = port ? `http://127.0.0.1:${port}/v1` : null
1207
+ sendJson(res, 200, {
1208
+ running: !!port,
1209
+ port: port || null,
1210
+ baseUrl,
1211
+ model: 'fcm',
1212
+ activeSet: activeSetName,
1213
+ apiKey: 'not-needed',
1214
+ })
1215
+ return
1216
+ }
1217
+
1218
+ // ── M4: Installed Models — scan tool configs + soft-delete ────────────
1219
+ case '/api/installed-models': {
1220
+ if (req.method !== 'GET') { res.writeHead(405); res.end('Method Not Allowed'); return }
1221
+ const results = scanAllToolConfigs()
1222
+ sendJson(res, 200, { results })
1223
+ return
1224
+ }
1225
+
1226
+ // ── M4: Install Endpoints wizard — full provider install into tool ────
1227
+ case '/api/install-endpoints/providers': {
1228
+ if (req.method !== 'GET') { res.writeHead(405); res.end('Method Not Allowed'); return }
1229
+ const providers = getConfiguredInstallableProviders(config)
1230
+ sendJson(res, 200, { providers })
1231
+ return
1232
+ }
1233
+
1234
+ case '/api/install-endpoints/catalog': {
1235
+ const catProvider = url.searchParams.get('provider')
1236
+ if (!catProvider) { sendJson(res, 400, { error: 'Missing ?provider= parameter' }); return }
1237
+ const models = getProviderCatalogModels(catProvider)
1238
+ sendJson(res, 200, { provider: catProvider, models })
1239
+ return
1240
+ }
1241
+
1242
+ case '/api/install-endpoints/wizard': {
1243
+ if (req.method !== 'POST') { res.writeHead(405); res.end('Method Not Allowed'); return }
1244
+ const body = await readJsonBody(req)
1245
+ const wizProvider = body?.providerKey
1246
+ const wizTool = body?.toolMode
1247
+ const wizScope = body?.scope || 'all'
1248
+ const wizModelIds = body?.modelIds || []
1249
+ if (!wizProvider || !wizTool) {
1250
+ sendJson(res, 400, { error: 'Missing providerKey or toolMode' }); return
1251
+ }
1252
+ noteUserActivity()
1253
+ try {
1254
+ const installResult = installProviderEndpoints(config, wizProvider, wizTool, {
1255
+ scope: wizScope,
1256
+ modelIds: wizModelIds,
1257
+ })
1258
+ void sendUsageTelemetry(config, { noTelemetry: false }, {
1259
+ event: 'app_action',
1260
+ mode: wizTool,
1261
+ properties: {
1262
+ source: 'web',
1263
+ action_type: 'install_endpoints_wizard',
1264
+ provider: wizProvider,
1265
+ tool_mode: wizTool,
1266
+ scope: wizScope,
1267
+ model_count: installResult.modelCount || 0,
1268
+ },
1269
+ })
1270
+ sendJson(res, 200, { success: true, ...installResult })
1271
+ } catch (err) {
1272
+ sendJson(res, 422, { error: err.message, code: 'install_failed' })
1273
+ }
1274
+ return
1275
+ }
1276
+
1277
+ // 📖 M4: soft-delete an installed model (pattern match — must be before default:)
1278
+ // 📖 Path: /api/installed-models/:tool/:model/disable
1279
+ default: {
1280
+ const disableMatch = url.pathname.match(/^\/api\/installed-models\/([^/]+)\/([^/]+)\/disable$/)
1281
+ if (disableMatch && req.method === 'POST') {
1282
+ const toolMode = decodeURIComponent(disableMatch[1])
1283
+ const modelId = decodeURIComponent(disableMatch[2])
1284
+ const result = softDeleteModel(toolMode, modelId)
1285
+ sendJson(res, result.success ? 200 : 422, result)
1286
+ return
1287
+ }
1288
+ }
904
1289
  // 📖 Serve Vite's /assets/* bundle, and our static favicon set that
905
1290
  // 📖 Vite copies verbatim from web/public/ into web/dist/. The legacy
906
1291
  // 📖 /favicon.ico lives at web/public/favicon.ico (root of public/).