free-coding-models 0.5.5 → 0.5.6

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 CHANGED
@@ -169,14 +169,17 @@ and every TUI capability that's safe to port ships behind a button or chip.
169
169
  | **Filter bar** | Sticky right below the header (always visible) · Tier / Status / Verdict / Health chip rows · Visibility dropdown (Normal / Configured only / Usable only) · Provider select · custom text filter chip with `X` clear · Reset button (TUI `N`) · ping mode (Speed / Normal / Slow / Forced) · "next ping in Xs" countdown (TUI style, always shown) |
170
170
  | **Stats bar** | Removed in M1 (users found it noisy; the table + chips carry the same info at a glance) |
171
171
  | **Detail panel** | Slide-in from the right on row click · per-row benchmark button (TUI `Ctrl+A`) · favorite toggle (TUI `F`) + up/down reorder (TUI `Shift+↑↓`) · latency trend chart · all stats |
172
- | **Command palette** | `⌘K` / `Ctrl+P` (the only global keyboard shortcut) · fuzzy search across views, theme, ping mode, reset, export |
172
+ | **Command palette** | `⌘K` / `Ctrl+P` (the only global keyboard shortcut) · fuzzy search across views, theme, ping mode, reset, export, **and the full TUI command registry** (every filter / sort / tool / page entry from `src/tui/command-palette.js`) |
173
173
  | **Keyboard** | `Esc` closes any modal · `Cmd+K` toggles the palette — that's it. Everything else is mouse-first. |
174
- | **URL deep-linking** | `?tier=S+&sort=verdict&origin=groq&view=dashboard&q=…` hydrates the dashboard on load. CLI flags become shareable links. |
174
+ | **URL deep-linking** | `?tier=S+&sort=verdict&origin=groq&view=dashboard&q=…` hydrates the dashboard on load **and** every filter / sort / view change is reflected back in the URL (debounced 80ms, `history.replaceState`). CLI flags become shareable links. |
175
175
  | **Favorites** | Shared with the TUI through `~/.free-coding-models.json` — a star in the Web is a star in the TUI. Includes pinned+sticky display mode (TUI `Y`). |
176
+ | **Help modal** | Header overflow menu → "Help" opens a full-screen modal with all the TUI's keyboard shortcuts, filter behavior, and parity notes. Live search bar. |
177
+ | **Changelog modal** | Header overflow menu → "Changelog" or Settings "Open Changelog" link. Two-phase (index of versions + per-version release notes). Deep-linkable to a specific version. |
178
+ | **Update flow** | Header `⬆ vX.Y.Z` chip + popover with "Update now" + "What's new" (jumps to the new version's changelog entry). Polls every 5 min. |
179
+ | **Settings parity** | Full Settings page: theme (auto/dark/light), favorites pinned mode, startup AI Speed Scan, shell env export, legacy proxy cleanup, per-provider **Test** key button (TUI `T` key), update row. All settings persisted to the same `~/.free-coding-models.json` the TUI uses. |
176
180
  | **Theme** | Tri-state `auto / dark / light` cycle (TUI `G`) — auto follows the OS preference. |
177
181
 
178
- Roadmap items (header menu badges show "M2 / M3 / M4" until they land):
179
- - **M2** — Help modal, Changelog viewer, Settings parity (theme toggle, test key, shell-env, legacy cleanup, startup AI scan), Update flow, URL write-back, full command palette backed by the TUI registry.
182
+ Roadmap items (header menu badges show "M3 / M4" until they land):
180
183
  - **M3** — Smart Recommend (3-question wizard → 10s analysis → Top 3), tool mode picker, per-row Launch, missing-tool install prompt, incompatible-fallback modal.
181
184
  - **M4** — Router Dashboard, Token Usage, Install Endpoints wizard, Installed Models manager.
182
185
 
@@ -511,7 +514,7 @@ When a tool mode is active (via `Z`), models incompatible with that tool are hig
511
514
  - **Readable everywhere** — semantic theme palette keeps table rows, overlays, badges, and help screens legible in dark and light terminals
512
515
  - **Global theme switch** — `G` cycles `auto`, `dark`, + `light` live without restarting
513
516
  - **Auto-retry** — timeout models keep getting retried
514
- - **Aggressive update nudging** — fluorescent green banner when an update is available, impossible to miss, Shift+U hotkey, command palette entry, background re-check every 5 min, mid-session updates the banner live without restarting
517
+ - **Mandatory self-update policy** — startup checks npm for a newer FCM and installs it automatically without a prompt. If the install fails twice in a row (offline, proxy, or permissions), FCM still starts but shows a red outdated-version warning until the user retries with `Shift+U` or runs the displayed install command.
515
518
  - **Last release timestamp** — light pink footer shows `Last release: Mar 27, 2026, 09:42 PM` from npm so users know how fresh the data is
516
519
 
517
520
  ---
@@ -72,6 +72,12 @@ async function main() {
72
72
 
73
73
  if (startupUpdate.updated) return;
74
74
  if (startupUpdate.blocked) process.exit(1);
75
+ if (startupUpdate.allowedOutdated) {
76
+ process.env.FCM_UPDATE_ALLOWED_OUTDATED = '1';
77
+ process.env.FCM_UPDATE_LATEST_VERSION = startupUpdate.latestVersion || '';
78
+ process.env.FCM_UPDATE_WARNING_MESSAGE = startupUpdate.warningMessage || '';
79
+ process.env.FCM_UPDATE_FAILURES = String(startupUpdate.failures || 0);
80
+ }
75
81
 
76
82
  // 📖 Standalone web dashboard: same full-catalog ping UI as the TUI, served
77
83
  // 📖 locally with Socket.IO/SSE/REST realtime updates.
@@ -1,6 +1,7 @@
1
1
  # Changelog v0.5.5 - 2026-06-01
2
2
 
3
3
  ### Changed
4
+ - 🔒 **Mandatory self-update policy**: FCM now checks npm at startup across the TUI, Web Dashboard, Docker/daemon, and Desktop sidecar paths, then installs newer releases automatically without asking the user. If automatic installation fails twice in a row, FCM stops blocking startup and shows a red outdated-version warning so offline/proxy/permission users can still work while clearly seeing that their model catalog may be stale.
4
5
  - ⬆️ **deps-dev**: bump `vite` from `8.0.14` → `8.0.16` (#105)
5
6
  - ⬆️ **deps-dev**: bump `vite-plus` from `0.1.20` → `0.1.23` (#106)
6
7
  - ⬆️ **deps-dev**: bump `@vitejs/plugin-react` from `6.0.1` → `6.0.2` (#107)
@@ -0,0 +1,24 @@
1
+ # Changelog v0.5.6 - 2026-06-01
2
+
3
+ ### Added
4
+ - **Web Dashboard M2 — Settings parity + full command palette + URL write-back + help / changelog / update** — the local Web Dashboard now mirrors the TUI for the everyday flow on every view it ships today.
5
+ - **Full command palette (TUI registry 1:1)** — `⌘K` / `Ctrl+P` opens a fuzzy-searchable palette that pulls every command from `src/tui/command-palette.js` (filters, sorts, target tools, theme, ping, reset, export, plus Web-only pages). Commands without a Web equivalent route to a friendly "arrives in M3/M4" toast.
6
+ - **Help modal** — Header overflow menu → "Help" opens a full-screen modal with 11 sections of Web behavior + TUI parity notes. Live search bar.
7
+ - **Changelog modal** — Two-phase (index of versions + per-version release notes). Settings "Open Changelog" link and the update chip "What's new" button both deep-link to a specific version.
8
+ - **Update chip + popover** — Header shows `⬆ vX.Y.Z` when a newer npm release is available. Click → "Update now" (spawns the package manager) + "What's new" (jumps to the new version's changelog entry). Polls every 5 minutes.
9
+ - **Full Settings parity** — theme dropdown (auto / dark / light), favorites pinned+sticky toggle, startup AI Speed Scan toggle, shell env export toggle, legacy proxy cleanup button, **per-provider Test key button** (TUI `T` key) with outcome badge, update status row, open Changelog link. All settings persist to the same `~/.free-coding-models.json` the TUI uses.
10
+ - **URL write-back (read + write)** — every filter / sort / view / tool-mode / palette state change is reflected back to the URL via `history.replaceState` (debounced 80ms). Sharing a URL with `?tier=S+&sort=verdict&origin=groq&view=analytics&q=…` opens a pre-filtered dashboard.
11
+
12
+ ### Changed
13
+ - **Web command palette upgraded** from M1's static placeholder to a fully wired palette that imports `buildCommandPaletteEntries` + `filterCommandPaletteEntries` from the TUI engine — both surfaces are now guaranteed to show the same command set.
14
+ - **Header menu** marks `Help` and `Changelog` as live (no more `M2` badge). `Recommend` (M3), `Router` (M4), `Install Endpoints` (M4), and `Installed Models` (M4) still badge.
15
+
16
+ ### Fixed
17
+ - 🐛 **TUI Changelog overlay was silently broken** — `src/core/changelog-loader.js` resolved `changelog/` relative to `src/` instead of the project root. Fix walks up two levels. The TUI's `N` key and the new Web Changelog modal both load 142 versioned changelog files now.
18
+ - 🐛 **`/api/key/:provider/test` and `/api/key/:provider` were colliding** — the general single-segment key match ate the two-segment test path. The test path is now matched at the top of the request handler so the two routes coexist.
19
+ - 🐛 **`/api/settings/feature` only handled booleans** — passing a string (e.g. `theme=dark`) silently fell into the toggle branch and saved `true`. The endpoint now accepts arbitrary `value` payloads (string, number, boolean) and only toggles when `value` is omitted.
20
+
21
+ ### Notes
22
+ - All 451 unit tests pass (was 440 before M2). The new M2 tests cover `buildUrlParams`, the URL state validation allowlists, and import-cleanly smoke tests for the three new React hooks.
23
+ - The TUI source of truth is untouched — every new Web feature uses the same engine modules (`src/core/changelog-loader.js`, `src/core/updater.js`, `src/core/legacy-proxy-cleanup.js`, `src/core/shell-env.js`, `src/tui/command-palette.js`).
24
+ - This release is the Web Dashboard reaching parity with the TUI for the day-to-day table flow. M3 ships the tool-mode picker + Smart Recommend; M4 ships the Router Dashboard + Token Usage.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "free-coding-models",
3
- "version": "0.5.5",
3
+ "version": "0.5.6",
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",
@@ -75,10 +75,10 @@
75
75
  "node": ">=18.0.0"
76
76
  },
77
77
  "devDependencies": {
78
- "@vitejs/plugin-react": "^6.0.1",
78
+ "@vitejs/plugin-react": "^6.0.2",
79
79
  "react": "^19.2.6",
80
80
  "react-dom": "^19.2.6",
81
- "vite": "^8.0.13",
82
- "vite-plus": "^0.1.16"
81
+ "vite": "^8.0.16",
82
+ "vite-plus": "^0.1.23"
83
83
  }
84
84
  }
@@ -20,7 +20,11 @@ import { fileURLToPath } from 'url'
20
20
 
21
21
  const __filename = fileURLToPath(import.meta.url)
22
22
  const __dirname = dirname(__filename)
23
- const CHANGELOG_DIR = join(__dirname, '..', 'changelog')
23
+ // 📖 Resolve the project-root changelog directory. The loader lives at
24
+ // 📖 src/core/, so we walk up two levels to reach the project root, then
25
+ // 📖 into changelog/. (A previous version only walked up one level and
26
+ // 📖 ended up pointing at src/changelog/, which never existed.)
27
+ const CHANGELOG_DIR = join(__dirname, '..', '..', 'changelog')
24
28
 
25
29
  /**
26
30
  * 📖 loadChangelog: Read and parse all per-version changelog files
@@ -353,6 +353,16 @@ function getWebModelsPayload(runtime) {
353
353
  return payload
354
354
  }
355
355
 
356
+ function getWebUpdateStatusPayload() {
357
+ if (process.env.FCM_UPDATE_ALLOWED_OUTDATED !== '1') return null
358
+ return {
359
+ latestVersion: process.env.FCM_UPDATE_LATEST_VERSION || null,
360
+ allowedOutdated: true,
361
+ warningMessage: process.env.FCM_UPDATE_WARNING_MESSAGE || null,
362
+ failures: Number.parseInt(process.env.FCM_UPDATE_FAILURES || '0', 10) || 0,
363
+ }
364
+ }
365
+
356
366
  function getWebStatePayload(runtime) {
357
367
  const router = runtime.routerConfig()
358
368
  const probeInterval = router.probeIntervals?.[router.probeMode] || DEFAULT_ROUTER_SETTINGS.probeIntervals.balanced
@@ -366,6 +376,7 @@ function getWebStatePayload(runtime) {
366
376
  globalBenchmarkRunning: runtime.webGlobalBenchmarkRunning || false,
367
377
  globalBenchmarkTotal: runtime.webGlobalBenchmarkTotal || 0,
368
378
  globalBenchmarkCompleted: runtime.webGlobalBenchmarkCompleted || 0,
379
+ updateStatus: getWebUpdateStatusPayload(),
369
380
  models: getWebModelsPayload(runtime),
370
381
  }
371
382
  }