free-coding-models 0.3.12 → 0.3.13

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/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ---
4
4
 
5
+ ## 0.3.13
6
+
7
+ ### Fixed
8
+ - **Small Width Warnings toggle actually works again**: the Settings row now shows `Small Width Warnings` with clear enabled/disabled status, the startup overlay reacts immediately to the toggle, and the narrow-terminal warning now auto-hides after 2 seconds instead of 4.
9
+
5
10
  ## 0.3.12
6
11
 
7
12
  > **Proxy / bridge update:** the current legacy proxy stack is now officially discontinued while we rebuild that whole layer from zero. This cleanup is intentional: Claude Code support, a smarter router, and a much more reliable external-tools bridge are being reworked as a separate, cleaner system and will come back in a future release. In the meantime, FCM has been cleaned up and narrowed to the stable direct-launch surface so the app stays solid for day-to-day usage.
@@ -399,11 +399,11 @@ async function main() {
399
399
  originFilterMode: 0, // 📖 Index into ORIGIN_CYCLE (0=All, then providers)
400
400
  premiumMode: cliArgs.premiumMode, // 📖 Special elite-only mode: S/S+ only, Health UP only, Perfect/Normal/Slow verdict only.
401
401
  hideUnconfiguredModels: config.settings?.hideUnconfiguredModels === true, // 📖 Hide providers with no configured API key when true.
402
- disableWidthsWarning: config.settings?.disableWidthsWarning ?? false, // 📖 Disable widths warning toggle (default off)
402
+ disableWidthsWarning: config.settings?.disableWidthsWarning ?? false, // 📖 Cached for runtime checks; keep it in sync with config.settings.
403
403
  scrollOffset: 0, // 📖 First visible model index in viewport
404
404
  terminalRows: process.stdout.rows || 24, // 📖 Current terminal height
405
405
  terminalCols: process.stdout.columns || 80, // 📖 Current terminal width
406
- widthWarningStartedAt: (process.stdout.columns || 80) < 166 ? now : null, // 📖 Start the narrow-terminal countdown immediately when booting in a small viewport.
406
+ widthWarningStartedAt: (process.stdout.columns || 80) < 166 && !(config.settings?.disableWidthsWarning ?? false) ? now : null, // 📖 Start immediately only when warnings are enabled in a narrow viewport.
407
407
  widthWarningDismissed: false, // 📖 Esc hides the narrow-terminal warning early for the current narrow-width session.
408
408
  widthWarningShowCount: 0, // 📖 Counter for how many times the narrow-terminal warning has been shown (max 2 per session).
409
409
  // 📖 Settings screen state (P key opens it)
@@ -465,9 +465,11 @@ async function main() {
465
465
  // 📖 Re-clamp viewport on terminal resize
466
466
  process.stdout.on('resize', () => {
467
467
  const prevCols = state.terminalCols
468
+ const widthsWarningDisabled = state.config.settings?.disableWidthsWarning === true
468
469
  state.terminalRows = process.stdout.rows || 24
469
470
  state.terminalCols = process.stdout.columns || 80
470
- if (state.terminalCols < 166 && !state.disableWidthsWarning) {
471
+ state.disableWidthsWarning = widthsWarningDisabled
472
+ if (state.terminalCols < 166 && !widthsWarningDisabled) {
471
473
  if (prevCols >= 166 || state.widthWarningDismissed) {
472
474
  state.widthWarningStartedAt = Date.now()
473
475
  state.widthWarningDismissed = false
@@ -862,7 +864,7 @@ async function main() {
862
864
  ? overlays.renderHelp()
863
865
  : state.changelogOpen
864
866
  ? overlays.renderChangelog()
865
- : renderTable(state.results, state.pendingPings, state.frame, state.cursor, state.sortColumn, state.sortDirection, state.pingInterval, state.lastPingTime, state.mode, state.tierFilterMode, state.scrollOffset, state.terminalRows, state.terminalCols, state.originFilterMode, null, state.pingMode, state.pingModeSource, state.hideUnconfiguredModels, state.widthWarningStartedAt, state.widthWarningDismissed, state.widthWarningShowCount, state.settingsUpdateState, state.settingsUpdateLatestVersion, false, state.startupLatestVersion, state.versionAlertsEnabled)
867
+ : renderTable(state.results, state.pendingPings, state.frame, state.cursor, state.sortColumn, state.sortDirection, state.pingInterval, state.lastPingTime, state.mode, state.tierFilterMode, state.scrollOffset, state.terminalRows, state.terminalCols, state.originFilterMode, null, state.pingMode, state.pingModeSource, state.hideUnconfiguredModels, state.widthWarningStartedAt, state.widthWarningDismissed, state.widthWarningShowCount, state.settingsUpdateState, state.settingsUpdateLatestVersion, false, state.startupLatestVersion, state.versionAlertsEnabled, state.config.settings?.disableWidthsWarning ?? false)
866
868
  process.stdout.write(ALT_HOME + content)
867
869
  if (process.stdout.isTTY) {
868
870
  process.stdout.flush && process.stdout.flush()
@@ -873,7 +875,7 @@ async function main() {
873
875
  const initialVisible = state.results.filter(r => !r.hidden)
874
876
  state.visibleSorted = sortResultsWithPinnedFavorites(initialVisible, state.sortColumn, state.sortDirection)
875
877
 
876
- process.stdout.write(ALT_HOME + renderTable(state.results, state.pendingPings, state.frame, state.cursor, state.sortColumn, state.sortDirection, state.pingInterval, state.lastPingTime, state.mode, state.tierFilterMode, state.scrollOffset, state.terminalRows, state.terminalCols, state.originFilterMode, null, state.pingMode, state.pingModeSource, state.hideUnconfiguredModels, state.widthWarningStartedAt, state.widthWarningDismissed, state.widthWarningShowCount, state.settingsUpdateState, state.settingsUpdateLatestVersion, false, state.startupLatestVersion, state.versionAlertsEnabled))
878
+ process.stdout.write(ALT_HOME + renderTable(state.results, state.pendingPings, state.frame, state.cursor, state.sortColumn, state.sortDirection, state.pingInterval, state.lastPingTime, state.mode, state.tierFilterMode, state.scrollOffset, state.terminalRows, state.terminalCols, state.originFilterMode, null, state.pingMode, state.pingModeSource, state.hideUnconfiguredModels, state.widthWarningStartedAt, state.widthWarningDismissed, state.widthWarningShowCount, state.settingsUpdateState, state.settingsUpdateLatestVersion, false, state.startupLatestVersion, state.versionAlertsEnabled, state.config.settings?.disableWidthsWarning ?? false))
877
879
  if (process.stdout.isTTY) {
878
880
  process.stdout.flush && process.stdout.flush()
879
881
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "free-coding-models",
3
- "version": "0.3.12",
3
+ "version": "0.3.13",
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",
@@ -350,6 +350,38 @@ export function createKeyHandler(ctx) {
350
350
  }
351
351
  }
352
352
 
353
+ // 📖 Keep the width-warning runtime state synced with the persisted Settings toggle
354
+ // 📖 so the overlay reacts immediately when the user enables or disables it.
355
+ function syncWidthsWarningState() {
356
+ const widthsWarningDisabled = state.config.settings?.disableWidthsWarning === true
357
+ state.disableWidthsWarning = widthsWarningDisabled
358
+
359
+ if (widthsWarningDisabled) {
360
+ state.widthWarningStartedAt = null
361
+ state.widthWarningDismissed = false
362
+ return
363
+ }
364
+
365
+ state.widthWarningShowCount = 0
366
+ if ((state.terminalCols || 80) < 166) {
367
+ state.widthWarningStartedAt = Date.now()
368
+ state.widthWarningDismissed = false
369
+ return
370
+ }
371
+
372
+ state.widthWarningStartedAt = null
373
+ state.widthWarningDismissed = false
374
+ }
375
+
376
+ // 📖 Toggle the width-warning setting and apply the effect immediately instead
377
+ // 📖 of waiting for a resize or restart.
378
+ function toggleWidthsWarningSetting() {
379
+ if (!state.config.settings) state.config.settings = {}
380
+ state.config.settings.disableWidthsWarning = !state.config.settings.disableWidthsWarning
381
+ syncWidthsWarningState()
382
+ saveConfig(state.config)
383
+ }
384
+
353
385
  function resetInstallEndpointsOverlay() {
354
386
  state.installEndpointsOpen = false
355
387
  state.installEndpointsPhase = 'providers'
@@ -1040,9 +1072,7 @@ export function createKeyHandler(ctx) {
1040
1072
 
1041
1073
  // 📖 Widths Warning toggle (Enter to toggle)
1042
1074
  if (state.settingsCursor === widthWarningRowIdx) {
1043
- if (!state.config.settings) state.config.settings = {}
1044
- state.config.settings.disableWidthsWarning = !state.config.settings.disableWidthsWarning
1045
- saveConfig(state.config)
1075
+ toggleWidthsWarningSetting()
1046
1076
  return
1047
1077
  }
1048
1078
 
@@ -1080,9 +1110,7 @@ export function createKeyHandler(ctx) {
1080
1110
  ) return
1081
1111
  // 📖 Widths Warning toggle (disable/enable)
1082
1112
  if (state.settingsCursor === widthWarningRowIdx) {
1083
- if (!state.config.settings) state.config.settings = {}
1084
- state.config.settings.disableWidthsWarning = !state.config.settings.disableWidthsWarning
1085
- saveConfig(state.config)
1113
+ toggleWidthsWarningSetting()
1086
1114
  return
1087
1115
  }
1088
1116
  // 📖 Profile system removed - API keys now persist permanently across all sessions
package/src/overlays.js CHANGED
@@ -217,11 +217,13 @@ export function createOverlayRenderers(state, deps) {
217
217
  const updateRow = `${updateBullet}${chalk.bold(updateActionLabel).padEnd(44)} ${updateStatus}`
218
218
  cursorLineByRow[updateRowIdx] = lines.length
219
219
  lines.push(updateCursor ? chalk.bgRgb(30, 30, 60)(updateRow) : updateRow)
220
- // 📖 Widths Warning toggle row (disable widths warning)
220
+ // 📖 Width warning visibility row for the startup narrow-terminal overlay.
221
221
  const disableWidthsWarning = Boolean(state.config.settings?.disableWidthsWarning)
222
222
  const widthWarningBullet = state.settingsCursor === widthWarningRowIdx ? chalk.bold.cyan(' ❯ ') : chalk.dim(' ')
223
- const widthWarningStatus = disableWidthsWarning ? chalk.greenBright('DISABLED') : chalk.dim('enabled')
224
- const widthWarningRow = `${widthWarningBullet}${chalk.bold('Disable Widths Warning').padEnd(44)} ${widthWarningStatus}`
223
+ const widthWarningStatus = disableWidthsWarning
224
+ ? chalk.redBright('🙈 Disabled')
225
+ : chalk.greenBright('👁 Enabled')
226
+ const widthWarningRow = `${widthWarningBullet}${chalk.bold('Small Width Warnings').padEnd(44)} ${widthWarningStatus}`
225
227
  cursorLineByRow[widthWarningRowIdx] = lines.length
226
228
  lines.push(state.settingsCursor === widthWarningRowIdx ? chalk.bgRgb(30, 30, 60)(widthWarningRow) : widthWarningRow)
227
229
  if (updateState === 'error' && state.settingsUpdateError) {
@@ -181,7 +181,7 @@ export function renderTable(results, pendingPings, frame, cursor = null, sortCol
181
181
  const W_TOKENS = 7
182
182
  // const W_USAGE = 7 // Usage column removed
183
183
  const MIN_TABLE_WIDTH = 166
184
- const warningDurationMs = 4_000
184
+ const warningDurationMs = 2_000
185
185
  const elapsed = widthWarningStartedAt ? Math.max(0, Date.now() - widthWarningStartedAt) : warningDurationMs
186
186
  const remainingMs = Math.max(0, warningDurationMs - elapsed)
187
187
  const showWidthWarning = terminalCols > 0 && terminalCols < MIN_TABLE_WIDTH && !disableWidthsWarning && !widthWarningDismissed && widthWarningShowCount < 2 && remainingMs > 0