free-coding-models 0.5.59 → 0.5.60

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.
@@ -836,6 +836,40 @@ export function createKeyHandler(ctx) {
836
836
  state.tokenUsageError = null
837
837
  }
838
838
 
839
+ // 📖 Runtime Report overlay (t3): per-model real-world breakdown + recent calls.
840
+ // 📖 Reads the local ~/.free-coding-models/runtime-telemetry.json file directly
841
+ // 📖 (the daemon writes to the same file; the CLI doesn't need to talk to it).
842
+ async function openRuntimeReportOverlay() {
843
+ state.runtimeReportOpen = true
844
+ state.runtimeReportScrollOffset = 0
845
+ state.runtimeReportError = null
846
+ state.runtimeReportData = null
847
+ state.runtimeReportSelectedKey = null
848
+ try {
849
+ const { loadRuntimeTelemetry, getAllModelTelemetry } = await import('../core/runtime-telemetry.js')
850
+ const cache = loadRuntimeTelemetry()
851
+ const all = getAllModelTelemetry({ cache })
852
+ const entries = Object.entries(all).sort((a, b) => (b[1].totalCalls || 0) - (a[1].totalCalls || 0))
853
+ state.runtimeReportData = entries
854
+ // 📖 Pre-select the currently-focused model if it has telemetry.
855
+ const focused = state.visibleSorted?.[state.cursor]
856
+ if (focused) {
857
+ const key = `${focused.providerKey}/${focused.modelId}`
858
+ if (entries.find(([k]) => k === key)) state.runtimeReportSelectedKey = key
859
+ }
860
+ } catch (err) {
861
+ state.runtimeReportError = err?.message || 'Failed to load runtime telemetry'
862
+ }
863
+ }
864
+
865
+ function closeRuntimeReportOverlay() {
866
+ state.runtimeReportOpen = false
867
+ state.runtimeReportScrollOffset = 0
868
+ state.runtimeReportError = null
869
+ state.runtimeReportData = null
870
+ state.runtimeReportSelectedKey = null
871
+ }
872
+
839
873
 
840
874
  function cycleToolMode() {
841
875
  const modeOrder = getToolModeOrder()
@@ -1355,6 +1389,7 @@ export function createKeyHandler(ctx) {
1355
1389
  case 'sort-verdict': return setSortColumnFromCommand('verdict')
1356
1390
  case 'sort-stability': return setSortColumnFromCommand('stability')
1357
1391
  case 'sort-uptime': return setSortColumnFromCommand('uptime')
1392
+ case 'sort-realworld': return setSortColumnFromCommand('realworld')
1358
1393
  case 'open-settings': return openSettingsOverlay()
1359
1394
  case 'open-help':
1360
1395
  state.helpVisible = true
@@ -1366,6 +1401,7 @@ export function createKeyHandler(ctx) {
1366
1401
  case 'open-router-dashboard': return openRouterDashboardOverlay(state)
1367
1402
  case 'open-playground': return openPlaygroundOverlay(state)
1368
1403
  case 'open-token-usage': return openTokenUsageOverlay()
1404
+ case 'open-runtime-report': return openRuntimeReportOverlay()
1369
1405
  case 'open-install-endpoints': return openInstallEndpointsOverlay()
1370
1406
  case 'open-installed-models': return openInstalledModelsOverlay()
1371
1407
  case 'action-cycle-theme': return cycleGlobalTheme()
@@ -2120,6 +2156,42 @@ export function createKeyHandler(ctx) {
2120
2156
  return
2121
2157
  }
2122
2158
 
2159
+ // 📖 Runtime Report overlay (t3): Shift+W. Per-model real-world breakdown +
2160
+ // 📖 recent calls. Scrolling with up/down/pageup/pagedown/escape.
2161
+ if (state.runtimeReportOpen) {
2162
+ if (key.ctrl && key.name === 'c') { exit(0); return }
2163
+ const pageStep = Math.max(1, (state.terminalRows || 1) - 4)
2164
+ if (key.name === 'escape') {
2165
+ closeRuntimeReportOverlay()
2166
+ return
2167
+ }
2168
+ if (key.name === 'up' || key.name === 'k') {
2169
+ state.runtimeReportScrollOffset = Math.max(0, state.runtimeReportScrollOffset - 1)
2170
+ return
2171
+ }
2172
+ if (key.name === 'down' || key.name === 'j') {
2173
+ state.runtimeReportScrollOffset += 1
2174
+ return
2175
+ }
2176
+ if (key.name === 'pageup') {
2177
+ state.runtimeReportScrollOffset = Math.max(0, state.runtimeReportScrollOffset - pageStep)
2178
+ return
2179
+ }
2180
+ if (key.name === 'pagedown') {
2181
+ state.runtimeReportScrollOffset += pageStep
2182
+ return
2183
+ }
2184
+ if (key.name === 'home') {
2185
+ state.runtimeReportScrollOffset = 0
2186
+ return
2187
+ }
2188
+ if (key.name === 'end') {
2189
+ state.runtimeReportScrollOffset = Number.MAX_SAFE_INTEGER
2190
+ return
2191
+ }
2192
+ return
2193
+ }
2194
+
2123
2195
  // 📖 Router Onboarding overlay: shown on first launch. Y=yes enable, N=not now, Esc=cancel.
2124
2196
  if (state.routerOnboardingOpen) {
2125
2197
  if (key.ctrl && key.name === 'c') { exit(0); return }
@@ -2872,6 +2944,14 @@ export function createKeyHandler(ctx) {
2872
2944
  return
2873
2945
  }
2874
2946
 
2947
+ // 📖 Shift+W: open the Runtime Report overlay (t3) — per-model real-world
2948
+ // 📖 success rate + throughput + recent calls. See command palette
2949
+ // 📖 'open-runtime-report' for the same action.
2950
+ if (key.name === 'w' && key.shift && !key.alt && !key.ctrl && !key.meta) {
2951
+ openRuntimeReportOverlay()
2952
+ return
2953
+ }
2954
+
2875
2955
  // 📖 E cycles: Normal → Configured only → Usable only → Normal
2876
2956
  // 📖 Configured only: hides models with no key or noauth/auth_error health
2877
2957
  // 📖 Usable only: only shows models with Health UP and Verdict ≤ Slow (Perfect/Normal/Slow)
@@ -297,6 +297,15 @@ export function createTuiState({
297
297
  probeCacheTtlMs: null, // 📖 Set in app.js from cliArgs.probeTtlMs || DEFAULT
298
298
  showBrokenMode: false,
299
299
 
300
+ // 📖 Runtime telemetry overlay state (t3): Shift+W opens the Runtime Report
301
+ // 📖 overlay. Data is loaded fresh from ~/.free-coding-models/runtime-telemetry.json
302
+ // 📖 when the overlay opens — no polling, no daemon dependency.
303
+ runtimeReportOpen: false,
304
+ runtimeReportScrollOffset: 0,
305
+ runtimeReportError: null,
306
+ runtimeReportData: null, // 📖 Array<[key, ModelTelemetry]>
307
+ runtimeReportSelectedKey: null, // 📖 Pre-selected model key
308
+
300
309
  // 📖 Header click flash animation: briefly highlights the clicked column header
301
310
  // 📖 with an inverse/bright style for ~250ms (3 frames at 12 FPS).
302
311
  headerFlashColumn: null, // 📖 Column name being flashed (null = no flash active)