free-coding-models 0.5.0 → 0.5.1

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 (51) hide show
  1. package/README.md +9 -1
  2. package/bin/free-coding-models.js +10 -0
  3. package/changelog/v0.5.1.md +24 -0
  4. package/package.json +7 -2
  5. package/src/core/router-daemon.js +166 -1
  6. package/src/core/utils.js +2 -0
  7. package/src/tui/cli-help.js +2 -0
  8. package/src/tui/render-table.js +1 -1
  9. package/web/README.md +8 -5
  10. package/web/dist/assets/index-ByGf4Kq-.js +14 -0
  11. package/web/dist/assets/index-Ds7wmHBv.css +1 -0
  12. package/web/dist/index.html +3 -6
  13. package/web/index.html +1 -4
  14. package/web/package.json +11 -0
  15. package/web/server.js +606 -211
  16. package/web/src/App.jsx +54 -12
  17. package/web/src/components/analytics/AnalyticsView.jsx +10 -4
  18. package/web/src/components/atoms/AILatencyCell.jsx +38 -0
  19. package/web/src/components/atoms/AILatencyCell.module.css +43 -0
  20. package/web/src/components/atoms/HealthCell.jsx +53 -0
  21. package/web/src/components/atoms/HealthCell.module.css +15 -0
  22. package/web/src/components/atoms/LastPingCell.jsx +35 -0
  23. package/web/src/components/atoms/LastPingCell.module.css +35 -0
  24. package/web/src/components/atoms/MoodCell.jsx +25 -0
  25. package/web/src/components/atoms/MoodCell.module.css +6 -0
  26. package/web/src/components/atoms/RankCell.jsx +9 -0
  27. package/web/src/components/atoms/RankCell.module.css +9 -0
  28. package/web/src/components/atoms/TPSCell.jsx +36 -0
  29. package/web/src/components/atoms/TPSCell.module.css +38 -0
  30. package/web/src/components/atoms/VerdictBadge.jsx +30 -7
  31. package/web/src/components/atoms/VerdictBadge.module.css +24 -15
  32. package/web/src/components/dashboard/ExportModal.jsx +9 -4
  33. package/web/src/components/dashboard/FilterBar.jsx +112 -10
  34. package/web/src/components/dashboard/FilterBar.module.css +86 -1
  35. package/web/src/components/dashboard/ModelTable.jsx +293 -52
  36. package/web/src/components/dashboard/ModelTable.module.css +131 -33
  37. package/web/src/components/dashboard/StatsBar.jsx +7 -5
  38. package/web/src/components/layout/Footer.jsx +1 -1
  39. package/web/src/components/layout/Header.jsx +43 -9
  40. package/web/src/components/layout/Header.module.css +38 -4
  41. package/web/src/components/layout/Sidebar.jsx +19 -11
  42. package/web/src/components/layout/Sidebar.module.css +15 -5
  43. package/web/src/components/settings/SettingsView.jsx +24 -6
  44. package/web/src/components/settings/SettingsView.module.css +0 -1
  45. package/web/src/global.css +70 -73
  46. package/web/src/hooks/useFilter.js +117 -25
  47. package/web/src/hooks/useSSE.js +33 -9
  48. package/web/src/hooks/useSocket.js +200 -0
  49. package/web/vite.config.js +41 -0
  50. package/web/dist/assets/index-CGN-0_A0.css +0 -1
  51. package/web/dist/assets/index-CvMUM9Jr.js +0 -11
@@ -0,0 +1,200 @@
1
+ /**
2
+ * @file web/src/hooks/useSocket.js
3
+ * @description Realtime model-data hook with Socket.IO primary, SSE fallback, and REST polling safety net.
4
+ *
5
+ * 📖 The dashboard runs locally, so freshness matters more than shaving every
6
+ * byte. Socket.IO gives the snappiest path in `pnpm dev:web`; SSE keeps Docker /
7
+ * daemon-style servers working without Socket.IO; REST polling guarantees the UI
8
+ * eventually recovers if both streaming transports are interrupted.
9
+ *
10
+ * @functions
11
+ * → useSocket(serverUrl) — Subscribe to live dashboard state
12
+ * @exports useSocket
13
+ */
14
+ import { useState, useEffect, useRef, useCallback } from 'react'
15
+ import { io } from 'socket.io-client'
16
+
17
+ const REST_FALLBACK_INTERVAL_MS = 2_000
18
+ const STALE_UPDATE_MS = 4_000
19
+ const ACTIVITY_THROTTLE_MS = 1_000
20
+
21
+ function normalizePayload(data) {
22
+ if (!data) return null
23
+ if (Array.isArray(data)) return { models: data }
24
+ if (Array.isArray(data.models)) return data
25
+ return null
26
+ }
27
+
28
+ function sameOriginUrl(path, serverUrl) {
29
+ if (!serverUrl) return path
30
+ return `${serverUrl.replace(/\/$/, '')}${path}`
31
+ }
32
+
33
+ export function useSocket(serverUrl = '') {
34
+ const [models, setModels] = useState([])
35
+ const [connected, setConnected] = useState(false)
36
+ const [transport, setTransport] = useState('connecting')
37
+ const [updateCount, setUpdateCount] = useState(0)
38
+ const [nextPingAt, setNextPingAt] = useState(null)
39
+ const [serverIsPinging, setServerIsPinging] = useState(false)
40
+ const [pendingPings, setPendingPings] = useState(0)
41
+ const [pingMode, setPingMode] = useState('speed')
42
+ const [globalBenchmarkRunning, setGlobalBenchmarkRunning] = useState(false)
43
+ const [globalBenchmarkTotal, setGlobalBenchmarkTotal] = useState(0)
44
+ const [globalBenchmarkCompleted, setGlobalBenchmarkCompleted] = useState(0)
45
+
46
+ const socketRef = useRef(null)
47
+ const esRef = useRef(null)
48
+ const pollRef = useRef(null)
49
+ const lastUpdateRef = useRef(0)
50
+ const lastActivityRef = useRef(0)
51
+ const mountedRef = useRef(false)
52
+
53
+ const applyPayload = useCallback((raw, source = 'unknown') => {
54
+ const data = normalizePayload(raw)
55
+ if (!data || !mountedRef.current) return
56
+
57
+ setModels(data.models ?? [])
58
+ setPingMode(data.pingMode ?? 'speed')
59
+ setNextPingAt(data.nextPingAt ?? null)
60
+ setServerIsPinging(Boolean(data.isPinging))
61
+ setPendingPings(Number.isFinite(data.pendingPings) ? data.pendingPings : 0)
62
+ setGlobalBenchmarkRunning(Boolean(data.globalBenchmarkRunning))
63
+ setGlobalBenchmarkTotal(Number.isFinite(data.globalBenchmarkTotal) ? data.globalBenchmarkTotal : 0)
64
+ setGlobalBenchmarkCompleted(Number.isFinite(data.globalBenchmarkCompleted) ? data.globalBenchmarkCompleted : 0)
65
+ setUpdateCount((count) => count + 1)
66
+ lastUpdateRef.current = Date.now()
67
+ if (source !== 'poll') {
68
+ setConnected(true)
69
+ setTransport(source)
70
+ }
71
+ }, [])
72
+
73
+ const fetchSnapshot = useCallback(async () => {
74
+ try {
75
+ const stateResponse = await fetch(sameOriginUrl('/api/state', serverUrl), { headers: { Accept: 'application/json' } })
76
+ if (stateResponse.ok) {
77
+ applyPayload(await stateResponse.json(), 'poll')
78
+ setConnected(true)
79
+ setTransport((current) => current === 'socket' || current === 'sse' ? current : 'poll')
80
+ return
81
+ }
82
+ } catch {}
83
+
84
+ try {
85
+ const response = await fetch(sameOriginUrl('/api/models', serverUrl), { headers: { Accept: 'application/json' } })
86
+ if (!response.ok) throw new Error(`HTTP ${response.status}`)
87
+ applyPayload(await response.json(), 'poll')
88
+ setConnected(true)
89
+ setTransport((current) => current === 'socket' || current === 'sse' ? current : 'poll')
90
+ } catch {
91
+ setConnected(false)
92
+ setTransport('offline')
93
+ }
94
+ }, [applyPayload, serverUrl])
95
+
96
+ const startSse = useCallback(() => {
97
+ if (esRef.current || !mountedRef.current) return
98
+ try {
99
+ const es = new EventSource(sameOriginUrl('/api/events', serverUrl))
100
+ esRef.current = es
101
+ es.onopen = () => {
102
+ if (!mountedRef.current) return
103
+ setConnected(true)
104
+ setTransport('sse')
105
+ }
106
+ const handleSsePayload = (event) => {
107
+ try { applyPayload(JSON.parse(event.data), 'sse') }
108
+ catch (err) { console.warn('[useSocket] SSE parse error:', err) }
109
+ }
110
+ es.onmessage = handleSsePayload
111
+ es.addEventListener('models', handleSsePayload)
112
+ es.onerror = () => {
113
+ es.close()
114
+ if (esRef.current === es) esRef.current = null
115
+ if (!socketRef.current?.connected) setConnected(false)
116
+ }
117
+ } catch {
118
+ esRef.current = null
119
+ }
120
+ }, [applyPayload, serverUrl])
121
+
122
+ const sendActivity = useCallback(() => {
123
+ const now = Date.now()
124
+ if (now - lastActivityRef.current < ACTIVITY_THROTTLE_MS) return
125
+ lastActivityRef.current = now
126
+
127
+ if (socketRef.current?.connected) {
128
+ socketRef.current.emit('client:activity')
129
+ return
130
+ }
131
+
132
+ fetch(sameOriginUrl('/api/activity', serverUrl), { method: 'POST' }).catch(() => {})
133
+ }, [serverUrl])
134
+
135
+ useEffect(() => {
136
+ mountedRef.current = true
137
+
138
+ const socket = io(serverUrl || undefined, {
139
+ transports: ['websocket', 'polling'],
140
+ reconnectionDelay: 500,
141
+ reconnectionDelayMax: 2500,
142
+ timeout: 1200,
143
+ })
144
+ socketRef.current = socket
145
+
146
+ socket.on('connect', () => {
147
+ setConnected(true)
148
+ setTransport('socket')
149
+ esRef.current?.close()
150
+ esRef.current = null
151
+ socket.emit('models:refresh')
152
+ socket.emit('client:activity')
153
+ })
154
+ socket.on('disconnect', () => {
155
+ if (!mountedRef.current) return
156
+ setConnected(false)
157
+ startSse()
158
+ })
159
+ socket.on('connect_error', () => {
160
+ if (!mountedRef.current) return
161
+ setConnected(false)
162
+ startSse()
163
+ })
164
+ socket.on('models:update', (data) => applyPayload(data, 'socket'))
165
+
166
+ pollRef.current = setInterval(() => {
167
+ const stale = Date.now() - lastUpdateRef.current > STALE_UPDATE_MS
168
+ if (!socket.connected || stale) void fetchSnapshot()
169
+ }, REST_FALLBACK_INTERVAL_MS)
170
+
171
+ void fetchSnapshot()
172
+
173
+ const activityEvents = ['keydown', 'pointerdown', 'mousemove', 'focus']
174
+ for (const eventName of activityEvents) window.addEventListener(eventName, sendActivity, { passive: true })
175
+
176
+ return () => {
177
+ mountedRef.current = false
178
+ for (const eventName of activityEvents) window.removeEventListener(eventName, sendActivity)
179
+ if (pollRef.current) clearInterval(pollRef.current)
180
+ socket.disconnect()
181
+ esRef.current?.close()
182
+ socketRef.current = null
183
+ esRef.current = null
184
+ }
185
+ }, [applyPayload, fetchSnapshot, sendActivity, serverUrl, startSse])
186
+
187
+ return {
188
+ models,
189
+ connected,
190
+ transport,
191
+ updateCount,
192
+ nextPingAt,
193
+ isPinging: serverIsPinging,
194
+ pendingPings,
195
+ pingMode,
196
+ globalBenchmarkRunning,
197
+ globalBenchmarkTotal,
198
+ globalBenchmarkCompleted,
199
+ }
200
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @file web/vite.config.js
3
+ * @description Vite config with proxy for backend API + Socket.IO (with WebSocket upgrade).
4
+ */
5
+ import { defineConfig } from 'vite'
6
+ import react from '@vitejs/plugin-react'
7
+ import { readFileSync } from 'node:fs'
8
+ import { fileURLToPath } from 'node:url'
9
+
10
+ const __dirname = fileURLToPath(new URL('.', import.meta.url))
11
+ const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
12
+
13
+ export default defineConfig({
14
+ plugins: [react()],
15
+ root: 'web',
16
+ build: {
17
+ outDir: 'dist',
18
+ emptyOutDir: true,
19
+ },
20
+ server: {
21
+ port: 5173,
22
+ proxy: {
23
+ '/api': {
24
+ target: 'http://localhost:3333',
25
+ changeOrigin: true,
26
+ },
27
+ '/socket.io': {
28
+ target: 'http://localhost:3333',
29
+ changeOrigin: true,
30
+ ws: true, // ← enable WebSocket upgrade
31
+ },
32
+ '/v1': {
33
+ target: 'http://localhost:3333',
34
+ changeOrigin: true,
35
+ },
36
+ },
37
+ },
38
+ define: {
39
+ __APP_VERSION__: JSON.stringify(pkg.version),
40
+ },
41
+ })
@@ -1 +0,0 @@
1
- ._header_1nuxz_1{z-index:100;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:20px;height:60px;padding:0 24px;display:flex;position:sticky;top:0}._left_1nuxz_16{align-items:center;gap:12px;display:flex}._center_1nuxz_17{flex:1;max-width:480px}._right_1nuxz_18{align-items:center;gap:10px;display:flex}._logo_1nuxz_20{align-items:center;gap:8px;display:flex}._logoIcon_1nuxz_21{font-size:22px}._logoText_1nuxz_22{background:linear-gradient(135deg, var(--color-accent), #06b6d4);-webkit-text-fill-color:transparent;-webkit-background-clip:text;background-clip:text;font-size:16px;font-weight:700}._version_1nuxz_27{font-size:11px;font-weight:500;font-family:var(--font-mono);color:var(--color-text-dim);background:var(--color-accent-dim);border:1px solid var(--color-border);border-radius:999px;padding:2px 8px}._searchBar_1nuxz_33{background:var(--color-surface);border:1px solid var(--color-border);border-radius:10px;align-items:center;gap:8px;height:36px;padding:0 12px;transition:border-color .15s,box-shadow .15s;display:flex}._searchBar_1nuxz_33:focus-within{border-color:var(--color-accent);box-shadow:0 0 0 3px var(--color-accent-glow)}._searchIcon_1nuxz_43{flex-shrink:0;font-size:14px}._searchInput_1nuxz_44{color:var(--color-text);font-size:13px;font-family:var(--font-sans);background:0 0;border:none;outline:none;flex:1}._searchInput_1nuxz_44::placeholder{color:var(--color-text-dim)}._kbd_1nuxz_49{font-size:10px;font-family:var(--font-mono);color:var(--color-text-dim);background:var(--color-bg);border:1px solid var(--color-border);border-radius:4px;flex-shrink:0;padding:2px 6px}._iconBtn_1nuxz_55{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_1nuxz_55:hover{background:var(--color-bg-hover);border-color:var(--color-border-hover)}._primaryBtn_1nuxz_62{border:1px solid var(--color-accent);background:var(--color-accent);color:#000;cursor:pointer;font-size:13px;font-weight:600;font-family:var(--font-sans);border-radius:6px;align-items:center;gap:6px;padding:6px 14px;transition:all .15s;display:inline-flex}._primaryBtn_1nuxz_62:hover{background:var(--color-accent-hover)}@media (width<=768px){._center_1nuxz_17{display:none}}._sidebar_16fei_1{z-index:200;background:var(--color-bg-elevated);border-right:1px solid var(--color-border);flex-direction:column;width:64px;padding:12px 0;transition:width .25s cubic-bezier(.16,1,.3,1);display:flex;position:fixed;top:0;bottom:0;left:0;overflow:hidden}._sidebar_16fei_1:hover{width:200px}._logo_16fei_16{white-space:nowrap;align-items:center;gap:10px;margin-bottom:16px;padding:8px 18px;display:flex;overflow:hidden}._logoIcon_16fei_25{flex-shrink:0;font-size:24px}._logoText_16fei_26{background:linear-gradient(135deg, var(--color-accent), #06b6d4);-webkit-text-fill-color:transparent;opacity:0;-webkit-background-clip:text;background-clip:text;font-size:16px;font-weight:800;transition:opacity .25s cubic-bezier(.16,1,.3,1)}._sidebar_16fei_1:hover ._logoText_16fei_26{opacity:1}._nav_16fei_38{flex-direction:column;flex:1;gap:4px;display:flex}._bottom_16fei_39{flex-direction:column;gap:4px;display:flex}._navItem_16fei_41{color:var(--color-text-muted);cursor:pointer;white-space:nowrap;font-family:var(--font-sans);background:0 0;border:none;align-items:center;gap:12px;padding:10px 20px;font-size:13px;font-weight:500;transition:all .15s cubic-bezier(.16,1,.3,1);display:flex;overflow:hidden}._navItem_16fei_41:hover{color:var(--color-text);background:var(--color-bg-hover)}._navIcon_16fei_61{text-align:center;flex-shrink:0;width:20px;font-size:16px}._navLabel_16fei_67{opacity:0;transition:opacity .25s cubic-bezier(.16,1,.3,1)}._sidebar_16fei_1:hover ._navLabel_16fei_67{opacity:1}._active_16fei_72{border-right:3px solid var(--color-accent);color:var(--color-accent)!important;background:var(--color-accent-dim)!important}._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}._statsBar_1q3n1_1{z-index:1;grid-template-columns:repeat(5,1fr);gap:14px;padding:20px 24px 0;display:grid;position:relative}._card_1q3n1_6{background:var(--color-bg-card);-webkit-backdrop-filter:blur(12px);border:1px solid var(--color-border);border-radius:16px;align-items:center;gap:12px;padding:16px 18px;transition:all .25s cubic-bezier(.16,1,.3,1);display:flex}._card_1q3n1_6:hover{border-color:var(--color-border-hover);box-shadow:var(--shadow-md);transform:translateY(-2px)}._icon_1q3n1_21{font-size:28px}._body_1q3n1_22{flex:1}._value_1q3n1_23{font-size:22px;font-weight:800;font-family:var(--font-mono);line-height:1}._label_1q3n1_24{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.5px;margin-top:2px;font-size:11px;font-weight:500}@media (width<=1024px){._statsBar_1q3n1_1{grid-template-columns:repeat(3,1fr)}}@media (width<=768px){._statsBar_1q3n1_1{grid-template-columns:repeat(2,1fr)}}@media (width<=480px){._statsBar_1q3n1_1{grid-template-columns:1fr}}._filters_jhonm_1{z-index:1;flex-wrap:wrap;align-items:center;gap:20px;padding:16px 24px;display:flex;position:relative}._group_jhonm_6{align-items:center;gap:8px;display:flex}._filterLabel_jhonm_7{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.5px;font-size:11px;font-weight:600}._tierRow_jhonm_11{gap:4px;display:flex}._tierBtn_jhonm_12{font-size:12px;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;border-radius:6px;padding:4px 10px;transition:all .15s}._tierBtn_jhonm_12:hover{background:var(--color-bg-hover);color:var(--color-text)}._active_jhonm_19{font-weight:700;background:var(--color-accent)!important;color:#000!important;border-color:var(--color-accent)!important}._providerSelect_jhonm_23{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:6px;outline:none;padding:5px 10px}._providerSelect_jhonm_23:focus{border-color:var(--color-accent)}._spacer_jhonm_30{flex:1}._live_jhonm_31{color:var(--color-accent);text-transform:uppercase;letter-spacing:1px;align-items:center;gap:6px;font-size:11px;font-weight:700;display:flex}._liveDot_jhonm_36{background:var(--color-accent);border-radius:50%;width:8px;height:8px;animation:2s ease-in-out infinite _pulseDot_jhonm_1}@keyframes _pulseDot_jhonm_1{0%,to{box-shadow:0 0 0 0 var(--color-accent-glow)}50%{box-shadow:0 0 0 6px #0000}}._badge_1vsmk_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_1vsmk_11{color:gold;background:#ffd70026;border:1px solid #ffd7004d}._tier_s_1vsmk_11{color:#ff8c00;background:#ff8c001f;border:1px solid #ff8c0040}._tier_aplus_1vsmk_13{color:#00c8ff;background:#00c8ff1a;border:1px solid #00c8ff33}._tier_a_1vsmk_13{color:#3ddc84;background:#3ddc841a;border:1px solid #3ddc8433}._tier_aminus_1vsmk_15{color:#7ecf7e;background:#7ecf7e1a;border:1px solid #7ecf7e33}._tier_bplus_1vsmk_16{color:#a8a8c8;background:#a8a8c81a;border:1px solid #a8a8c826}._tier_b_1vsmk_16{color:#808098;background:#8080981a;border:1px solid #80809826}._tier_c_1vsmk_18{color:#606078;background:#6060781a;border:1px solid #60607826}._dot_xhoha_1{vertical-align:middle;border-radius:50%;width:8px;height:8px;margin-right:6px;display:inline-block}._up_xhoha_9{background:#0f8;box-shadow:0 0 6px #0f86}._down_xhoha_10,._timeout_xhoha_11{background:#f44}._pending_xhoha_12{background:#555570;animation:1.5s ease-in-out infinite _pulse_xhoha_1}@keyframes _pulse_xhoha_1{0%,to{box-shadow:0 0 #76b90040}50%{box-shadow:0 0 0 6px #0000}}._badge_j5mmw_1{text-transform:uppercase;letter-spacing:.5px;border-radius:999px;padding:2px 8px;font-size:10px;font-weight:700;display:inline-block}._perfect_j5mmw_10{color:#0f8;background:#00ff881f;border:1px solid #00ff8840}._normal_j5mmw_11{color:#76b900;background:#76b9001f;border:1px solid #76b90040}._slow_j5mmw_12{color:#fa0;background:#ffaa001f;border:1px solid #ffaa0040}._spiky_j5mmw_13{color:#f60;background:#ff66001f;border:1px solid #ff660040}._veryslow_j5mmw_14{color:#f44;background:#ff44441f;border:1px solid #f443}._overloaded_j5mmw_15{color:#f22;background:#ff22221f;border:1px solid #f223}._unstable_j5mmw_16{color:#c00;background:#cc00001f;border:1px solid #c003}._notactive_j5mmw_17{color:#555570;background:#5555701f;border:1px solid #55557026}._pending_j5mmw_18{color:#444460;background:#4444601a;border:1px solid #44446026}._ratelimited_j5mmw_19{color:#fa0;background:#ffaa0026;border:1px solid #ffaa004d}._cell_1qs4d_1{align-items:center;gap:6px;display:flex}._bar_1qs4d_2{background:var(--color-surface);border-radius:3px;width:48px;height:6px;overflow:hidden}._fill_1qs4d_3{border-radius:3px;height:100%;transition:width .25s cubic-bezier(.16,1,.3,1)}._high_1qs4d_4{background:linear-gradient(90deg,#0f8,#76b900)}._mid_1qs4d_5{background:linear-gradient(90deg,#fa0,#ff8c00)}._low_1qs4d_6{background:linear-gradient(90deg,#f44,#c00)}._value_1qs4d_7{font-family:JetBrains Mono,monospace;font-size:12px;font-weight:600}._none_1qs4d_8{color:var(--color-text-dim)}._container_8mrfy_1{background:var(--color-bg-card);-webkit-backdrop-filter:blur(12px)saturate(1.5);border:1px solid var(--color-border);border-radius:16px;margin:16px 0;overflow:hidden}._table_8mrfy_10{border-collapse:collapse;width:100%;font-size:13px}._th_8mrfy_11{text-transform:uppercase;letter-spacing:.8px;color:var(--color-text-muted);background:var(--color-bg-elevated);border-bottom:1px solid var(--color-border);white-space:nowrap;-webkit-user-select:none;user-select:none;cursor:default;padding:12px 14px;font-size:11px;font-weight:700}._th_8mrfy_11:hover{color:var(--color-accent)}._table_8mrfy_10 td{border-bottom:1px solid var(--color-border);white-space:nowrap;padding:10px 14px}._table_8mrfy_10 tbody tr{cursor:pointer;transition:background .15s}._table_8mrfy_10 tbody tr:hover{background:var(--color-bg-hover)}._tdRank_8mrfy_20{text-align:center;font-family:var(--font-mono);color:var(--color-text-dim);font-weight:600}._rank1_8mrfy_21 td:first-child{border-left:3px solid gold}._rank2_8mrfy_22 td:first-child{border-left:3px solid silver}._rank3_8mrfy_23 td:first-child{border-left:3px solid #cd7f32}._modelCell_8mrfy_24{flex-direction:column;display:flex}._modelName_8mrfy_25{align-items:center;gap:4px;font-size:13px;font-weight:600;display:flex}._modelId_8mrfy_26{font-family:var(--font-mono);color:var(--color-text-dim);margin-top:1px;font-size:10px}._noKey_8mrfy_27{color:#fa0;background:#ffaa001f;border:1px solid #fa03;border-radius:3px;margin-left:6px;padding:1px 6px;font-size:10px;font-weight:600}._providerPill_8mrfy_31{background:var(--color-accent-dim);color:var(--color-text-muted);border:1px solid var(--color-border);border-radius:999px;padding:2px 8px;font-size:11px;font-weight:500;display:inline-block}._swe_8mrfy_35{font-family:var(--font-mono);font-weight:600}._sweHigh_8mrfy_36{color:gold}._sweMid_8mrfy_37{color:#3ddc84}._sweLow_8mrfy_38{color:var(--color-text-dim)}._ctx_8mrfy_39{font-family:var(--font-mono);color:var(--color-text-muted);font-size:12px}._ping_8mrfy_40{font-family:var(--font-mono);font-weight:600}._pingFast_8mrfy_41{color:#0f8}._pingMedium_8mrfy_42{color:#fa0}._pingSlow_8mrfy_43{color:#f44}._pingNone_8mrfy_44{color:var(--color-text-dim)}._uptime_8mrfy_45{font-family:var(--font-mono);font-size:12px}._empty_8mrfy_46{text-align:center;color:var(--color-text-muted);padding:60px 0}._panel_uzr3l_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_uzr3l_16{border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:center;padding:20px 24px;display:flex}._title_uzr3l_24{margin:0;font-size:16px;font-weight:700}._closeBtn_uzr3l_30{color:var(--color-text-muted);cursor:pointer;background:0 0;border:none;font-size:22px;line-height:1}._closeBtn_uzr3l_30:hover{color:var(--color-text)}._body_uzr3l_43{padding:24px}._stat_uzr3l_47{border-bottom:1px solid var(--color-border);justify-content:space-between;align-items:center;padding:10px 0;display:flex}._statLabel_uzr3l_55{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.5px;font-size:12px;font-weight:600}._statValue_uzr3l_63,._ping_uzr3l_68{font-family:var(--font-mono);font-weight:600}._pingFast_uzr3l_73{color:#0f8}._pingMedium_uzr3l_74{color:#fa0}._pingSlow_uzr3l_75{color:#f44}._pingNone_uzr3l_76{color:var(--color-text-dim)}._chart_uzr3l_78{background:var(--color-surface);border-radius:var(--radius-md);border:1px solid var(--color-border);margin:20px 0;padding:16px}._chartTitle_uzr3l_86{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.8px;margin-bottom:12px;font-size:11px;font-weight:700}._chartEmpty_uzr3l_95{color:var(--color-text-dim);text-align:center;padding:20px}._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_17r6q_1{max-width:900px;padding:24px}._pageHeader_17r6q_6{margin-bottom:24px}._pageTitle_17r6q_10{margin:0 0 6px;font-size:24px;font-weight:800}._pageSubtitle_17r6q_16{color:var(--color-text-muted);margin:0;font-size:13px;line-height:1.5}._pageSubtitle_17r6q_16 code{font-family:var(--font-mono);background:var(--color-surface);border-radius:4px;padding:2px 6px;font-size:12px}._loading_17r6q_31{text-align:center;color:var(--color-text-muted);padding:60px 0}._toolbar_17r6q_37{flex-wrap:wrap;align-items:center;gap:12px;margin-bottom:20px;display:flex}._toolbarSearch_17r6q_45{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_17r6q_45 svg{color:var(--color-text-dim);flex-shrink:0}._toolbarSearch_17r6q_45 input{color:var(--color-text);font-size:13px;font-family:var(--font-sans);background:0 0;border:none;outline:none;flex:1}._toolbarSearch_17r6q_45 input::placeholder{color:var(--color-text-dim)}._toolbarActions_17r6q_77{gap:8px;display:flex}._toolbarBtn_17r6q_82{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_17r6q_82:hover{background:var(--color-bg-hover);border-color:var(--color-border-hover)}._providers_17r6q_103{flex-direction:column;gap:12px;display:flex}._card_17r6q_109{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_17r6q_109:hover{border-color:var(--color-border-hover)}._cardHeader_17r6q_122{cursor:pointer;transition:background var(--transition-fast);align-items:center;gap:12px;padding:16px 20px;display:flex}._cardHeader_17r6q_122:hover{background:var(--color-bg-hover)}._cardIcon_17r6q_135{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_17r6q_147{flex:1;min-width:0}._cardName_17r6q_152{font-size:14px;font-weight:700}._cardMeta_17r6q_157{color:var(--color-text-muted);margin-top:2px;font-size:11px}._cardStatus_17r6q_163{border-radius:999px;flex-shrink:0;padding:3px 10px;font-size:11px;font-weight:700}._statusConfigured_17r6q_171{background:var(--color-success-dim);color:var(--color-success)}._statusMissing_17r6q_176{background:var(--color-warning-dim);color:var(--color-warning)}._toggleIcon_17r6q_181{color:var(--color-text-dim);transition:transform var(--transition-fast);flex-shrink:0;font-size:18px}._toggleIconExpanded_17r6q_188{transform:rotate(180deg)}._cardBody_17r6q_192{max-height:0;transition:max-height var(--transition-medium);border-top:0 solid #0000;overflow:hidden}._cardExpanded_17r6q_199 ._cardBody_17r6q_192{border-top:1px solid var(--color-border);max-height:500px}._cardContent_17r6q_204{padding:16px 20px}._keyGroup_17r6q_208{margin-bottom:12px}._keyLabel_17r6q_212{color:var(--color-text-muted);text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px;font-size:11px;font-weight:600;display:block}._keyDisplay_17r6q_222{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_17r6q_233{font-family:var(--font-mono);color:var(--color-text-muted);word-break:break-all;flex:1;font-size:13px}._keyDisplayActions_17r6q_241{flex-shrink:0;gap:4px;display:flex}._actionBtn_17r6q_247{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_17r6q_247:hover{background:var(--color-bg-hover)}._actionBtnDanger_17r6q_265{background:var(--color-danger-dim);color:var(--color-danger);border-color:#f443}._actionBtnDanger_17r6q_265:hover{background:#f443}._keyInputRow_17r6q_275{align-items:center;gap:8px;display:flex}._keyInput_17r6q_275{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_17r6q_275:focus{border-color:var(--color-accent)}._keyInput_17r6q_275::placeholder{color:var(--color-text-dim)}._saveBtn_17r6q_302{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_17r6q_302:hover{background:#00ff8826}._enabledRow_17r6q_322{border-top:1px solid var(--color-border);justify-content:space-between;align-items:center;margin-top:12px;padding-top:12px;display:flex}._enabledLabel_17r6q_331{color:var(--color-text-muted);font-size:12px;font-weight:500}._toggleSwitch_17r6q_337{cursor:pointer;width:44px;height:24px;position:relative}._toggleSwitch_17r6q_337 input{display:none}._toggleSlider_17r6q_348{background:var(--color-surface);border:1px solid var(--color-border);transition:all var(--transition-fast);border-radius:12px;position:absolute;inset:0}._toggleSlider_17r6q_348: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_17r6q_337 input:checked+._toggleSlider_17r6q_348{background:var(--color-accent-dim);border-color:var(--color-accent)}._toggleSwitch_17r6q_337 input:checked+._toggleSlider_17r6q_348:after{background:var(--color-accent);transform:translate(20px)}._page_1sl6l_1{padding:24px}._pageHeader_1sl6l_5{margin-bottom:24px}._pageTitle_1sl6l_9{margin:0 0 6px;font-size:24px;font-weight:800}._pageSubtitle_1sl6l_15{color:var(--color-text-muted);margin:0;font-size:13px}._grid_1sl6l_21{grid-template-columns:repeat(2,1fr);gap:16px;display:grid}._card_1sl6l_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_1sl6l_36{grid-column:span 2}._cardTitle_1sl6l_40{margin:0 0 16px;font-size:14px;font-weight:700}._empty_1sl6l_49{color:var(--color-text-dim);text-align:center;padding:20px 0}._healthItem_1sl6l_55{border-bottom:1px solid var(--color-border);align-items:center;gap:12px;padding:8px 0;display:flex}._healthItem_1sl6l_55:last-child{border-bottom:none}._healthName_1sl6l_67{flex-shrink:0;width:120px;font-size:12px;font-weight:600}._healthBar_1sl6l_74{background:var(--color-surface);border-radius:4px;flex:1;height:8px;overflow:hidden}._healthFill_1sl6l_82{background:linear-gradient(90deg, var(--color-accent), var(--color-success));height:100%;transition:width var(--transition-medium);border-radius:4px}._healthPct_1sl6l_89{text-align:right;width:40px;font-family:var(--font-mono);font-size:12px;font-weight:600}._pctFast_1sl6l_97{color:#0f8}._pctMedium_1sl6l_98{color:#fa0}._pctSlow_1sl6l_99{color:#f44}._leaderItem_1sl6l_101{border-bottom:1px solid var(--color-border);align-items:center;gap:10px;padding:8px 0;display:flex}._leaderItem_1sl6l_101:last-child{border-bottom:none}._leaderRank_1sl6l_113{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_1sl6l_127{color:gold;background:#ffd70026}._rank2_1sl6l_128{color:silver;background:#c0c0c026}._rank3_1sl6l_129{color:#cd7f32;background:#cd7f3226}._leaderName_1sl6l_131{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:12px;font-weight:600;overflow:hidden}._leaderLatency_1sl6l_141{font-family:var(--font-mono);color:var(--color-success);flex-shrink:0;font-size:12px;font-weight:600}._tierItem_1sl6l_149{align-items:center;gap:10px;padding:6px 0;display:flex}._tierBadge_1sl6l_156{flex-shrink:0;width:40px}._tierBar_1sl6l_161{background:var(--color-surface);border-radius:5px;flex:1;height:10px;overflow:hidden}._tierFill_1sl6l_169{height:100%;transition:width var(--transition-medium);border-radius:5px}._tierCount_1sl6l_175{text-align:right;width:30px;font-family:var(--font-mono);color:var(--color-text-muted);font-size:12px}@media (width<=1024px){._grid_1sl6l_21{grid-template-columns:1fr}._cardWide_1sl6l_36{grid-column:span 1}}._container_156te_1{width:100%;padding:2rem}._wip_156te_6{text-align:center;flex-direction:column;justify-content:center;align-items:center;min-height:60vh;display:flex}._wip_156te_6 h1{color:var(--text-primary);margin-bottom:1rem;font-size:2rem;font-weight:700}._wip_156te_6 p{color:var(--text-secondary);font-size:1.125rem}._container_18l8h_1{z-index:10000;pointer-events:none;flex-direction:column;gap:8px;display:flex;position:fixed;top:20px;right:20px}._toast_tvk0q_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_tvk0q_1;display:flex}._success_tvk0q_17{border-left:4px solid #0f8}._error_tvk0q_18{border-left:4px solid #f44}._warning_tvk0q_19{border-left:4px solid #fa0}._info_tvk0q_20{border-left:4px solid #06b6d4}._icon_tvk0q_21{flex-shrink:0;font-size:18px}._message_tvk0q_22{flex:1}._close_tvk0q_23{color:var(--color-text-dim);cursor:pointer;background:0 0;border:none;padding:0;font-size:16px;line-height:1}._exiting_tvk0q_32{animation:.3s cubic-bezier(.16,1,.3,1) forwards _slideOut_tvk0q_1}@keyframes _slideIn_tvk0q_1{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}@keyframes _slideOut_tvk0q_1{0%{opacity:1;transform:translate(0)}to{opacity:0;transform:translate(100%)}}:root{--color-bg:#0a0a0f;--color-bg-elevated:#12121a;--color-bg-card:#12121eb3;--color-bg-hover:#1e1e32cc;--color-bg-active:#282841e6;--color-surface:#1a1a2e;--color-border:#ffffff0f;--color-border-hover:#ffffff1f;--color-text:#e8e8f0;--color-text-muted:#8888a8;--color-text-dim:#555570;--color-accent:#76b900;--color-accent-hover:#8ad100;--color-accent-glow:#76b90040;--color-accent-dim:#76b90014;--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;--sidebar-w:64px;--sidebar-w-expanded:200px;--radius-sm:6px;--radius-md:10px;--radius-lg:16px;--radius-xl:20px;--shadow-sm:0 1px 3px #0000004d;--shadow-md:0 4px 12px #0006;--shadow-lg:0 8px 32px #00000080;--shadow-glow:0 0 30px var(--color-accent-glow);--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:#f5f5fa;--color-bg-elevated:#fff;--color-bg-card:#ffffffd9;--color-bg-hover:#f0f0f8e6;--color-bg-active:#e6e6f2f2;--color-surface:#eeeef4;--color-border:#00000014;--color-border-hover:#00000026;--color-text:#1a1a2e;--color-text-muted:#668;--color-text-dim:#99a;--color-accent-glow:#76b90026;--color-accent-dim:#76b9000d;--color-danger-dim:#ff444414;--color-warning-dim:#ffaa0014;--color-success-dim:#00ff8814;--color-info-dim:#06b6d414;--shadow-sm:0 1px 3px #00000014;--shadow-md:0 4px 12px #0000001a;--shadow-lg:0 8px 32px #0000001f}*,:before,:after{box-sizing:border-box;margin:0;padding:0}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);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{z-index:0;pointer-events:none;background-image:linear-gradient(#ffffff05 1px,#0000 1px),linear-gradient(90deg,#ffffff05 1px,#0000 1px);background-size:60px 60px;position:fixed;inset:0}.bg-glow{z-index:0;pointer-events:none;filter:blur(120px);opacity:.3;border-radius:50%;animation:20s ease-in-out infinite float;position:fixed}.bg-glow--1{background:radial-gradient(circle, var(--color-accent) 0%, transparent 70%);width:600px;height:600px;top:-200px;left:-200px}.bg-glow--2{background:radial-gradient(circle,#6366f1 0%,#0000 70%);width:400px;height:400px;animation-delay:-7s;top:50%;right:-150px}.bg-glow--3{background:radial-gradient(circle,#06b6d4 0%,#0000 70%);width:500px;height:500px;animation-delay:-14s;bottom:-200px;left:30%}@keyframes float{0%,to{transform:translate(0)scale(1)}33%{transform:translate(30px,-30px)scale(1.05)}66%{transform:translate(-20px,20px)scale(.95)}}[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-content{margin-left:var(--sidebar-w);z-index:1;min-height:100vh;transition:margin-left var(--transition-medium);flex-direction:column;flex:1;display:flex;position:relative}.view{flex-direction:column;flex:1;display:flex}::-webkit-scrollbar{width:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:3px}::-webkit-scrollbar-thumb:hover{background:var(--color-text-dim)}@media (width<=768px){.app-content{margin-left:0}}