nexo-brain 7.13.8 → 7.13.9
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/.claude-plugin/plugin.json +1 -1
- package/README.md +3 -1
- package/bin/nexo-brain.js +56 -11
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "7.13.
|
|
3
|
+
"version": "7.13.9",
|
|
4
4
|
"description": "Local cognitive runtime for Claude Code \u2014 persistent memory, overnight learning, doctor diagnostics, personal scripts, recovery-aware jobs, startup preflight, and optional dashboard/power helper.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "NEXO Brain",
|
package/README.md
CHANGED
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
|
|
19
19
|
[Watch the overview video](https://nexo-brain.com/watch/) · [Watch on YouTube](https://www.youtube.com/watch?v=i2lkGhKyVqI) · [Open the infographic](https://nexo-brain.com/assets/nexo-brain-infographic-v5.png)
|
|
20
20
|
|
|
21
|
-
Version `7.13.
|
|
21
|
+
Version `7.13.9` is the current packaged-runtime line. Patch release over v7.13.8 — Brain now moves aside an existing managed `.venv` when it was created with unsupported Python <3.10, then recreates it with the supported interpreter prepared by Desktop.
|
|
22
|
+
|
|
23
|
+
Previously in `7.13.8`: patch release — Brain rejects Python <3.10 during Desktop-managed fresh installs, honors the Python interpreter prepared by Desktop, and fails clearly before dependency resolution if an unsupported Apple Python 3.9 reaches the installer.
|
|
22
24
|
|
|
23
25
|
Previously in `7.13.7`: patch release — Brain adds an authenticated official protocol-card client (`nexo_card_catalog`, `nexo_card_get`, `nexo_card_match`) so agents can ask the NEXO Desktop backend for the right task protocol at runtime. The protocol corpus stays private on the server; this open-source package ships only the client, tool map, and agent guidance.
|
|
24
26
|
|
package/bin/nexo-brain.js
CHANGED
|
@@ -303,6 +303,46 @@ function pythonHasPip(pythonBin) {
|
|
|
303
303
|
}
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
+
function managedVenvPythonPath(nexoHome = NEXO_HOME) {
|
|
307
|
+
const venvPath = path.join(nexoHome, ".venv");
|
|
308
|
+
return process.platform === "win32"
|
|
309
|
+
? path.join(venvPath, "Scripts", "python.exe")
|
|
310
|
+
: path.join(venvPath, "bin", "python3");
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function safeTimestampForPath() {
|
|
314
|
+
return new Date().toISOString().replace(/[-:.TZ]/g, "").slice(0, 14);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function uniqueBackupPath(targetPath, suffix) {
|
|
318
|
+
const dir = path.dirname(targetPath);
|
|
319
|
+
const base = path.basename(targetPath);
|
|
320
|
+
const stamp = safeTimestampForPath();
|
|
321
|
+
let candidate = path.join(dir, `${base}.${suffix}-${stamp}`);
|
|
322
|
+
if (!fs.existsSync(candidate)) return candidate;
|
|
323
|
+
for (let i = 2; i < 100; i += 1) {
|
|
324
|
+
candidate = path.join(dir, `${base}.${suffix}-${stamp}-${i}`);
|
|
325
|
+
if (!fs.existsSync(candidate)) return candidate;
|
|
326
|
+
}
|
|
327
|
+
return path.join(dir, `${base}.${suffix}-${stamp}-${process.pid}`);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function ensureManagedVenvCompatible(venvPath, venvPython) {
|
|
331
|
+
if (!fs.existsSync(venvPython)) return;
|
|
332
|
+
const version = pythonVersion(venvPython);
|
|
333
|
+
if (version && pythonVersionMeetsMinimum(version)) return;
|
|
334
|
+
|
|
335
|
+
const reason = version ? `Python ${version}` : "an unreadable Python executable";
|
|
336
|
+
const backupPath = uniqueBackupPath(venvPath, "unsupported-python");
|
|
337
|
+
log(` Existing Python virtual environment uses ${reason}; moving it aside to recreate.`);
|
|
338
|
+
try {
|
|
339
|
+
fs.renameSync(venvPath, backupPath);
|
|
340
|
+
} catch (err) {
|
|
341
|
+
throw new Error(`Existing NEXO Python virtual environment is incompatible and could not be moved aside: ${err.message || err}`);
|
|
342
|
+
}
|
|
343
|
+
log(` Previous Python virtual environment moved to ${backupPath}`);
|
|
344
|
+
}
|
|
345
|
+
|
|
306
346
|
function seedPipFromBundledWheels(venvPython, bundledWheelsDir) {
|
|
307
347
|
if (!fs.existsSync(venvPython) || !fs.existsSync(bundledWheelsDir)) return false;
|
|
308
348
|
if (pythonHasPip(venvPython)) return true;
|
|
@@ -576,15 +616,13 @@ function resolveSystemPython() {
|
|
|
576
616
|
}
|
|
577
617
|
|
|
578
618
|
function ensureWarmupPython(nexoHome = NEXO_HOME) {
|
|
579
|
-
const existing = findVenvPython(nexoHome);
|
|
580
|
-
if (existing) return existing;
|
|
581
|
-
|
|
582
|
-
const basePython = resolveSystemPython();
|
|
583
619
|
const venvPath = path.join(nexoHome, ".venv");
|
|
584
|
-
const venvPython =
|
|
585
|
-
? path.join(venvPath, "Scripts", "python.exe")
|
|
586
|
-
: path.join(venvPath, "bin", "python3");
|
|
620
|
+
const venvPython = managedVenvPythonPath(nexoHome);
|
|
587
621
|
fs.mkdirSync(nexoHome, { recursive: true });
|
|
622
|
+
ensureManagedVenvCompatible(venvPath, venvPython);
|
|
623
|
+
if (fs.existsSync(venvPython)) return venvPython;
|
|
624
|
+
|
|
625
|
+
const basePython = resolveInstallerPython() || resolveSystemPython();
|
|
588
626
|
if (!fs.existsSync(venvPython)) {
|
|
589
627
|
log(" Creating Python virtual environment for model warmup...");
|
|
590
628
|
const result = spawnSync(basePython, ["-m", "venv", venvPath], { stdio: "inherit", timeout: 120000 });
|
|
@@ -2398,7 +2436,7 @@ async function maybeConfigurePublicContribution(schedule, useDefaults) {
|
|
|
2398
2436
|
* Resolve the venv python path for an existing NEXO_HOME installation.
|
|
2399
2437
|
*/
|
|
2400
2438
|
function findVenvPython(nexoHome) {
|
|
2401
|
-
const venvPy =
|
|
2439
|
+
const venvPy = managedVenvPythonPath(nexoHome);
|
|
2402
2440
|
if (fs.existsSync(venvPy)) return venvPy;
|
|
2403
2441
|
return null;
|
|
2404
2442
|
}
|
|
@@ -3702,11 +3740,11 @@ async function runSetup() {
|
|
|
3702
3740
|
log("Installing cognitive engine dependencies...");
|
|
3703
3741
|
fs.mkdirSync(NEXO_HOME, { recursive: true });
|
|
3704
3742
|
const venvPath = path.join(NEXO_HOME, ".venv");
|
|
3705
|
-
const venvPython =
|
|
3706
|
-
? path.join(venvPath, "Scripts", "python.exe")
|
|
3707
|
-
: path.join(venvPath, "bin", "python3");
|
|
3743
|
+
const venvPython = managedVenvPythonPath(NEXO_HOME);
|
|
3708
3744
|
const bundledWheelsDir = path.join(__dirname, "..", "python-wheels");
|
|
3709
3745
|
|
|
3746
|
+
ensureManagedVenvCompatible(venvPath, venvPython);
|
|
3747
|
+
|
|
3710
3748
|
// Create venv if it doesn't exist
|
|
3711
3749
|
if (!fs.existsSync(venvPython)) {
|
|
3712
3750
|
log(" Creating Python virtual environment...");
|
|
@@ -3724,6 +3762,13 @@ async function runSetup() {
|
|
|
3724
3762
|
}
|
|
3725
3763
|
}
|
|
3726
3764
|
}
|
|
3765
|
+
if (fs.existsSync(venvPython)) {
|
|
3766
|
+
const venvVersion = pythonVersion(venvPython);
|
|
3767
|
+
if (!venvVersion || !pythonVersionMeetsMinimum(venvVersion)) {
|
|
3768
|
+
log(`Python virtual environment is unsupported after creation (${venvVersion || "unknown version"}).`);
|
|
3769
|
+
process.exit(1);
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3727
3772
|
if (fs.existsSync(venvPython) && !pythonHasPip(venvPython)) {
|
|
3728
3773
|
seedPipFromBundledWheels(venvPython, bundledWheelsDir);
|
|
3729
3774
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "7.13.
|
|
3
|
+
"version": "7.13.9",
|
|
4
4
|
"mcpName": "io.github.wazionapps/nexo",
|
|
5
5
|
"description": "NEXO Brain — Shared brain for AI agents. Persistent memory, semantic RAG, natural forgetting, metacognitive guard, trust scoring, 150+ MCP tools. Works with Claude Code, Codex, Claude Desktop & any MCP client. 100% local, free.",
|
|
6
6
|
"homepage": "https://nexo-brain.com",
|