free-coding-models 0.5.27 → 0.5.29

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 (37) hide show
  1. package/bin/free-coding-models.js +10 -2
  2. package/changelog/v0.5.27.md +2 -0
  3. package/changelog/v0.5.28.md +5 -0
  4. package/changelog/v0.5.29.md +19 -0
  5. package/package.json +1 -1
  6. package/sources.js +3 -2
  7. package/src/core/config.js +25 -18
  8. package/src/core/endpoint-installer.js +5 -9
  9. package/src/core/legacy-proxy-cleanup.js +2 -0
  10. package/src/core/model-merger.js +4 -13
  11. package/src/core/router-daemon.js +160 -43
  12. package/src/core/router-dashboard.js +63 -25
  13. package/src/core/shared-helpers.js +117 -0
  14. package/src/core/sync-set.js +6 -21
  15. package/src/core/tool-launchers.js +24 -92
  16. package/src/core/utils.js +26 -100
  17. package/src/tui/app.js +18 -2
  18. package/src/tui/command-palette.js +3 -1
  19. package/src/tui/key-handler.js +229 -23
  20. package/src/tui/overlays.js +13 -1
  21. package/src/tui/render-table.js +21 -5
  22. package/src/tui/tui-state.js +6 -0
  23. package/web/dist/assets/index-BMU58Jju.js +41 -0
  24. package/web/dist/assets/index-Dd1jOGEn.css +1 -0
  25. package/web/dist/index.html +2 -2
  26. package/web/server.js +5 -0
  27. package/web/src/components/atoms/HealthCell.jsx +12 -7
  28. package/web/src/components/atoms/HealthCell.module.css +4 -0
  29. package/web/src/components/atoms/StatusDot.jsx +5 -2
  30. package/web/src/components/atoms/StatusDot.module.css +12 -7
  31. package/web/src/components/dashboard/ModelTable.jsx +5 -2
  32. package/web/src/components/dashboard/ModelTable.module.css +9 -0
  33. package/web/src/components/router/RouterView.jsx +124 -56
  34. package/web/src/components/router/RouterView.module.css +135 -1
  35. package/src/core/product-flags.js +0 -9
  36. package/web/dist/assets/index-JUPDB-J-.js +0 -41
  37. package/web/dist/assets/index-avN2GM3H.css +0 -1
@@ -49,7 +49,7 @@ import {
49
49
  } from '../core/constants.js'
50
50
  import { themeColors, currentPalette, getProviderRgb, getTierRgb, getReadableTextRgb, getTheme, THEME_BG_RGB } from './theme.js'
51
51
  import { TIER_COLOR } from './tier-colors.js'
52
- import { getAvg, getVerdict, getUptime, getStabilityScore, getVersionStatusInfo, NEW_MODELS } from '../core/utils.js'
52
+ import { getAvg, getVerdict, getUptime, getStabilityScore, getVersionStatusInfo, isNewModel } from '../core/utils.js'
53
53
  import { usagePlaceholderForProvider } from '../core/ping.js'
54
54
  import { formatBenchmarkLatency, formatBenchmarkTps } from '../core/benchmark.js'
55
55
  import { calculateViewport, sortResultsWithPinnedFavorites, padEndDisplay, displayWidth, stripAnsi, fadedRow } from './render-helpers.js'
@@ -192,6 +192,10 @@ export function renderTable({
192
192
  benchmarkResults = {},
193
193
  benchmarkRunning = new Set(),
194
194
  headerFlashColumn = null,
195
+ probeRunning = false,
196
+ probeTotal = 0,
197
+ probeCompleted = 0,
198
+ probeHiddenCount = 0,
195
199
  } = _) {
196
200
  // 📖 Filter out hidden models for display
197
201
  const visibleResults = results.filter(r => !r.hidden)
@@ -652,13 +656,13 @@ export function renderTable({
652
656
  : providerName
653
657
  const source = themeColors.provider(r.providerKey, providerDisplay.padEnd(wSource))
654
658
  // 📖 Prefix: ⭐ favorite > 🎯 recommended > 🆕 new — only one emoji, never shifts the line
655
- const isNewModel = NEW_MODELS.has(r.modelId) || NEW_MODELS.has(`${r.providerKey}/${r.modelId}`)
659
+ const modelIsNew = isNewModel(r.addedDate)
656
660
  let favoritePrefix = ''
657
661
  if (r.isRecommended) {
658
662
  favoritePrefix = '🎯 '
659
663
  } else if (r.isFavorite) {
660
664
  favoritePrefix = '⭐ '
661
- } else if (isNewModel) {
665
+ } else if (modelIsNew) {
662
666
  favoritePrefix = '🆕 '
663
667
  }
664
668
  const prefixDisplayWidth = displayWidth(favoritePrefix)
@@ -1157,13 +1161,25 @@ export function renderTable({
1157
1161
  const speedTestLabel = chalk.bgRgb(...currentPalette().badgeSpeedTestBg).rgb(...currentPalette().badgeSpeedTestFg).bold(' NEW ⭐️ Ctrl+A 🤖 AI Speed Test ')
1158
1162
  const globalBenchmarkLabel = chalk.bgRgb(...currentPalette().badgeBenchmarkBg).rgb(...currentPalette().badgeBenchmarkFg).bold(' NEW Ctrl+U : Global AI Speed Test (Uses a lot of requests!) ')
1159
1163
 
1160
- // 📖 Line 3: Speed Test (Ctrl+A) + Global Benchmark (Ctrl+U) + Last release
1161
- if (releaseLabel || speedTestLabel || globalBenchmarkLabel) {
1164
+ // 📖 Probe badge: show progress when 404 probe is running or recently completed
1165
+ let probeLabel = ''
1166
+ if (probeRunning) {
1167
+ const pct = probeTotal > 0 ? Math.round((probeCompleted / probeTotal) * 100) : 0
1168
+ const bar = '█'.repeat(Math.floor(pct / 5)) + '░'.repeat(20 - Math.floor(pct / 5))
1169
+ probeLabel = chalk.bgRgb(180, 40, 40).rgb(255, 255, 255).bold(` 🔍 Probe ${bar} ${probeCompleted}/${probeTotal} `)
1170
+ } else if (probeHiddenCount > 0 && probeTotal > 0) {
1171
+ probeLabel = chalk.bgRgb(120, 60, 60).rgb(255, 200, 200).bold(` 🔍 Probe done: ${probeHiddenCount} broken model${probeHiddenCount > 1 ? 's' : ''} hidden `)
1172
+ }
1173
+
1174
+ // 📖 Line 3: Speed Test + Global Benchmark + Probe + Last release
1175
+ if (releaseLabel || speedTestLabel || globalBenchmarkLabel || probeLabel) {
1162
1176
  const parts = [
1163
1177
  { text: ' ', key: null },
1164
1178
  { text: speedTestLabel, key: 'a' },
1165
1179
  { text: ' ', key: null },
1166
1180
  { text: globalBenchmarkLabel, key: 'u' },
1181
+ { text: probeLabel ? ' ' : '', key: null },
1182
+ { text: probeLabel, key: null },
1167
1183
  { text: ' ', key: null },
1168
1184
  { text: releaseLabel, key: null },
1169
1185
  ]
@@ -280,6 +280,12 @@ export function createTuiState({
280
280
  globalBenchmarkTotal: 0,
281
281
  globalBenchmarkCompleted: 0,
282
282
 
283
+ // 📖 404 Probe state (Ctrl+Shift+P)
284
+ probeRunning: false,
285
+ probeTotal: 0,
286
+ probeCompleted: 0,
287
+ probeHiddenCount: 0,
288
+
283
289
  // 📖 Header click flash animation: briefly highlights the clicked column header
284
290
  // 📖 with an inverse/bright style for ~250ms (3 frames at 12 FPS).
285
291
  headerFlashColumn: null, // 📖 Column name being flashed (null = no flash active)