nexo-brain 7.25.5 → 7.25.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/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/crons/sync.py +42 -18
- package/src/db/_schema.py +30 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "7.25.
|
|
3
|
+
"version": "7.25.6",
|
|
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,7 @@
|
|
|
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.25.
|
|
21
|
+
Version `7.25.6` is the current packaged-runtime line. Patch release over v7.25.5 - existing Local Memory sidecar databases repair legacy root/exclusion columns before source-dependent indexes are created, and core background crons prefer the NEXO-managed Python runtime.
|
|
22
22
|
|
|
23
23
|
Previously in `7.25.4`: patch release over v7.25.3 - Local Memory starts from safe user-content and email roots, adds configurable included/excluded file types, and cleans legacy whole-disk index state with backup or archive-rebuild safety.
|
|
24
24
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexo-brain",
|
|
3
|
-
"version": "7.25.
|
|
3
|
+
"version": "7.25.6",
|
|
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",
|
package/src/crons/sync.py
CHANGED
|
@@ -150,6 +150,41 @@ RETIRED_CORE_FILES = (
|
|
|
150
150
|
)
|
|
151
151
|
|
|
152
152
|
|
|
153
|
+
def _resolve_core_python_bin() -> str:
|
|
154
|
+
"""Prefer the NEXO-managed Python for core cron execution."""
|
|
155
|
+
candidates = [
|
|
156
|
+
os.environ.get("NEXO_RUNTIME_PYTHON", ""),
|
|
157
|
+
os.environ.get("NEXO_PYTHON", ""),
|
|
158
|
+
str(RUNTIME_ROOT / ".venv" / "bin" / "python3"),
|
|
159
|
+
str(RUNTIME_ROOT / ".venv" / "bin" / "python"),
|
|
160
|
+
str(_runtime_code_dir() / ".venv" / "bin" / "python3"),
|
|
161
|
+
str(_runtime_code_dir() / ".venv" / "bin" / "python"),
|
|
162
|
+
]
|
|
163
|
+
if platform.system() == "Darwin":
|
|
164
|
+
candidates.extend(
|
|
165
|
+
[
|
|
166
|
+
"/Library/Frameworks/Python.framework/Versions/3.12/bin/python3",
|
|
167
|
+
"/opt/homebrew/bin/python3.12",
|
|
168
|
+
"/usr/local/bin/python3.12",
|
|
169
|
+
"/opt/homebrew/bin/python3",
|
|
170
|
+
"/usr/local/bin/python3",
|
|
171
|
+
"/usr/bin/python3",
|
|
172
|
+
]
|
|
173
|
+
)
|
|
174
|
+
else:
|
|
175
|
+
candidates.extend(["/usr/bin/python3", "/usr/local/bin/python3", "python3"])
|
|
176
|
+
|
|
177
|
+
for candidate in candidates:
|
|
178
|
+
if not candidate:
|
|
179
|
+
continue
|
|
180
|
+
expanded = Path(str(candidate)).expanduser()
|
|
181
|
+
if expanded.exists():
|
|
182
|
+
return str(expanded)
|
|
183
|
+
if os.sep not in str(candidate) and shutil.which(str(candidate)):
|
|
184
|
+
return str(candidate)
|
|
185
|
+
return "python3"
|
|
186
|
+
|
|
187
|
+
|
|
153
188
|
def _runtime_scripts_dir() -> Path:
|
|
154
189
|
new = RUNTIME_ROOT / "core" / "scripts"
|
|
155
190
|
legacy = RUNTIME_ROOT / "scripts"
|
|
@@ -407,21 +442,10 @@ def build_plist(cron: dict) -> dict:
|
|
|
407
442
|
if subdir_src.is_dir():
|
|
408
443
|
_copy_into_runtime(subdir_src)
|
|
409
444
|
|
|
445
|
+
python_bin = _resolve_core_python_bin()
|
|
410
446
|
if script_type == "shell":
|
|
411
447
|
program_args = ["/bin/bash", wrapper_path, cron_id, "/bin/bash", script_path]
|
|
412
448
|
else:
|
|
413
|
-
# Find python3
|
|
414
|
-
python_candidates = [
|
|
415
|
-
"/opt/homebrew/bin/python3",
|
|
416
|
-
"/usr/local/bin/python3",
|
|
417
|
-
"/Library/Frameworks/Python.framework/Versions/3.12/bin/python3",
|
|
418
|
-
"/usr/bin/python3",
|
|
419
|
-
]
|
|
420
|
-
python_bin = "python3"
|
|
421
|
-
for p in python_candidates:
|
|
422
|
-
if Path(p).exists():
|
|
423
|
-
python_bin = p
|
|
424
|
-
break
|
|
425
449
|
program_args = ["/bin/bash", wrapper_path, cron_id, python_bin, script_path]
|
|
426
450
|
|
|
427
451
|
plist = {
|
|
@@ -436,6 +460,7 @@ def build_plist(cron: dict) -> dict:
|
|
|
436
460
|
"NEXO_CODE": str(_runtime_code_dir()),
|
|
437
461
|
"NEXO_SOURCE_CODE": str(SOURCE_ROOT),
|
|
438
462
|
"NEXO_MANAGED_CORE_CRON": "1",
|
|
463
|
+
"NEXO_RUNTIME_PYTHON": python_bin,
|
|
439
464
|
"PYTHONUNBUFFERED": "1",
|
|
440
465
|
},
|
|
441
466
|
}
|
|
@@ -505,6 +530,7 @@ def _linux_crontab_entry(cron: dict, exec_cmd: str, stdout_log: Path, stderr_log
|
|
|
505
530
|
"HOME": Path.home(),
|
|
506
531
|
"NEXO_HOME": NEXO_HOME,
|
|
507
532
|
"NEXO_CODE": _runtime_code_dir(),
|
|
533
|
+
"NEXO_RUNTIME_PYTHON": _resolve_core_python_bin(),
|
|
508
534
|
"PYTHONUNBUFFERED": "1",
|
|
509
535
|
}.items()
|
|
510
536
|
)
|
|
@@ -578,12 +604,13 @@ def _sync_wsl_windows_host_local_index_task(dry_run: bool = False) -> dict:
|
|
|
578
604
|
log("WARNING: WSL_DISTRO_NAME missing; local-index host task not installed.")
|
|
579
605
|
return {"ok": False, "skipped": True, "reason": "wsl_distro_missing"}
|
|
580
606
|
|
|
581
|
-
python_bin =
|
|
607
|
+
python_bin = _resolve_core_python_bin()
|
|
582
608
|
script_path = _runtime_code_dir() / "scripts" / "nexo-local-index.py"
|
|
583
609
|
command = (
|
|
584
610
|
f"cd {shlex.quote(str(Path.home()))} && "
|
|
585
611
|
f"NEXO_HOME={shlex.quote(str(NEXO_HOME))} "
|
|
586
612
|
f"NEXO_CODE={shlex.quote(str(_runtime_code_dir()))} "
|
|
613
|
+
f"NEXO_RUNTIME_PYTHON={shlex.quote(python_bin)} "
|
|
587
614
|
f"{shlex.quote(python_bin)} {shlex.quote(str(script_path))}"
|
|
588
615
|
)
|
|
589
616
|
wsl_args = " ".join(
|
|
@@ -835,11 +862,7 @@ def sync_linux(dry_run: bool = False):
|
|
|
835
862
|
|
|
836
863
|
log(f"Manifest: {len(manifest_crons)} core crons")
|
|
837
864
|
|
|
838
|
-
python_bin =
|
|
839
|
-
for p in ["/usr/bin/python3", "/usr/local/bin/python3"]:
|
|
840
|
-
if Path(p).exists():
|
|
841
|
-
python_bin = p
|
|
842
|
-
break
|
|
865
|
+
python_bin = _resolve_core_python_bin()
|
|
843
866
|
|
|
844
867
|
enable_units: list[str] = []
|
|
845
868
|
crontab_entries: list[str] = []
|
|
@@ -878,6 +901,7 @@ Type={service_type}
|
|
|
878
901
|
ExecStart={exec_cmd}
|
|
879
902
|
Environment=NEXO_HOME={NEXO_HOME}
|
|
880
903
|
Environment=NEXO_CODE={_runtime_code_dir()}
|
|
904
|
+
Environment=NEXO_RUNTIME_PYTHON={python_bin}
|
|
881
905
|
Environment=HOME={Path.home()}
|
|
882
906
|
StandardOutput=append:{stdout_log}
|
|
883
907
|
StandardError=append:{stderr_log}
|
package/src/db/_schema.py
CHANGED
|
@@ -1767,6 +1767,7 @@ def _m62_memory_observations_fts_trigger_fix(conn):
|
|
|
1767
1767
|
|
|
1768
1768
|
def _m63_local_context_layer(conn):
|
|
1769
1769
|
"""Local Context Layer storage for on-device memory indexing."""
|
|
1770
|
+
_m63_repair_legacy_local_context_columns(conn)
|
|
1770
1771
|
conn.executescript(
|
|
1771
1772
|
"""
|
|
1772
1773
|
CREATE TABLE IF NOT EXISTS local_index_roots (
|
|
@@ -1995,6 +1996,35 @@ def _m63_local_context_layer(conn):
|
|
|
1995
1996
|
)
|
|
1996
1997
|
|
|
1997
1998
|
|
|
1999
|
+
def _table_exists(conn, table: str) -> bool:
|
|
2000
|
+
row = conn.execute(
|
|
2001
|
+
"SELECT 1 FROM sqlite_master WHERE type='table' AND name=? LIMIT 1",
|
|
2002
|
+
(table,),
|
|
2003
|
+
).fetchone()
|
|
2004
|
+
return bool(row)
|
|
2005
|
+
|
|
2006
|
+
|
|
2007
|
+
def _m63_repair_legacy_local_context_columns(conn):
|
|
2008
|
+
"""Add v2 columns before m63 creates indexes that reference them.
|
|
2009
|
+
|
|
2010
|
+
Existing sidecar DBs can already have m63-era tables without the v2
|
|
2011
|
+
columns. CREATE TABLE IF NOT EXISTS will not alter those tables, so index
|
|
2012
|
+
creation must be preceded by additive repairs.
|
|
2013
|
+
"""
|
|
2014
|
+
if _table_exists(conn, "local_index_roots"):
|
|
2015
|
+
_migrate_add_column(conn, "local_index_roots", "source", "TEXT NOT NULL DEFAULT 'legacy'")
|
|
2016
|
+
_migrate_add_column(conn, "local_index_roots", "remote", "INTEGER NOT NULL DEFAULT 0")
|
|
2017
|
+
_migrate_add_column(conn, "local_index_roots", "seed_version", "INTEGER NOT NULL DEFAULT 1")
|
|
2018
|
+
if _table_exists(conn, "local_index_exclusions"):
|
|
2019
|
+
_migrate_add_column(conn, "local_index_exclusions", "source", "TEXT NOT NULL DEFAULT 'legacy'")
|
|
2020
|
+
_migrate_add_column(conn, "local_index_exclusions", "kind", "TEXT NOT NULL DEFAULT 'folder'")
|
|
2021
|
+
if _table_exists(conn, "local_index_file_type_rules"):
|
|
2022
|
+
_migrate_add_column(conn, "local_index_file_type_rules", "source", "TEXT NOT NULL DEFAULT 'legacy'")
|
|
2023
|
+
_migrate_add_column(conn, "local_index_file_type_rules", "priority", "INTEGER NOT NULL DEFAULT 0")
|
|
2024
|
+
_migrate_add_column(conn, "local_index_file_type_rules", "reason", "TEXT NOT NULL DEFAULT ''")
|
|
2025
|
+
_migrate_add_column(conn, "local_index_file_type_rules", "updated_at", "REAL NOT NULL DEFAULT 0")
|
|
2026
|
+
|
|
2027
|
+
|
|
1998
2028
|
def _m64_local_context_live_dirs(conn):
|
|
1999
2029
|
"""Track known folders so local context can detect new/deleted/changed files quickly."""
|
|
2000
2030
|
conn.executescript(
|