Skip to content

Commit 4c38c3e

Browse files
committed
0.1.32
1 parent e74bf25 commit 4c38c3e

File tree

4 files changed

+43
-34
lines changed

4 files changed

+43
-34
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22

33
---
44

5+
## 0.1.32 — 2026-02-22
6+
7+
### Changed
8+
- **Column header improvements**: Fixed column alignment issues for better visual appearance
9+
- **Status renamed to Condition**: "Status" column renamed to "Condition" for clarity
10+
- **Keyboard shortcut updates**: S key now sorts by SWE-bench score, C key sorts by Condition
11+
- **Footer Discord text update**: Changed "Join our Discord!" to "Join Free-Coding-Models Discord!"
12+
13+
---
14+
515
## 0.1.31 — 2026-02-22
616

717
### Added

bin/free-coding-models.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ function renderTable(results, pendingPings, frame, cursor = null, sortColumn = '
425425
const sweH = sortColumn === 'swe' ? dir + ' SWE%' : 'SWE%'
426426
const pingH = sortColumn === 'ping' ? dir + ' Latest Ping' : 'Latest Ping'
427427
const avgH = sortColumn === 'avg' ? dir + ' Avg Ping' : 'Avg Ping'
428-
const statusH = sortColumn === 'status' ? dir + ' Status' : 'Status'
428+
const conditionH = sortColumn === 'condition' ? dir + ' Condition' : 'Condition'
429429
const verdictH = sortColumn === 'verdict' ? dir + ' Verdict' : 'Verdict'
430430
const uptimeH = sortColumn === 'uptime' ? dir + ' Up%' : 'Up%'
431431

@@ -441,15 +441,15 @@ function renderTable(results, pendingPings, frame, cursor = null, sortColumn = '
441441
const tierH_c = colorFirst('Tier', W_TIER)
442442
const originH_c = sortColumn === 'origin' ? chalk.bold.cyan(originH.padEnd(W_SOURCE)) : colorFirst(originH, W_SOURCE)
443443
const modelH_c = colorFirst(modelH, W_MODEL)
444-
const sweH_c = sortColumn === 'swe' ? chalk.bold.cyan(sweH.padEnd(W_SWE)) : colorFirst(sweH, W_SWE)
445-
const pingH_c = sortColumn === 'ping' ? chalk.bold.cyan(pingH.padEnd(W_PING)) : colorFirst(pingH.replace('Latest ', ''), W_PING)
446-
const avgH_c = sortColumn === 'avg' ? chalk.bold.cyan(avgH.padEnd(W_AVG)) : colorFirst(avgH.replace('Avg ', ''), W_AVG)
447-
const statusH_c = sortColumn === 'status' ? chalk.bold.cyan(statusH.padEnd(W_STATUS)) : colorFirst(statusH, W_STATUS)
444+
const sweH_c = sortColumn === 'swe' ? chalk.bold.cyan(sweH.padEnd(W_SWE)) : colorFirst('SWE%', W_SWE)
445+
const pingH_c = sortColumn === 'ping' ? chalk.bold.cyan(pingH.padEnd(W_PING)) : colorFirst('Latest Ping', W_PING)
446+
const avgH_c = sortColumn === 'avg' ? chalk.bold.cyan(avgH.padEnd(W_AVG)) : colorFirst('Avg Ping', W_AVG)
447+
const conditionH_c = sortColumn === 'condition' ? chalk.bold.cyan(conditionH.padEnd(W_STATUS)) : colorFirst('Condition', W_STATUS)
448448
const verdictH_c = sortColumn === 'verdict' ? chalk.bold.cyan(verdictH.padEnd(W_VERDICT)) : colorFirst(verdictH, W_VERDICT)
449449
const uptimeH_c = sortColumn === 'uptime' ? chalk.bold.cyan(uptimeH.padStart(W_UPTIME)) : colorFirst(uptimeH, W_UPTIME, chalk.green)
450450

451451
// 📖 Header with proper spacing
452-
lines.push(' ' + rankH_c + ' ' + tierH_c + ' ' + originH_c + ' ' + modelH_c + ' ' + sweH_c + ' ' + pingH_c + ' ' + avgH_c + ' ' + statusH_c + ' ' + verdictH_c + ' ' + uptimeH_c)
452+
lines.push(' ' + rankH_c + ' ' + tierH_c + ' ' + originH_c + ' ' + modelH_c + ' ' + sweH_c + ' ' + pingH_c + ' ' + avgH_c + ' ' + conditionH_c + ' ' + verdictH_c + ' ' + uptimeH_c)
453453

454454
// 📖 Separator line
455455
lines.push(
@@ -618,9 +618,9 @@ function renderTable(results, pendingPings, frame, cursor = null, sortColumn = '
618618
: mode === 'opencode-desktop'
619619
? chalk.rgb(0, 200, 255)('Enter→OpenDesktop')
620620
: chalk.rgb(0, 200, 255)('Enter→OpenCode')
621-
lines.push(chalk.dim(` ↑↓ Navigate • `) + actionHint + chalk.dim(` • R/T/O/M/L/A/S/V/U/E Sort • W↓/X↑ Interval (${intervalSec}s) • T Tier • Z Mode • Ctrl+C Exit`))
621+
lines.push(chalk.dim(` ↑↓ Navigate • `) + actionHint + chalk.dim(` • R/T/O/M/L/A/S/C/V/U Sort • W↓/X↑ Interval (${intervalSec}s) • T Tier • Z Mode • Ctrl+C Exit`))
622622
lines.push('')
623-
lines.push(chalk.dim(' Made with ') + '💖' + chalk.dim(' by ') + '\x1b]8;;https://github.com/vava-nessa\x1b\\vava-nessa\x1b]8;;\x1b\\' + chalk.dim(' • ') + '💬 ' + chalk.cyanBright('\x1b]8;;https://discord.gg/WKA3TwYVuZ\x1b\\Join our Discord! (link fixed)\x1b]8;;\x1b\\') + chalk.dim(' • ') + '⭐ ' + '\x1b]8;;https://github.com/vava-nessa/free-coding-models\x1b\\Read the docs on GitHub\x1b]8;;\x1b\\')
623+
lines.push(chalk.dim(' Made with ') + '💖 & ☕' + chalk.dim(' by ') + '\x1b]8;;https://github.com/vava-nessa\x1b\\vava-nessa\x1b]8;;\x1b\\' + chalk.dim(' • ') + '💬 ' + chalk.cyanBright('\x1b]8;;https://discord.gg/WKA3TwYVuZ\x1b\\Join Free-Coding-Models Discord!\x1b]8;;\x1b\\') + chalk.dim(' • ') + '⭐ ' + '\x1b]8;;https://github.com/vava-nessa/free-coding-models\x1b\\Read the docs on GitHub\x1b]8;;\x1b\\')
624624
lines.push('')
625625
// 📖 Append \x1b[K (erase to EOL) to each line so leftover chars from previous
626626
// 📖 frames are cleared. Then pad with blank cleared lines to fill the terminal,
@@ -1191,11 +1191,10 @@ async function main() {
11911191
const onKeyPress = async (str, key) => {
11921192
if (!key) return
11931193

1194-
// 📖 Sorting keys: R=rank, T=tier, O=origin, M=model, L=latest ping, A=avg ping, S=status, V=verdict, U=uptime, E=SWE-bench
1194+
// 📖 Sorting keys: R=rank, T=tier, O=origin, M=model, L=latest ping, A=avg ping, S=SWE-bench, C=condition, V=verdict, U=uptime
11951195
const sortKeys = {
11961196
'r': 'rank', 't': 'tier', 'o': 'origin', 'm': 'model',
1197-
'l': 'ping', 'a': 'avg', 's': 'status', 'v': 'verdict', 'u': 'uptime',
1198-
'e': 'swe'
1197+
'l': 'ping', 'a': 'avg', 's': 'swe', 'c': 'condition', 'v': 'verdict', 'u': 'uptime'
11991198
}
12001199

12011200
if (sortKeys[key.name]) {

lib/utils.js

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -129,16 +129,16 @@ export const getUptime = (r) => {
129129
// 📖 Returns a NEW array — never mutates the original (important for React-style re-renders).
130130
//
131131
// 📖 Supported columns (matching the keyboard shortcuts in the TUI):
132-
// - 'rank' (R key) — original index from sources.js
133-
// - 'tier' (T key) — tier hierarchy (S+ first, C last)
134-
// - 'origin' (O key) — provider name (all NIM for now, future-proofed)
135-
// - 'model' (M key) — alphabetical by display label
136-
// - 'ping' (L key) — last ping latency (only successful ones count)
137-
// - 'avg' (A key) — average latency across all successful pings
138-
// - 'status' (S key) — alphabetical status string
139-
// - 'verdict' (V key) — verdict order (Perfect → Pending)
140-
// - 'uptime' (U key) — uptime percentage
141-
// - 'swe' (E key) — SWE-bench score (higher is better)
132+
// - 'rank' (R key) — original index from sources.js
133+
// - 'tier' (T key) — tier hierarchy (S+ first, C last)
134+
// - 'origin' (O key) — provider name (all NIM for now, future-proofed)
135+
// - 'model' (M key) — alphabetical by display label
136+
// - 'ping' (L key) — last ping latency (only successful ones count)
137+
// - 'avg' (A key) — average latency across all successful pings
138+
// - 'swe' (S key) — SWE-bench score (higher is better)
139+
// - 'condition'(C key) — alphabetical condition string
140+
// - 'verdict' (V key) — verdict order (Perfect → Pending)
141+
// - 'uptime' (U key) — uptime percentage
142142
//
143143
// 📖 sortDirection 'asc' = ascending (smallest first), 'desc' = descending (largest first)
144144
export const sortResults = (results, sortColumn, sortDirection) => {
@@ -173,7 +173,18 @@ export const sortResults = (results, sortColumn, sortDirection) => {
173173
case 'avg':
174174
cmp = getAvg(a) - getAvg(b)
175175
break
176-
case 'status':
176+
case 'swe': {
177+
// 📖 Sort by SWE-bench score — higher is better
178+
// 📖 Parse percentage strings like "49.2%", "73.1%" or use 0 for missing values
179+
const parseSwe = (score) => {
180+
if (!score || score === '—') return 0
181+
const num = parseFloat(score.replace('%', ''))
182+
return isNaN(num) ? 0 : num
183+
}
184+
cmp = parseSwe(a.sweScore) - parseSwe(b.sweScore)
185+
break
186+
}
187+
case 'condition':
177188
cmp = a.status.localeCompare(b.status)
178189
break
179190
case 'verdict': {
@@ -186,17 +197,6 @@ export const sortResults = (results, sortColumn, sortDirection) => {
186197
case 'uptime':
187198
cmp = getUptime(a) - getUptime(b)
188199
break
189-
case 'swe': {
190-
// 📖 Sort by SWE-bench score — higher is better
191-
// 📖 Parse percentage strings like "49.2%", "73.1%" or use 0 for missing values
192-
const parseSwe = (score) => {
193-
if (!score || score === '—') return 0
194-
const num = parseFloat(score.replace('%', ''))
195-
return isNaN(num) ? 0 : num
196-
}
197-
cmp = parseSwe(a.sweScore) - parseSwe(b.sweScore)
198-
break
199-
}
200200
}
201201

202202
// 📖 Flip comparison for descending order

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "free-coding-models",
3-
"version": "0.1.31",
3+
"version": "0.1.32",
44
"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.",
55
"keywords": [
66
"nvidia",

0 commit comments

Comments
 (0)