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.
- package/README.md +30 -0
- package/bin/free-coding-models.js +12 -0
- package/changelog/v0.5.60.md +54 -0
- package/package.json +2 -2
- package/src/core/router-daemon.js +96 -0
- package/src/core/runtime-telemetry.js +541 -0
- package/src/core/utils.js +15 -0
- package/src/tui/app.js +17 -0
- package/src/tui/key-handler.js +80 -0
- package/src/tui/tui-state.js +9 -0
- package/web/dist/assets/{index-C_ZdUGrS.js → index-CQQJkofy.js} +2 -2
- package/web/dist/index.html +1 -1
- package/web/src/components/router/RouterView.jsx +34 -0
package/src/tui/key-handler.js
CHANGED
|
@@ -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)
|
package/src/tui/tui-state.js
CHANGED
|
@@ -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)
|