free-coding-models 0.1.20 → 0.1.21

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.
@@ -328,10 +328,13 @@ const spinCell = (f, o = 0) => chalk.dim.yellow(FRAMES[(f + o) % FRAMES.length].
328
328
 
329
329
  // 📖 renderTable: mode param controls footer hint text (opencode vs openclaw)
330
330
  function renderTable(results, pendingPings, frame, cursor = null, sortColumn = 'avg', sortDirection = 'asc', pingInterval = PING_INTERVAL, lastPingTime = Date.now(), mode = 'opencode', tierFilter = null) {
331
- const up = results.filter(r => r.status === 'up').length
332
- const down = results.filter(r => r.status === 'down').length
333
- const timeout = results.filter(r => r.status === 'timeout').length
334
- const pending = results.filter(r => r.status === 'pending').length
331
+ // 📖 Filter out hidden models for display
332
+ const visibleResults = results.filter(r => !r.hidden)
333
+
334
+ const up = visibleResults.filter(r => r.status === 'up').length
335
+ const down = visibleResults.filter(r => r.status === 'down').length
336
+ const timeout = visibleResults.filter(r => r.status === 'timeout').length
337
+ const pending = visibleResults.filter(r => r.status === 'pending').length
335
338
 
336
339
  // 📖 Calculate seconds until next ping
337
340
  const timeSinceLastPing = Date.now() - lastPingTime
@@ -372,7 +375,7 @@ function renderTable(results, pendingPings, frame, cursor = null, sortColumn = '
372
375
  const W_UPTIME = 6
373
376
 
374
377
  // 📖 Sort models using the shared helper
375
- const sorted = sortResults(results, sortColumn, sortDirection)
378
+ const sorted = sortResults(visibleResults, sortColumn, sortDirection)
376
379
 
377
380
  const lines = [
378
381
  '',
@@ -1055,21 +1058,33 @@ async function main() {
1055
1058
  console.log()
1056
1059
  }
1057
1060
 
1058
- // 📖 Filter models to only show top tiers if BEST mode is active
1061
+ // 📖 Create results array with all models initially visible
1059
1062
  let results = MODELS.map(([modelId, label, tier], i) => ({
1060
1063
  idx: i + 1, modelId, label, tier,
1061
1064
  status: 'pending',
1062
1065
  pings: [], // 📖 All ping results (ms or 'TIMEOUT')
1063
1066
  httpCode: null,
1067
+ hidden: false, // 📖 Simple flag to hide/show models
1064
1068
  }))
1065
1069
 
1070
+ // 📖 Apply filters by setting hidden flag
1066
1071
  if (bestMode) {
1067
- results = results.filter(r => r.tier === 'S+' || r.tier === 'S' || r.tier === 'A+')
1072
+ results.forEach(r => {
1073
+ r.hidden = !(r.tier === 'S+' || r.tier === 'S' || r.tier === 'A+')
1074
+ })
1068
1075
  }
1069
1076
 
1070
- // 📖 Apply tier letter filter if --tier X was given
1077
+ // 📖 Apply tier letter filter if --tier X was given (just sets initial state)
1078
+ // 📖 User can still change filter with E/D keys later
1071
1079
  if (tierFilter) {
1072
- results = filterByTierOrExit(results, tierFilter)
1080
+ const tierSet = TIER_LETTER_MAP[tierFilter]
1081
+ if (!tierSet) {
1082
+ console.error(chalk.red(` ✖ Unknown tier "${tierFilter}". Valid tiers: S, A, B, C`))
1083
+ process.exit(1)
1084
+ }
1085
+ results.forEach(r => {
1086
+ r.hidden = !tierSet.includes(r.tier)
1087
+ })
1073
1088
  }
1074
1089
 
1075
1090
  // 📖 Add interactive selection state - cursor index and user's choice
@@ -1105,38 +1120,17 @@ async function main() {
1105
1120
  process.on('SIGINT', () => exit(0))
1106
1121
  process.on('SIGTERM', () => exit(0))
1107
1122
 
1108
- // 📖 Apply tier filter to results based on current state.tierFilter
1109
- // 📖 Preserves existing ping history when filtering
1123
+ // 📖 Apply tier filter based on current state.tierFilter
1124
+ // 📖 This preserves all ping history by merging with existing results
1110
1125
  function applyTierFilter() {
1111
- const allModels = MODELS.map(([modelId, label, tier], i) => ({
1112
- idx: i + 1, modelId, label, tier,
1113
- status: 'pending',
1114
- pings: [],
1115
- httpCode: null,
1116
- }))
1117
-
1118
- if (!state.tierFilter) {
1119
- return allModels
1120
- }
1121
-
1122
- // 📖 Filter models by tier and preserve existing ping history
1123
- const filteredModels = allModels.filter(model =>
1124
- TIER_LETTER_MAP[state.tierFilter].includes(model.tier)
1125
- )
1126
+ const tierSet = state.tierFilter ? TIER_LETTER_MAP[state.tierFilter] : null
1126
1127
 
1127
- // 📖 Try to preserve existing ping data from current results
1128
- return filteredModels.map(model => {
1129
- const existingResult = state.results.find(r => r.modelId === model.modelId)
1130
- if (existingResult) {
1131
- return {
1132
- ...model,
1133
- status: existingResult.status,
1134
- pings: [...existingResult.pings],
1135
- httpCode: existingResult.httpCode
1136
- }
1137
- }
1138
- return model
1128
+ // 📖 Simple approach: just update hidden flag on existing results
1129
+ state.results.forEach(r => {
1130
+ r.hidden = tierSet ? !tierSet.includes(r.tier) : false
1139
1131
  })
1132
+
1133
+ return state.results // 📖 Return same array, just updated hidden flags
1140
1134
  }
1141
1135
 
1142
1136
  // 📖 Setup keyboard input for interactive selection during pings
@@ -1294,14 +1288,14 @@ async function main() {
1294
1288
  }
1295
1289
 
1296
1290
  // 📖 Initial ping of all models
1297
- const initialPing = Promise.all(results.map(r => pingModel(r)))
1291
+ const initialPing = Promise.all(state.results.map(r => pingModel(r)))
1298
1292
 
1299
1293
  // 📖 Continuous ping loop with dynamic interval (adjustable with W/X keys)
1300
1294
  const schedulePing = () => {
1301
1295
  state.pingIntervalObj = setTimeout(async () => {
1302
1296
  state.lastPingTime = Date.now()
1303
1297
 
1304
- results.forEach(r => {
1298
+ state.results.forEach(r => {
1305
1299
  pingModel(r).catch(() => {
1306
1300
  // Individual ping failures don't crash the loop
1307
1301
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "free-coding-models",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "Find the fastest coding LLM models in seconds — ping free models from multiple providers, pick the best one for OpenCode, Cursor, or any AI coding assistant.",
5
5
  "keywords": [
6
6
  "nvidia",