free-coding-models 0.5.30 → 0.5.32

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.
@@ -10,7 +10,7 @@
10
10
  // 📖 npm install running on the same machine.
11
11
  // 📖 IMPORTANT: these checks MUST run synchronously before any static imports
12
12
  // 📖 resolve, because router-daemon.js reads FCM_DEV at module load time.
13
- import { existsSync } from 'node:fs'
13
+ import { existsSync, readFileSync } from 'node:fs'
14
14
  import { join, dirname } from 'node:path'
15
15
  import { fileURLToPath } from 'node:url'
16
16
  if (process.argv.includes('--dev') || (!process.env.FCM_DEV && existsSync(join(dirname(fileURLToPath(import.meta.url)), '..', '.git')))) {
@@ -78,7 +78,14 @@ async function main() {
78
78
  })
79
79
  : { latestVersion: null, allowedOutdated: false, warningMessage: null, failures: 0, checked: false, updated: false, blocked: false };
80
80
 
81
- if (startupUpdate.updated) return;
81
+ if (startupUpdate.updated) {
82
+ try {
83
+ // 📖 Stop any running daemon so that the relaunch/restart will start the new version.
84
+ const { stopRouterDaemon } = await import('../src/core/router-daemon.js');
85
+ await stopRouterDaemon();
86
+ } catch {}
87
+ return;
88
+ }
82
89
  if (startupUpdate.blocked) process.exit(1);
83
90
  if (startupUpdate.allowedOutdated) {
84
91
  process.env.FCM_UPDATE_ALLOWED_OUTDATED = '1';
@@ -87,6 +94,19 @@ async function main() {
87
94
  process.env.FCM_UPDATE_FAILURES = String(startupUpdate.failures || 0);
88
95
  }
89
96
 
97
+ // 📖 If the daemon is running an outdated version, stop it so it will restart on the new version.
98
+ if (!cliArgs.daemonStopMode && !cliArgs.daemonStatusMode) {
99
+ try {
100
+ const { getRouterDaemonStatus, stopRouterDaemon } = await import('../src/core/router-daemon.js');
101
+ const status = await getRouterDaemonStatus();
102
+ const LOCAL_VERSION = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
103
+ if (status.ok && status.version && status.version !== LOCAL_VERSION) {
104
+ console.log(chalk.yellow(` ⚠ Outdated daemon version v${status.version} detected (current: v${LOCAL_VERSION}). Stopping old daemon...`));
105
+ await stopRouterDaemon();
106
+ }
107
+ } catch {}
108
+ }
109
+
90
110
  // 📖 Standalone web dashboard: same full-catalog ping UI as the TUI, served
91
111
  // 📖 locally with Socket.IO/SSE/REST realtime updates.
92
112
  if (cliArgs.webMode) {
@@ -0,0 +1,6 @@
1
+ # Changelog v0.5.31 - 2026-06-15
2
+
3
+ ### Added
4
+ - **"Use favorites" button in the Router Set Dashboard.** Added a "Use favorites" action to the active set manager on the Router Dashboard, allowing you to instantly replace the current set of routed models with your starred/favorited models.
5
+ - **Support for overwriting router sets via PUT `/api/router/sets/:name`**. Exposes a new PUT endpoint in the local web server to safely update/overwrite the models in a set in one request, proxying to the daemon (with a config-write fallback when the daemon is offline).
6
+ - **Unit test for the PUT sets endpoint** in `test/test.js` to ensure stability and verify that the endpoint correctly updates the set.
@@ -0,0 +1,4 @@
1
+ # Changelog v0.5.32 - 2026-06-15
2
+
3
+ ### Added
4
+ - **Automatic daemon restart on version mismatch.** Added version detection to the daemon `/health` status payload. The CLI now automatically checks the running daemon version on startup (or when starting the daemon in the background) and terminates the outdated daemon if a version mismatch with the current CLI is detected, forcing a restart on the new version.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "free-coding-models",
3
- "version": "0.5.30",
3
+ "version": "0.5.32",
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",
@@ -1379,6 +1379,7 @@ class RouterRuntime {
1379
1379
  // 📖 the Playground showed "router offline" even when the Router card
1380
1380
  // 📖 said "Running" — both hit /api/router/status but read different fields.
1381
1381
  running: true,
1382
+ version: LOCAL_VERSION,
1382
1383
  pid: process.pid,
1383
1384
  port: this.port,
1384
1385
  enabled: router.enabled,
@@ -3526,7 +3527,13 @@ export async function getRouterDaemonStatus() {
3526
3527
 
3527
3528
  export async function startRouterDaemonBackground() {
3528
3529
  const existing = await getRouterDaemonStatus()
3529
- if (existing.ok) return { ...existing, alreadyRunning: true }
3530
+ if (existing.ok) {
3531
+ if (existing.version && existing.version !== LOCAL_VERSION) {
3532
+ await stopRouterDaemon()
3533
+ } else {
3534
+ return { ...existing, alreadyRunning: true }
3535
+ }
3536
+ }
3530
3537
 
3531
3538
  const child = fork(CLI_ENTRY_PATH, ['--daemon'], {
3532
3539
  detached: true,