@nexus-cortex/cli 4.30.0 → 4.31.0
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/bin/cortex.js +77 -30
- package/package.json +2 -2
package/bin/cortex.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
import { spawn, spawnSync } from 'child_process';
|
|
26
26
|
import { fileURLToPath } from 'url';
|
|
27
27
|
import { dirname, join, resolve } from 'path';
|
|
28
|
-
import { existsSync, readFileSync, realpathSync,
|
|
28
|
+
import { existsSync, readFileSync, realpathSync, mkdirSync, writeFileSync } from 'fs';
|
|
29
29
|
import { homedir } from 'os';
|
|
30
30
|
import { createRequire } from 'module';
|
|
31
31
|
|
|
@@ -62,36 +62,64 @@ if (!process.env.CORTEX_ROOT) {
|
|
|
62
62
|
const BASE_PORT = process.env.PORT || '4000';
|
|
63
63
|
const BASE_URL = process.env.CORTEX_URL || `http://localhost:${BASE_PORT}`;
|
|
64
64
|
|
|
65
|
-
// ──
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
try { mkdirSync(dirname(marker), { recursive: true }); writeFileSync(marker, String(Date.now())); } catch {}
|
|
65
|
+
// ── Self-update (transparent) ─────────────────────────────────────
|
|
66
|
+
// No silent background install (the old approach failed invisibly and locked itself).
|
|
67
|
+
// Instead: a one-line "update available" notice when a newer release exists (read from
|
|
68
|
+
// a tiny cached version check), and `cortex --update` to update on the spot with visible
|
|
69
|
+
// npm output. Silence the notice with CORTEX_NO_UPDATE_NOTICE=true.
|
|
70
|
+
const UPDATE_CACHE = join(homedir(), '.cortex', '.update-check');
|
|
71
|
+
const PKG_VERSION = (() => {
|
|
72
|
+
try { return JSON.parse(readFileSync(join(__cortex_dirname, '..', 'package.json'), 'utf8')).version; }
|
|
73
|
+
catch { return null; }
|
|
74
|
+
})();
|
|
75
|
+
|
|
76
|
+
function semverGt(a, b) {
|
|
77
|
+
const pa = String(a).split('.').map((n) => parseInt(n, 10) || 0);
|
|
78
|
+
const pb = String(b).split('.').map((n) => parseInt(n, 10) || 0);
|
|
79
|
+
for (let i = 0; i < 3; i++) {
|
|
80
|
+
if ((pa[i] || 0) > (pb[i] || 0)) return true;
|
|
81
|
+
if ((pa[i] || 0) < (pb[i] || 0)) return false;
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
86
85
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
async function fetchLatestVersion() {
|
|
87
|
+
try {
|
|
88
|
+
const https = await import('node:https');
|
|
89
|
+
return await new Promise((resolve) => {
|
|
90
|
+
const req = https.get('https://registry.npmjs.org/nexus-cortex/latest', { timeout: 3000 }, (res) => {
|
|
91
|
+
let body = '';
|
|
92
|
+
res.on('data', (c) => { body += c; });
|
|
93
|
+
res.on('end', () => { try { resolve(JSON.parse(body).version); } catch { resolve(null); } });
|
|
94
|
+
});
|
|
95
|
+
req.on('error', () => resolve(null));
|
|
96
|
+
req.on('timeout', () => { req.destroy(); resolve(null); });
|
|
90
97
|
});
|
|
91
|
-
|
|
92
|
-
|
|
98
|
+
} catch { return null; }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Show the notice from cache (instant, no network); refresh the cache in the background
|
|
102
|
+
// when stale — a tiny registry GET, NEVER an install. Best-effort; never blocks/throws.
|
|
103
|
+
function notifyUpdateAvailable() {
|
|
104
|
+
try {
|
|
105
|
+
if (String(process.env.CORTEX_NO_UPDATE_NOTICE).toLowerCase() === 'true') return;
|
|
106
|
+
if (!PKG_VERSION || !__cortex_dirname.includes('node_modules')) return;
|
|
107
|
+
let cache = {};
|
|
108
|
+
try { cache = JSON.parse(readFileSync(UPDATE_CACHE, 'utf8')); } catch { /* none/legacy — refresh below */ }
|
|
109
|
+
if (cache.latest && semverGt(cache.latest, PKG_VERSION)) {
|
|
110
|
+
process.stderr.write(`\n ↑ Update available: ${PKG_VERSION} → ${cache.latest} · run \`cortex --update\`\n\n`);
|
|
111
|
+
}
|
|
112
|
+
const THROTTLE = 12 * 60 * 60 * 1000;
|
|
113
|
+
if (!cache.lastCheck || Date.now() - cache.lastCheck > THROTTLE) {
|
|
114
|
+
fetchLatestVersion().then((latest) => {
|
|
115
|
+
try {
|
|
116
|
+
mkdirSync(dirname(UPDATE_CACHE), { recursive: true });
|
|
117
|
+
writeFileSync(UPDATE_CACHE, JSON.stringify({ lastCheck: Date.now(), latest: latest || cache.latest || null }));
|
|
118
|
+
} catch { /* ignore */ }
|
|
119
|
+
}).catch(() => {});
|
|
120
|
+
}
|
|
121
|
+
} catch { /* never let the notice affect the CLI */ }
|
|
93
122
|
}
|
|
94
|
-
maybeAutoUpdate();
|
|
95
123
|
|
|
96
124
|
let serverProcess = null;
|
|
97
125
|
|
|
@@ -112,6 +140,25 @@ if (args.includes('--version') || args.includes('-v')) {
|
|
|
112
140
|
process.exit(0);
|
|
113
141
|
}
|
|
114
142
|
|
|
143
|
+
// ── Self-update command ───────────────────────────────────────────
|
|
144
|
+
// `cortex --update` — update the global install on the spot, with visible npm output.
|
|
145
|
+
if (args.includes('--update')) {
|
|
146
|
+
process.stdout.write(`Updating nexus-cortex (current: ${PKG_VERSION || 'unknown'})…\n\n`);
|
|
147
|
+
const res = spawnSync('npm', ['install', '-g', 'nexus-cortex@latest'], { stdio: 'inherit' });
|
|
148
|
+
if (res.status === 0) {
|
|
149
|
+
try { mkdirSync(dirname(UPDATE_CACHE), { recursive: true }); writeFileSync(UPDATE_CACHE, JSON.stringify({ lastCheck: Date.now(), latest: null })); } catch { /* ignore */ }
|
|
150
|
+
process.stdout.write('\n✓ Updated. Run `cortex --version` to confirm.\n');
|
|
151
|
+
process.exit(0);
|
|
152
|
+
}
|
|
153
|
+
process.stderr.write('\nUpdate failed — see the npm output above. If it is a permissions error, try:\n sudo npm install -g nexus-cortex@latest\n');
|
|
154
|
+
process.exit(res.status || 1);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Update-available notice (skip for machine-readable / quiet output).
|
|
158
|
+
if (!args.includes('--json') && !args.includes('--quiet') && !args.includes('-q')) {
|
|
159
|
+
notifyUpdateAvailable();
|
|
160
|
+
}
|
|
161
|
+
|
|
115
162
|
// ── Setup wizard (interactive API-key onboarding) ─────────────────
|
|
116
163
|
// Global config lives at ~/.cortex/.env so a global npm install works from ANY
|
|
117
164
|
// folder (the server loads it). Runs on `cortex config init` and on first run
|
|
@@ -322,8 +369,8 @@ FLAGS:
|
|
|
322
369
|
--timeout MS Request timeout in ms (default: 600000 = 10 min)
|
|
323
370
|
--idle-timeout SECS Auto-shutdown server after N seconds of inactivity
|
|
324
371
|
--cwd DIR (agent) Run in DIR — the agent's file tools operate there
|
|
325
|
-
--
|
|
326
|
-
(
|
|
372
|
+
--update Update nexus-cortex to the latest version (npm i -g)
|
|
373
|
+
(a notice appears when you're behind; CORTEX_NO_UPDATE_NOTICE=true to silence)
|
|
327
374
|
--shutdown Stop the running server and exit
|
|
328
375
|
--tmux List active tmux sessions with dashboard URLs
|
|
329
376
|
--stats Show current session statistics
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexus-cortex/cli",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.31.0",
|
|
4
4
|
"description": "Nexus Cortex CLI - Terminal interface for multi-provider LLM orchestration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"prepack": "node ../../scripts/copy-pkg-cortex-scaffold.mjs"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@nexus-cortex/core": "^4.
|
|
22
|
+
"@nexus-cortex/core": "^4.31.0",
|
|
23
23
|
"chalk": "^4.1.2",
|
|
24
24
|
"cli-spinners": "^2.9.0",
|
|
25
25
|
"commander": "^11.0.0",
|