nexo-brain 5.3.16 → 5.3.18

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-brain",
3
- "version": "5.3.16",
3
+ "version": "5.3.18",
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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexo-brain",
3
- "version": "5.3.16",
3
+ "version": "5.3.18",
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",
@@ -28,11 +28,30 @@ SRC_DIR = Path(__file__).resolve().parent
28
28
  NEXO_CODE = Path(os.environ.get("NEXO_CODE", str(SRC_DIR)))
29
29
  REPO_DIR = SRC_DIR.parent
30
30
 
31
+
32
+ def _resolve_repo_dir() -> Path:
33
+ """Return the source repo root, falling back to NEXO_HOME for npm installs.
34
+
35
+ On git installs SRC_DIR is ``<repo>/src`` so parent is the repo root.
36
+ On npm installs SRC_DIR *is* NEXO_HOME (``~/.nexo``) so parent is ``~``,
37
+ which has no ``templates/`` or ``migrations/``. In that case we fall back
38
+ to NEXO_HOME itself where the installer already copied the runtime files.
39
+ """
40
+ candidate = SRC_DIR.parent
41
+ if (candidate / "templates").is_dir():
42
+ return candidate
43
+ if (NEXO_HOME / "templates").is_dir():
44
+ return NEXO_HOME
45
+ return candidate
46
+
47
+
48
+ _RESOLVED_REPO_DIR = _resolve_repo_dir()
49
+
31
50
  LAST_CHECK_FILE = DATA_DIR / "auto_update_last_check.json"
32
51
  MIGRATION_VERSION_FILE = DATA_DIR / "migration_version"
33
52
  CLAUDE_MD_VERSION_FILE = DATA_DIR / "claude_md_version.txt"
34
- MIGRATIONS_DIR = REPO_DIR / "migrations"
35
- TEMPLATE_FILE = REPO_DIR / "templates" / "CLAUDE.md.template"
53
+ MIGRATIONS_DIR = _RESOLVED_REPO_DIR / "migrations"
54
+ TEMPLATE_FILE = _RESOLVED_REPO_DIR / "templates" / "CLAUDE.md.template"
36
55
 
37
56
  CHECK_COOLDOWN_SECONDS = 3600 # 1 hour
38
57
  GIT_TIMEOUT_SECONDS = 4 # stay well under the 5s total budget
@@ -1512,18 +1531,27 @@ def _auto_update_check_locked() -> dict:
1512
1531
  except Exception as e:
1513
1532
  _log(f"Doctor plugin backfill error: {e}")
1514
1533
 
1515
- # Backfill script/skill templates for existing installs
1534
+ # Backfill all templates for existing installs (no hardcoded list)
1516
1535
  try:
1517
- templates_src = REPO_DIR / "templates"
1536
+ templates_src = _RESOLVED_REPO_DIR / "templates"
1518
1537
  templates_dest = NEXO_HOME / "templates"
1519
1538
  templates_dest.mkdir(parents=True, exist_ok=True)
1520
- for fname in ("script-template.py", "nexo_helper.py", "skill-template.md", "skill-script-template.py"):
1521
- src_file = templates_src / fname
1522
- dest_file = templates_dest / fname
1523
- if src_file.is_file() and (not dest_file.exists() or src_file.stat().st_mtime > dest_file.stat().st_mtime):
1524
- import shutil
1525
- shutil.copy2(str(src_file), str(dest_file))
1526
- _log(f"Backfilled template {fname}")
1539
+ import shutil
1540
+ if templates_src.is_dir():
1541
+ for item in templates_src.iterdir():
1542
+ if item.name == "__pycache__":
1543
+ continue
1544
+ dest_item = templates_dest / item.name
1545
+ if item.is_file():
1546
+ if not dest_item.exists() or item.stat().st_mtime > dest_item.stat().st_mtime:
1547
+ shutil.copy2(str(item), str(dest_item))
1548
+ elif item.is_dir():
1549
+ dest_item.mkdir(parents=True, exist_ok=True)
1550
+ for sub in item.iterdir():
1551
+ if sub.is_file():
1552
+ dest_sub = dest_item / sub.name
1553
+ if not dest_sub.exists() or sub.stat().st_mtime > dest_sub.stat().st_mtime:
1554
+ shutil.copy2(str(sub), str(dest_sub))
1527
1555
  except Exception as e:
1528
1556
  _log(f"Template backfill error: {e}")
1529
1557
 
@@ -1560,8 +1588,8 @@ def _auto_update_check_locked() -> dict:
1560
1588
  result["git_update"] = _check_git_updates()
1561
1589
  else:
1562
1590
  # Non-git install — check npm for newer version
1563
- version_json = REPO_DIR / "version.json"
1564
- pkg_json = REPO_DIR / "package.json"
1591
+ version_json = _RESOLVED_REPO_DIR / "version.json"
1592
+ pkg_json = _RESOLVED_REPO_DIR / "package.json"
1565
1593
  if version_json.exists() or pkg_json.exists():
1566
1594
  result["npm_notice"] = _check_npm_version()
1567
1595
 
@@ -1888,8 +1916,16 @@ def _copy_runtime_from_source(src_dir: Path, repo_dir: Path, dest: Path = NEXO_H
1888
1916
  if templates_src.is_dir():
1889
1917
  templates_dest.mkdir(parents=True, exist_ok=True)
1890
1918
  for item in templates_src.iterdir():
1919
+ if item.name == "__pycache__":
1920
+ continue
1891
1921
  if item.is_file():
1892
1922
  shutil.copy2(str(item), str(templates_dest / item.name))
1923
+ elif item.is_dir():
1924
+ sub_dest = templates_dest / item.name
1925
+ sub_dest.mkdir(parents=True, exist_ok=True)
1926
+ for sub in item.iterdir():
1927
+ if sub.is_file():
1928
+ shutil.copy2(str(sub), str(sub_dest / sub.name))
1893
1929
 
1894
1930
  package_json = repo_dir / "package.json"
1895
1931
  if package_json.is_file():